From 7954c7a4bdbf73baa7fb15fbabf90937e1c6f6f0 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Thu, 8 Aug 2013 09:49:56 +0000 Subject: WinPopup moved to NotAdopted coz don't work git-svn-id: http://svn.miranda-ng.org/main/trunk@5626 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- .../WinPopup/docs/winpopup_proto_readme.txt | 245 ++++ .../WinPopup/docs/winpopup_proto_todo.txt | 9 + .../WinPopup/docs/winpopup_proto_translation.txt | 43 + plugins/!NotAdopted/WinPopup/res/add.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/away.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/bad_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/bad_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/computer.ico | Bin 0 -> 1406 bytes .../!NotAdopted/WinPopup/res/computer_error.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/dnd.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/explore.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/freechat.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/good_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/good_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/invisible.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/lana.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/na.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/occupied.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/offline.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/online.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/onthephone.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/other_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/other_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/res/outtolunch.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/res/overlay/away.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/res/overlay/dnd.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/res/overlay/freechat.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/res/overlay/invisible.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/res/overlay/na.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/res/overlay/occupied.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/res/overlay/onphone.ico | Bin 0 -> 1150 bytes .../WinPopup/res/overlay/outtolunch.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/res/winpopup_proto.ico | Bin 0 -> 9062 bytes plugins/!NotAdopted/WinPopup/res/winpopup_proto.rc | 212 ++++ plugins/!NotAdopted/WinPopup/src/add_dialog.cpp | 66 ++ plugins/!NotAdopted/WinPopup/src/add_dialog.h | 23 + plugins/!NotAdopted/WinPopup/src/chat.cpp | 329 ++++++ plugins/!NotAdopted/WinPopup/src/chat.h | 42 + .../!NotAdopted/WinPopup/src/dllLoaderMinimal.h | 338 ++++++ plugins/!NotAdopted/WinPopup/src/mailslot.cpp | 304 +++++ plugins/!NotAdopted/WinPopup/src/mailslot.h | 46 + plugins/!NotAdopted/WinPopup/src/md5.h | 220 ++++ plugins/!NotAdopted/WinPopup/src/messagebox.cpp | 223 ++++ plugins/!NotAdopted/WinPopup/src/messagebox.h | 27 + plugins/!NotAdopted/WinPopup/src/messenger.cpp | 458 ++++++++ plugins/!NotAdopted/WinPopup/src/messenger.h | 52 + plugins/!NotAdopted/WinPopup/src/netbios.cpp | 1055 +++++++++++++++++ plugins/!NotAdopted/WinPopup/src/netbios.h | 130 +++ plugins/!NotAdopted/WinPopup/src/netbios_name.cpp | 630 +++++++++++ plugins/!NotAdopted/WinPopup/src/netbios_name.h | 155 +++ plugins/!NotAdopted/WinPopup/src/network.cpp | 81 ++ plugins/!NotAdopted/WinPopup/src/network.h | 29 + plugins/!NotAdopted/WinPopup/src/options.cpp | 381 +++++++ plugins/!NotAdopted/WinPopup/src/options.h | 22 + plugins/!NotAdopted/WinPopup/src/processapi.cpp | 571 ++++++++++ plugins/!NotAdopted/WinPopup/src/processapi.h | 258 +++++ plugins/!NotAdopted/WinPopup/src/resource.h | 66 ++ plugins/!NotAdopted/WinPopup/src/scanner.cpp | 208 ++++ plugins/!NotAdopted/WinPopup/src/scanner.h | 47 + plugins/!NotAdopted/WinPopup/src/search.cpp | 317 ++++++ plugins/!NotAdopted/WinPopup/src/search.h | 58 + plugins/!NotAdopted/WinPopup/src/services.cpp | 879 ++++++++++++++ plugins/!NotAdopted/WinPopup/src/services.h | 34 + plugins/!NotAdopted/WinPopup/src/smbconst.h | 106 ++ plugins/!NotAdopted/WinPopup/src/stdafx.cpp | 22 + plugins/!NotAdopted/WinPopup/src/stdafx.h | 122 ++ plugins/!NotAdopted/WinPopup/src/user_info.cpp | 325 ++++++ plugins/!NotAdopted/WinPopup/src/user_info.h | 22 + .../!NotAdopted/WinPopup/src/winpopup_proto.cpp | 1193 ++++++++++++++++++++ plugins/!NotAdopted/WinPopup/src/winpopup_proto.h | 318 ++++++ .../!NotAdopted/WinPopup/winpopup_proto_11.vcxproj | 239 ++++ .../WinPopup/winpopup_proto_11.vcxproj.filters | 134 +++ 72 files changed, 10039 insertions(+) create mode 100644 plugins/!NotAdopted/WinPopup/docs/winpopup_proto_readme.txt create mode 100644 plugins/!NotAdopted/WinPopup/docs/winpopup_proto_todo.txt create mode 100644 plugins/!NotAdopted/WinPopup/docs/winpopup_proto_translation.txt create mode 100644 plugins/!NotAdopted/WinPopup/res/add.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/bad_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/bad_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/computer.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/computer_error.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/explore.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/good_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/good_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/lana.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/offline.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/online.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/onthephone.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/other_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/other_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/onphone.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/overlay/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/winpopup_proto.ico create mode 100644 plugins/!NotAdopted/WinPopup/res/winpopup_proto.rc create mode 100644 plugins/!NotAdopted/WinPopup/src/add_dialog.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/add_dialog.h create mode 100644 plugins/!NotAdopted/WinPopup/src/chat.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/chat.h create mode 100644 plugins/!NotAdopted/WinPopup/src/dllLoaderMinimal.h create mode 100644 plugins/!NotAdopted/WinPopup/src/mailslot.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/mailslot.h create mode 100644 plugins/!NotAdopted/WinPopup/src/md5.h create mode 100644 plugins/!NotAdopted/WinPopup/src/messagebox.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/messagebox.h create mode 100644 plugins/!NotAdopted/WinPopup/src/messenger.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/messenger.h create mode 100644 plugins/!NotAdopted/WinPopup/src/netbios.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/netbios.h create mode 100644 plugins/!NotAdopted/WinPopup/src/netbios_name.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/netbios_name.h create mode 100644 plugins/!NotAdopted/WinPopup/src/network.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/network.h create mode 100644 plugins/!NotAdopted/WinPopup/src/options.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/options.h create mode 100644 plugins/!NotAdopted/WinPopup/src/processapi.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/processapi.h create mode 100644 plugins/!NotAdopted/WinPopup/src/resource.h create mode 100644 plugins/!NotAdopted/WinPopup/src/scanner.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/scanner.h create mode 100644 plugins/!NotAdopted/WinPopup/src/search.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/search.h create mode 100644 plugins/!NotAdopted/WinPopup/src/services.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/services.h create mode 100644 plugins/!NotAdopted/WinPopup/src/smbconst.h create mode 100644 plugins/!NotAdopted/WinPopup/src/stdafx.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/stdafx.h create mode 100644 plugins/!NotAdopted/WinPopup/src/user_info.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/user_info.h create mode 100644 plugins/!NotAdopted/WinPopup/src/winpopup_proto.cpp create mode 100644 plugins/!NotAdopted/WinPopup/src/winpopup_proto.h create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj.filters (limited to 'plugins/!NotAdopted') diff --git a/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_readme.txt b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_readme.txt new file mode 100644 index 0000000000..d4dfb8bd9b --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_readme.txt @@ -0,0 +1,245 @@ +WinPopup Protocol plugin for Miranda IM + +Copyright (C) 2004-2011 Nikolay Raspopov +mailto: ryo-oh-ki[at]narod[dot]ru +http://www.cherubicsoft.com/miranda/ + +Communicate with users over LAN, compatible with "net send", WinPopup, +VikPoup, RealPopup, Netter and Miranda`s net_send_protocol, mNetSend plugins. +Uses Mailslot, NetBIOS and Messenger service for sending and receiving messages. + +System requirements: + + Network with NetBIOS over TCP/IP enabled + + for 0.0.0.17 + Miranda IM 0.5.2.x + Windows 95,98,ME,NT. + + for 0.0.0.18 + Miranda IM 0.7.x.x + Windows 2000,XP,2003,Vista,7. + +Notes: + + Search supports wildcards (case insensitive): + ? - any single symbol, + * - any number of symbols including zero, + # - any digital symbol, + [abcd] - symbol set, + [a-z] - sumbol range, + [!...] - NOT in symbol set or range. + + How to send group messages: + 1) Open plugin options page; + 2) Check "Use Mailslot when sending" option; + 3) Press "Add Contact..." button; + 4) Type domain/workgroup name or * for everybody and check "Group contact" option; + 5) Send messge using newly created contact. + + You got "Access Denied" error when switching to online: + Try to check "Use Messenger service when sending and receiving" option + in plugin options. + + "Legacy online status detection" option: + Detection online status by <00> NetBIOS-name also, + normally status detected by <03> NetBIOS-name (aka Messenger). + +Installation: + + 1) Close similar applications - WinPopup, VikPopup, RealPopup, HiBuddy, NetHail, + NetSend, Netter, OfficePopup, LanTalk XP etc. + 2) Disable similar Miranda IM plugins - net_send_protocol, mNetSend. + 3) Unzip winpopup_proto.dll to ..Miranda IM\Plugin\ folder. + 4) Restart Miranda IM. + +Files: + + winpopup_proto.dll - WinPopup Protocol Plugin + winpopup_proto_readme.txt - This file + winpopup_proto_translation.txt - Translation template for language pack authors only + +History: + + Old versions available at: http://www.cherubicsoft.com/miranda/ + + 0.0.0.19 + - Tweaked NetBIOS time-outs + - More NetBIOS debug messages + - Fixed sending over NetBIOS + + 0.0.0.18 + - Headers updated up to Miranda IM 0.9 + - Added Unicode support + - Added 64-bit support + - Added avatar support + - Added group contact support + - Performance optimizations + - Added support for NetLib log + - Fixed crash at miranda exit when contact still scanning + - Fixed resource leaks (icons) + - Fixed small memory leaks by replacing internal ForkThread() with Miranda mir_forkthread() + - Fixed contact status detection when "Always Online" option set + - Fixed extra requests of contact status retrieving + - Fixed contact away message requesting + - Fixed potential security problems + - Reduced miranda exit time + - Changed system requirements (removed Win9x/NT support, added Vista/7 support) + - Project upgraded up to VS 2008 + + 0.0.0.17 + - Headers updated up to Miranda IM 0.8 + - Added main menu + - Added "Legacy online status detection" option (by Anatoliy Samara) + + 0.0.0.16 + - Headers updated up to Miranda IM 0.6 and plugin's sources were commented + - Added support for non-latin (OEM) user/computer names + - Added "Always Online" checkbox to contact's options + - Added mNetSend contact's status support + - Added "Free for chat" and "Invisible" statuses + - Now Messenger service can be started even from disabled state (Administrators only) + - Contact status check delay reduced from 60 to 30 seconds + - Fixed plugin hangup is some cases during Miranda shutdown on Win9x + - Updated translation file + + 0.0.0.15 + - Fixed duplicated NetBIOS-names of options page + - Fixed non-Messenger dialogs stealing + - Fixed false NetBIOS error 13 when computer and user names are equal + - Fixed false Access Denied error when unprivileged user starts Miranda IM and + Messenger service already stopped or started + - Fixed incompatibility with WinNT 4.0 (since 0.0.0.14) + - Fixed empty NetBIOS names registration (some rare plugins combinations) + - Changed infinite message popups timeout to 10 second timeout + - Added message boxes with timeouts (used when Popup plugin is absent) + - Added item "Explore" of contacts menu + - Added NetBIOS names registration separate selection + - Added automatic applying (switching to offline/online) of changed options + - Added remote computer comment field to user info + - Updated translation file + + 0.0.0.14 + - Added full implementation of "Messenger sevice" mode + - Added enhanced network error messages + - Added support for Popup plugin + - Fixed unexpected long timeout of contact online status scanning + - Fixed missed Translate() calls + - Fixed worker threads handling (more robust way, like Miranda IM itself) + - Updated translation file + - Some minor fixes + + 0.0.0.13 + - System requirements lowered to Win95 + - ICMP CODS (contact online detection system :) replaced by NetBIOS CODS + - Fixed empty message appearance when unsupported type of SMB-packet recieved + (by Andrew O. Shadoura) + - Fixed "missed names" in NetBIOS reciever + - Fixed "connecting 2" plugin status (now "offline") + - Added NetBIOS method of sending + - Added NetMessageBufferSend method of sending + (WinNT + started Messenger service) + - Added "patient" NetBIOS-names deregistration routines + - Added search cancellation capabilities + - Added page with NetBIOS information to User Info dialog + - Added "NetBIOS names registration status" to Options dialog + - Added support for Updater plugin + (http://addons.miranda-im.org/details.php?action=viewfile&id=2254) + - Updated translation file + - Some minor fixes + + 0.0.0.12 + - Version fix + + 0.0.0.11 + - Fixed crash after Miranda exit (DestroyServiceFunction bug) + - Persistent protocol status icons changed to customized + + 0.0.0.10 + - Fixed crash if invalid computer name consists of upper ASCII table symbols + (russian symbols, germany umlauts etc.) in CharUpper WinAPI32 function + - Fixed incorrect IP resolving if invalid computer name begins with digital + - Fixed forgotten "unpingable" contacts (by Andrey anl_public3[at]mail.ru) + - Fixed 100% CPU usage if network connection was lost (now switching to offline) + - Added simple NetBIOS-names lookup + - Allowed contacts with unknown IP (user responsibility) + - Updated translation file + + 0.0.0.9 + - Now searching for computer names, comments or workgroups (using wildcards) + - Added protection vs mailslot BO-attack + - Added duplicate message filtering + - Some small NetBIOS fixes + - Removed 256 chars message limitation (doh!) + - Fixed big message (> 424 bytes) handling error + + 0.0.0.8 + - Fixed unexpected locking inside Win32 API function ReadFile when + reading from mailslot created with MAILSLOT_WAIT_FOREVER flag under Win98 + (MAILSLOT_WAIT_FOREVER replaced with 2000 ms timeout) + - Added big message splitting (424 bytes parts) + - Added send message throttle (1000 ms) to preventing receivers mailslot overloading + - Added direct contact addition (inside Options page) by name or IP + - Added "RealIP" (equal "IP") and "About" (computer comment) settings to contact + - Changed translation file + + 0.0.0.7 + - Added options page + - Added "Connecting" status (more smoother startup and shutdown) + - Added translation template file + - Added self message recognition + - Added message CR-LF-B6 normalization + - Added uninstaller support (PluginUninstaller 1.1.2.1) + - Some titles renamed from "WinPopup Protocol" to "WinPopup" + - Extended error messages + - Project updated up to Visual Studio .NET 2003 + - Project refactored (STL to ATL -> file size changed from 112Kb to 72Kb) + + 0.0.0.6 + - Fixed "Unknown Contact" in some poor interface plugins + - Added persistent protocol status icons + + 0.0.0.5 + - Added "IP" setting to contacts (good for some plugins) + - Optimized ping detection routine + - Optimized LAN names search routine (now multithreaded, NetBIOS search not yet implemented) + - Optimized message sender (now multithreaded) + - Added NetBIOS message receiver + - Fixed Stop/Restart Windows Messenger Service routine + + 0.0.0.4 + - Added experimental support for NetBIOS name registration (computer, current user, nick) + - Added restoring Microsoft Network Messenger after closing Miranda IM + - Fixed false contact status detection (was bug in ping functions) + + 0.0.0.3 + - Plugin file renamed to winpopup_proto.dll + - Fixed tiny memory leak in ReceiveMessage function + - Added online/offline status checker + - Added auto-answer + - Added support for extended statuses (away, na, dnd, etc.) + - Added Miranda-aware safe threads handling + - Fixed hidden contact of first message + + 0.0.0.2 + - Fixed tiny memory leak in SendMsg function + - Mailslot-receiver thread code refactored + + 0.0.0.1 + - Released first version + +License: + + 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. diff --git a/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_todo.txt b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_todo.txt new file mode 100644 index 0000000000..98409ccb7a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_todo.txt @@ -0,0 +1,9 @@ +; this is a WinPopup Protocol plugin TODO list (russian) + +- Ввести кеширование поиска по сети (сбор имен все время?) +- Ввести контакты на пользователя, а не на компьютер +- Попробовать реализовать смену ника отправителя +- Добавить поиск по IP +- Ввести сравку и/или поддержку тултипов +- Доделать в коде класса mailslot определение конфликтных процессов + (найти способ определения процесса - владельца мейлслота) diff --git a/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_translation.txt b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_translation.txt new file mode 100644 index 0000000000..d8e26340ee --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/docs/winpopup_proto_translation.txt @@ -0,0 +1,43 @@ +; this is a template for translation of WinPopup Protocol plugin +; last updated 25 Feb 2010 for 0.0.0.18 + +[Add contact...] +[Always Online] +[Auto-reply] +[Auto-reply to users with your status message while away] +[Cancel] +[Cannot send message] +[Cannot create receiving mailslot] +[Cannot operate Messenger service] +[Cannot register NetBIOS name] +[Cannot resolve contacts IP-address. Add it anyway?] +[Cannot start Messenger service] +[Cannot stop Messenger service] +[Computer,User,Group] +[Comment:] +[Error] +[Explore] +[Failed names] +[Filter Duplicate Messages (RECOMMENDED)] +[Group contact] +[LAN adapter] +[Legacy online status detection] +[NetBIOS names:] +[NetBIOS names registration] +[Network] +[Nick] +[No progress] +[OK] +[Offline] +[Options] +[Other names] +[Please shutdown any other IM applications and/or Messenger service] +[Plugins] +[Retrieving...] +[Successful names] +[Status:] +[Unexpected service status change] +[Use Mailslot when sending (RECOMMENDED)] +[Use NetBIOS when sending] +[Use Messenger service when sending and receiving] +[Username] diff --git a/plugins/!NotAdopted/WinPopup/res/add.ico b/plugins/!NotAdopted/WinPopup/res/add.ico new file mode 100644 index 0000000000..2b407bd899 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/add.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/away.ico b/plugins/!NotAdopted/WinPopup/res/away.ico new file mode 100644 index 0000000000..fd4fc06d27 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/bad_name.ico b/plugins/!NotAdopted/WinPopup/res/bad_name.ico new file mode 100644 index 0000000000..d90e82cf30 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/bad_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/bad_names.ico b/plugins/!NotAdopted/WinPopup/res/bad_names.ico new file mode 100644 index 0000000000..939dcffcb1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/bad_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/computer.ico b/plugins/!NotAdopted/WinPopup/res/computer.ico new file mode 100644 index 0000000000..70e0c09112 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/computer.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/computer_error.ico b/plugins/!NotAdopted/WinPopup/res/computer_error.ico new file mode 100644 index 0000000000..380ed3d9f1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/computer_error.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/dnd.ico b/plugins/!NotAdopted/WinPopup/res/dnd.ico new file mode 100644 index 0000000000..3cc44e4a98 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/explore.ico b/plugins/!NotAdopted/WinPopup/res/explore.ico new file mode 100644 index 0000000000..0e26c97f10 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/explore.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/freechat.ico b/plugins/!NotAdopted/WinPopup/res/freechat.ico new file mode 100644 index 0000000000..730bbe436a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/good_name.ico b/plugins/!NotAdopted/WinPopup/res/good_name.ico new file mode 100644 index 0000000000..86aaef9d46 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/good_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/good_names.ico b/plugins/!NotAdopted/WinPopup/res/good_names.ico new file mode 100644 index 0000000000..37fc97841f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/good_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/invisible.ico b/plugins/!NotAdopted/WinPopup/res/invisible.ico new file mode 100644 index 0000000000..2c5378e70c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/lana.ico b/plugins/!NotAdopted/WinPopup/res/lana.ico new file mode 100644 index 0000000000..d753509117 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/lana.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/na.ico b/plugins/!NotAdopted/WinPopup/res/na.ico new file mode 100644 index 0000000000..e9cffaf26f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/occupied.ico b/plugins/!NotAdopted/WinPopup/res/occupied.ico new file mode 100644 index 0000000000..2abca3db31 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/offline.ico b/plugins/!NotAdopted/WinPopup/res/offline.ico new file mode 100644 index 0000000000..a94a20319a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/offline.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/online.ico b/plugins/!NotAdopted/WinPopup/res/online.ico new file mode 100644 index 0000000000..8bd53fe6f7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/online.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/onthephone.ico b/plugins/!NotAdopted/WinPopup/res/onthephone.ico new file mode 100644 index 0000000000..5f88fdbc48 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/onthephone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/other_name.ico b/plugins/!NotAdopted/WinPopup/res/other_name.ico new file mode 100644 index 0000000000..b46b632318 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/other_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/other_names.ico b/plugins/!NotAdopted/WinPopup/res/other_names.ico new file mode 100644 index 0000000000..c5eb01ad5c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/other_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/outtolunch.ico b/plugins/!NotAdopted/WinPopup/res/outtolunch.ico new file mode 100644 index 0000000000..9b144d1eea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/away.ico b/plugins/!NotAdopted/WinPopup/res/overlay/away.ico new file mode 100644 index 0000000000..4c6928082d Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/dnd.ico b/plugins/!NotAdopted/WinPopup/res/overlay/dnd.ico new file mode 100644 index 0000000000..778689c234 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/freechat.ico b/plugins/!NotAdopted/WinPopup/res/overlay/freechat.ico new file mode 100644 index 0000000000..58a04c226e Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/invisible.ico b/plugins/!NotAdopted/WinPopup/res/overlay/invisible.ico new file mode 100644 index 0000000000..9775d6deea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/na.ico b/plugins/!NotAdopted/WinPopup/res/overlay/na.ico new file mode 100644 index 0000000000..8ffa02a346 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/occupied.ico b/plugins/!NotAdopted/WinPopup/res/overlay/occupied.ico new file mode 100644 index 0000000000..290f2b4ef7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/onphone.ico b/plugins/!NotAdopted/WinPopup/res/overlay/onphone.ico new file mode 100644 index 0000000000..9dda2ec2ae Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/onphone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/overlay/outtolunch.ico b/plugins/!NotAdopted/WinPopup/res/overlay/outtolunch.ico new file mode 100644 index 0000000000..d357c23da1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/overlay/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/winpopup_proto.ico b/plugins/!NotAdopted/WinPopup/res/winpopup_proto.ico new file mode 100644 index 0000000000..6ee65927cf Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/res/winpopup_proto.ico differ diff --git a/plugins/!NotAdopted/WinPopup/res/winpopup_proto.rc b/plugins/!NotAdopted/WinPopup/res/winpopup_proto.rc new file mode 100644 index 0000000000..150235a040 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/res/winpopup_proto.rc @@ -0,0 +1,212 @@ +// Microsoft Visual C++ generated resource script. +// +#include "..\src\resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_WINPOPUP ICON "winpopup_proto.ico" +IDI_ONLINE ICON "online.ico" +IDI_OFFLINE ICON "offline.ico" +IDI_AWAY ICON "away.ico" +IDI_FREECHAT ICON "freechat.ico" +IDI_INVISIBLE ICON "invisible.ico" +IDI_NA ICON "na.ico" +IDI_DND ICON "dnd.ico" +IDI_OCCUPIED ICON "occupied.ico" +IDI_ONTHEPHONE ICON "onthephone.ico" +IDI_OUTTOLUNCH ICON "outtolunch.ico" +IDI_LANA ICON "lana.ico" +IDI_COMPUTER ICON "computer.ico" +IDI_GOOD_NAME ICON "good_name.ico" +IDI_BAD_NAME ICON "bad_name.ico" +IDI_OTHER_NAME ICON "other_name.ico" +IDI_OTHER_NAMES ICON "other_names.ico" +IDI_BAD_NAMES ICON "bad_names.ico" +IDI_GOOD_NAMES ICON "good_names.ico" +IDI_EXPLORE ICON "explore.ico" +IDI_COMPUTER_ERROR ICON "computer_error.ico" +IDI_ADD_COMPUTER ICON "add.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPTIONS DIALOGEX 0, 0, 306, 229 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Auto-reply to users with your status message while away",IDC_AUTOANSWER, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,10,291,10 + CONTROL "Filter Duplicate Messages (RECOMMENDED)",IDC_DUPS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,20,291,10 + CONTROL "Use Mailslot when sending (RECOMMENDED)",IDC_USE_MAILSLOT, + "Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,7,30,291,10 + CONTROL "Use NetBIOS when sending",IDC_USE_NETBIOS,"Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,40,291,10 + CONTROL "Use Messenger service when sending and receiving",IDC_USE_NETSEND, + "Button",BS_AUTORADIOBUTTON | WS_TABSTOP,7,50,291,10 + CONTROL "Nick",IDC_CHECK_NICK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,85,80,10 + EDITTEXT IDC_NICK1,93,84,100,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + CONTROL "Username",IDC_CHECK_USER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,101,80,10 + EDITTEXT IDC_USER,93,100,100,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + EDITTEXT IDC_NICK2,198,84,100,12,ES_AUTOHSCROLL | ES_READONLY | NOT WS_TABSTOP + CONTROL "",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_DISABLEDRAGDROP | WS_BORDER | WS_TABSTOP,7,128,141,73 + PUSHBUTTON "Add contact...",IDC_ADD,0,215,73,14 + GROUPBOX "NetBIOS names registration",IDC_STATIC,0,73,305,136 + ICON "",IDC_LEGEND_1,154,128,20,20 + LTEXT "Successful names",IDC_STATIC,181,128,117,8 + ICON "",IDC_LEGEND_2,154,142,20,20 + LTEXT "Failed names",IDC_STATIC,181,142,117,8 + ICON "",IDC_LEGEND_3,154,155,20,20 + LTEXT "Other names",IDC_STATIC,181,155,117,8 + ICON "",IDC_LEGEND_4,166,128,20,20 + ICON "",IDC_LEGEND_5,166,142,20,20 + ICON "",IDC_LEGEND_6,166,155,20,20 + GROUPBOX "Options",IDC_STATIC,0,0,305,72 + LTEXT "Status:",IDC_STATIC,7,117,24,8 + CONTROL "Legacy online status detection",IDC_ALWAYSCHECK00FORONLINE, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,60,291,10 +END + +IDD_ADD DIALOGEX 0, 0, 186, 46 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add contact..." +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + EDITTEXT IDC_NAME,7,7,115,14,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,129,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,25,50,14 + CONTROL "Group contact",IDC_GROUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,29,61,10 +END + +IDD_USERINFO DIALOGEX 0, 0, 222, 132 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_DISABLEDRAGDROP | WS_BORDER | WS_HSCROLL | WS_TABSTOP,5,14,125,82 + CONTROL "Always Online",IDC_ONLINE_CHECK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,32,82,24 + EDITTEXT IDC_ABOUT,5,107,125,20,ES_AUTOHSCROLL | ES_READONLY + LTEXT "NetBIOS names:",IDC_STATIC,5,5,125,8 + LTEXT "Comment:",IDC_STATIC,5,97,125,8 + CONTROL "Legacy online status detection",IDC_CHECK00FORONLINE, + "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,135,5,82,24 + CONTROL "Group contact",IDC_GROUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,59,82,24 +END + +IDD_CREATE DIALOGEX 0, 0, 186, 134 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPTIONS, DIALOG + BEGIN + VERTGUIDE, 7 + VERTGUIDE, 87 + VERTGUIDE, 93 + VERTGUIDE, 148 + VERTGUIDE, 154 + VERTGUIDE, 193 + VERTGUIDE, 198 + VERTGUIDE, 298 + HORZGUIDE, 10 + HORZGUIDE, 26 + HORZGUIDE, 121 + HORZGUIDE, 136 + HORZGUIDE, 149 + END + + IDD_ADD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 39 + END + + IDD_USERINFO, DIALOG + BEGIN + LEFTMARGIN, 5 + RIGHTMARGIN, 217 + VERTGUIDE, 135 + TOPMARGIN, 5 + BOTTOMMARGIN, 127 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/!NotAdopted/WinPopup/src/add_dialog.cpp b/plugins/!NotAdopted/WinPopup/src/add_dialog.cpp new file mode 100644 index 0000000000..2caa171835 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/add_dialog.cpp @@ -0,0 +1,66 @@ +/* + +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" + +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/src/add_dialog.h b/plugins/!NotAdopted/WinPopup/src/add_dialog.h new file mode 100644 index 0000000000..4b42136f9f --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/add_dialog.h @@ -0,0 +1,23 @@ +/* + +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. +*/ + +// / +void AddDialog(HWND hParentWnd); diff --git a/plugins/!NotAdopted/WinPopup/src/chat.cpp b/plugins/!NotAdopted/WinPopup/src/chat.cpp new file mode 100644 index 0000000000..00ffd10b41 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/chat.cpp @@ -0,0 +1,329 @@ +/* + +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" + +#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/src/chat.h b/plugins/!NotAdopted/WinPopup/src/chat.h new file mode 100644 index 0000000000..41c6fd6476 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/chat.h @@ -0,0 +1,42 @@ +/* + +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. +*/ + +#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/src/dllLoaderMinimal.h b/plugins/!NotAdopted/WinPopup/src/dllLoaderMinimal.h new file mode 100644 index 0000000000..218a5a114c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/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/src/mailslot.cpp b/plugins/!NotAdopted/WinPopup/src/mailslot.cpp new file mode 100644 index 0000000000..f632872d36 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/mailslot.cpp @@ -0,0 +1,304 @@ +/* + +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" + +#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/src/mailslot.h b/plugins/!NotAdopted/WinPopup/src/mailslot.h new file mode 100644 index 0000000000..363ac6df3e --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/mailslot.h @@ -0,0 +1,46 @@ +/* + +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. +*/ + +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/src/md5.h b/plugins/!NotAdopted/WinPopup/src/md5.h new file mode 100644 index 0000000000..b8c5ad5735 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/md5.h @@ -0,0 +1,220 @@ +/* + +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. +*/ + +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/src/messagebox.cpp b/plugins/!NotAdopted/WinPopup/src/messagebox.cpp new file mode 100644 index 0000000000..80ddd5471a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/messagebox.cpp @@ -0,0 +1,223 @@ +/* + +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" + +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/src/messagebox.h b/plugins/!NotAdopted/WinPopup/src/messagebox.h new file mode 100644 index 0000000000..182b40483a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/messagebox.h @@ -0,0 +1,27 @@ +/* + +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. +*/ + +// +// 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/src/messenger.cpp b/plugins/!NotAdopted/WinPopup/src/messenger.cpp new file mode 100644 index 0000000000..51df7b2beb --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/messenger.cpp @@ -0,0 +1,458 @@ +/* + +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" + +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/src/messenger.h b/plugins/!NotAdopted/WinPopup/src/messenger.h new file mode 100644 index 0000000000..fe028b2657 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/messenger.h @@ -0,0 +1,52 @@ +/* + +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. +*/ + +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/src/netbios.cpp b/plugins/!NotAdopted/WinPopup/src/netbios.cpp new file mode 100644 index 0000000000..2a1c5a4f68 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/netbios.cpp @@ -0,0 +1,1055 @@ +/* + +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" + +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 = 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/src/netbios.h b/plugins/!NotAdopted/WinPopup/src/netbios.h new file mode 100644 index 0000000000..9b5634c42a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/netbios.h @@ -0,0 +1,130 @@ +/* + +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. +*/ + +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/src/netbios_name.cpp b/plugins/!NotAdopted/WinPopup/src/netbios_name.cpp new file mode 100644 index 0000000000..befffb04e5 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/netbios_name.cpp @@ -0,0 +1,630 @@ +/* + +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" + +//////////////////////////////////////////////////////////////////////// +// 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/src/netbios_name.h b/plugins/!NotAdopted/WinPopup/src/netbios_name.h new file mode 100644 index 0000000000..c273082be9 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/netbios_name.h @@ -0,0 +1,155 @@ +/* + +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. +*/ + +#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/src/network.cpp b/plugins/!NotAdopted/WinPopup/src/network.cpp new file mode 100644 index 0000000000..b94ac8be28 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/network.cpp @@ -0,0 +1,81 @@ +/* + +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" + +// , 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/src/network.h b/plugins/!NotAdopted/WinPopup/src/network.h new file mode 100644 index 0000000000..9b6be5f0d3 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/network.h @@ -0,0 +1,29 @@ +/* + +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. +*/ + +// 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/src/options.cpp b/plugins/!NotAdopted/WinPopup/src/options.cpp new file mode 100644 index 0000000000..4dc42977fa --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/options.cpp @@ -0,0 +1,381 @@ +/* + +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" + +#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 = {0}; + odp.cbSize = sizeof (odp); + odp.ptszGroup = LPGENT("Network"); + odp.position = odp.pszGroup[0]; + odp.hInstance = pluginModule; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS); + odp.ptszTitle = LPGENT(modtitle); + odp.pfnDlgProc = DlgProcOptions; + odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR; + Options_AddPage(wParam, &odp); + + return 0; +} diff --git a/plugins/!NotAdopted/WinPopup/src/options.h b/plugins/!NotAdopted/WinPopup/src/options.h new file mode 100644 index 0000000000..3e949cc8b6 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/options.h @@ -0,0 +1,22 @@ +/* + +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. +*/ + +int __cdecl OPT_INITIALISE (WPARAM wParam, LPARAM lParam); diff --git a/plugins/!NotAdopted/WinPopup/src/processapi.cpp b/plugins/!NotAdopted/WinPopup/src/processapi.cpp new file mode 100644 index 0000000000..43e1235680 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/processapi.cpp @@ -0,0 +1,571 @@ +/* + +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" + +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/src/processapi.h b/plugins/!NotAdopted/WinPopup/src/processapi.h new file mode 100644 index 0000000000..17855158d4 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/processapi.h @@ -0,0 +1,258 @@ +/* + +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. +*/ + +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; + +//-------------------------------------------------------------------------------------------- +// 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/src/resource.h b/plugins/!NotAdopted/WinPopup/src/resource.h new file mode 100644 index 0000000000..be40ff446c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/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/src/scanner.cpp b/plugins/!NotAdopted/WinPopup/src/scanner.cpp new file mode 100644 index 0000000000..5074e97a5f --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/scanner.cpp @@ -0,0 +1,208 @@ +/* + +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" + +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/src/scanner.h b/plugins/!NotAdopted/WinPopup/src/scanner.h new file mode 100644 index 0000000000..b184be0448 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/scanner.h @@ -0,0 +1,47 @@ +/* + +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. +*/ + +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/src/search.cpp b/plugins/!NotAdopted/WinPopup/src/search.cpp new file mode 100644 index 0000000000..0599419c88 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/search.cpp @@ -0,0 +1,317 @@ +/* + +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. +*/ + +#include "stdafx.h" + +search pluginSearch; + +// +bool MatchPattern (LPCTSTR String, LPCTSTR Pattern); +// NetBIOS- +bool MatchPatternNetBIOS (LPCTSTR Host, LPCTSTR Pattern); + +search::search() + : m_count( 0 ) + , m_event( NULL ) +{ +} + +INT_PTR search::StartSearch(LPCTSTR szId) +{ + LOG("Search \"%s\"", szId); + + if (m_event) + // + SetEvent (m_event); + else + m_event = CreateEvent (NULL, TRUE, FALSE, NULL); + + // + if ( BasicSearchData* data = new BasicSearchData ) + { + data->me = this; + HANDLE cookie = data->cookie = GenerateCookie(); + data->id = szId; + data->id.MakeUpper(); + data->root = NULL; + mir_forkthread( BasicSearchThread, data ); + return (INT_PTR)cookie; + } + + return 0; +} + +void search::AskForDestroy() +{ + if ( m_event ) + SetEvent( m_event ); +} + +void search::Destroy() +{ + if ( m_event ) + { + while( m_count ) + { + SetEvent( m_event ); + Sleep( 250 ); + } + CloseHandle( m_event ); + m_event = NULL; + } +} + +bool MatchPattern (LPCTSTR String, LPCTSTR Pattern) +{ + TCHAR c, p, l; + for (;;) + { + switch ( p = *Pattern++ ) + { + case 0: + // end of pattern + return *String ? false : true; // if end of string TRUE + + case _T('*'): + // match zero or more char + while (*String) + if (MatchPattern (String++, Pattern)) + return true; + return MatchPattern (String, Pattern); + + case _T('?'): + // match any one char + if (*String++ == 0) + return false; // not end of string + break; + + case _T('['): + // match char set + if ((c = *String++) == 0) + return false; // syntax + l = 0; + if (*Pattern == _T('!')) + { // match a char if NOT in set [] + ++Pattern; + while ((p = *Pattern++)!= _T('\0')) + { + if (p == _T(']')) // if end of char set, then + break; // no match found + if (p == _T('-')) + { // check a range of chars? + p = *Pattern; + // get high limit of range + if (p == 0 || p == _T(']')) + return false; // syntax + if (c >= l && c <= p) + return false; // if in range + } + l = p; + // if char matches this element + if (c == p) + return false; + } + } + else + { // match if char is in set [] + while ((p = *Pattern++) != _T('\0')) + { + if (p == _T(']')) // if end of char set, then + return false; // no match found + if (p == _T('-')) { // check a range of chars? + p = *Pattern; + // get high limit of range + if (p == 0 || p == _T(']')) + return false; // syntax + if (c >= l && c <= p) + break; // if in range, move on + } + l = p; + // if char matches this element + if (c == p) + break; // move on + } + while (p && p != _T(']')) // got a match in char set + p = *Pattern++; // skip to end of set + } + break; + + case _T('#'): + c = *String++; + if (c < _T('0') || c > _T('9')) + return false; // not a digit + break; + + default: + // check for exact char + c = *String++; + if (c != p) + return false; // not a match + break; + } + } +} + +bool MatchPatternNetBIOS (LPCTSTR Host, LPCTSTR Pattern) +{ + netbios_name_list names; + if ( pluginNetBIOS.GetNames( names, Host, false ) ) + { + POSITION pos = names.GetHeadPosition (); + CString n; + while ( pos ) + { + netbios_name& name = names.GetNext (pos); + if ( name.GetType() == 3 ) + { + CA2T sName( name.original ); + if ( MatchPattern( (LPCTSTR)sName, Pattern ) ) + return true; + } + } + } + return false; +} + +void search::BasicSearchJob(const BasicSearchData* data) +{ + if (WaitForSingleObject (m_event, 0) != WAIT_TIMEOUT) + return; + + HANDLE hEnum = NULL; + DWORD res = WNetOpenEnum (RESOURCE_GLOBALNET, RESOURCETYPE_ANY, + RESOURCEUSAGE_CONTAINER, data->root, &hEnum); + if (res == NO_ERROR) + { + for (;;) + { + if (WaitForSingleObject (m_event, 0) != WAIT_TIMEOUT) + return; + + DWORD cCount = 1; + DWORD BufferSize = 4096; + char* Buffer = (char*)mir_alloc( BufferSize ); + if ( ! Buffer ) + break; + res = WNetEnumResource( hEnum, &cCount, Buffer, &BufferSize ); + if ( res == NO_ERROR ) + { + if (WaitForSingleObject (m_event, 0) != WAIT_TIMEOUT) + return; + + LPNETRESOURCE lpnr = (LPNETRESOURCE)Buffer; + if ( lpnr->dwDisplayType == RESOURCEDISPLAYTYPE_SERVER ) + { + // + // , , + CharUpper (lpnr->lpRemoteName); + if (MatchPattern (lpnr->lpRemoteName + 2, data->id) || + (lpnr->lpComment && MatchPattern (lpnr->lpComment, data->id)) || + (data->root && MatchPattern (data->root->lpRemoteName, data->id)) || + MatchPatternNetBIOS (lpnr->lpRemoteName + 2, data->id)) + { + // + PROTOSEARCHRESULT psr = {}; + psr.cbSize = sizeof( PROTOSEARCHRESULT ); + psr.nick = lpnr->lpRemoteName + 2; + psr.firstName = lpnr->lpComment; + psr.lastName = data->root ? data->root->lpRemoteName : _T(""); + psr.email = _T(""); + ProtoBroadcastAck (modname, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, + data->cookie, (LPARAM) &psr); + } + } + else + { + if ( ( lpnr->dwUsage & 0xffff ) == RESOURCEUSAGE_CONTAINER ) + { + if ( BasicSearchData* data1 = new BasicSearchData ) + { + data1->me = data->me; + data1->cookie = data->cookie; + data1->id = data->id; + data1->root = lpnr; + Buffer = NULL; + res = (DWORD)InterlockedIncrement (&m_count); + mir_forkthread( BasicSearchThread, data1 ); + } + } + } + mir_free( Buffer ); + } + else + { + mir_free( Buffer ); + break; + } + } + WNetCloseEnum (hEnum); + } +} + +void search::BasicSearchThread(LPVOID param) +{ + if ( BasicSearchData* data = (BasicSearchData*)param ) + { + data->me->BasicSearch( data ); + if ( data->root ) mir_free( data->root ); + delete data; + } +} + +void search::BasicSearch(const BasicSearchData* data) +{ + // ? + if ( data->root == NULL ) + { + while( m_count ) + { + if ( ! pluginInstalled ) + return; + + // , + Sleep (100); + } + InterlockedIncrement( &m_count ); + ResetEvent( m_event ); + } + + // ? + if ( pluginInstalled ) + { + BasicSearchJob( data ); + + LONG res = InterlockedDecrement( &m_count ); + _ASSERTE( res >= 0 ); + if ( res == 0 ) + { + // ? + if ( WaitForSingleObject( m_event, 0 ) != WAIT_OBJECT_0 ) + { + ProtoBroadcastAck (modname, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, data->cookie, 0); + } + else + { + LOG("Search aborted by another search"); + } + } + } +} diff --git a/plugins/!NotAdopted/WinPopup/src/search.h b/plugins/!NotAdopted/WinPopup/src/search.h new file mode 100644 index 0000000000..463845367d --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/search.h @@ -0,0 +1,58 @@ +/* + +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. +*/ + +class search +{ +public: + search(); + + // + INT_PTR StartSearch(LPCTSTR szId); + + // + void AskForDestroy(); + + // + void Destroy(); + +protected: + typedef struct _BasicSearchData + { + search* me; // + HANDLE cookie; // + CString id; // (uppercase) + LPNETRESOURCE root; // (mir_alloc) + } BasicSearchData; + + HANDLE m_event; // + volatile LONG m_count; // + + // + void BasicSearch(const BasicSearchData* data); + + // + void BasicSearchJob(const BasicSearchData* data); + + // + static void BasicSearchThread(LPVOID param); +}; + +extern search pluginSearch; diff --git a/plugins/!NotAdopted/WinPopup/src/services.cpp b/plugins/!NotAdopted/WinPopup/src/services.cpp new file mode 100644 index 0000000000..7bb482dbbe --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/services.cpp @@ -0,0 +1,879 @@ +/* + +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" + +// "\\Nick" ShellExecute() ("Nick" ) +// wParam=hContact +// lParam=0 +// 0 +#define PS_EXPLORE "/Explore" + +// / +// wParam=Position +// lParam=0 +// 0 +#define PS_ADDDIALOG "/AddDialog" + +///////////////////////////////////////////////////////////////////////////// +// + +// WinPopup Protocol/Explore +INT_PTR Explore(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/AddDialog +INT_PTR AddDialog(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/GetCaps +INT_PTR GetCaps(WPARAM flagNum, LPARAM lParam); +// WinPopup Protocol/GetName +INT_PTR GetName(WPARAM cchName, LPARAM szName); +// WinPopup Protocol/LoadIcon +INT_PTR LoadIcon(WPARAM whichIcon, LPARAM lParam); +// WinPopup Protocol/SetStatus +INT_PTR SetStatus(WPARAM newStatus, LPARAM lParam); +// WinPopup Protocol/SetAwayMsg +INT_PTR SetAwayMsg(WPARAM status_mode, LPARAM szMessage); +// WinPopup Protocol/GetAwayMsg +INT_PTR GetAwayMsg(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/GetStatus +INT_PTR GetStatus(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/GetInfo +INT_PTR GetInfo(WPARAM flags, LPARAM lParam); +// WinPopup Protocol/RecvMessage +INT_PTR RecvMessage(WPARAM flags, LPARAM lParam); +// WinPopup Protocol/SendMsg +INT_PTR SendMsg(WPARAM flags, LPARAM lParam); +// WinPopup Protocol/BasicSearch +INT_PTR BasicSearch(WPARAM wParam, LPARAM szId); +// WinPopup Protocol/AddToList +INT_PTR AddToList(WPARAM flags, LPARAM lParam); +// WinPopup Protocol/GetAvatarCaps +INT_PTR GetAvatarCaps(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/GetAvatarInformation +INT_PTR GetAvatarInfo(WPARAM flags, LPARAM lParam); +// WinPopup Protocol/SetMyAvatar +INT_PTR SetMyAvatar(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/GetMyAvatar +INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam); +// WinPopup Protocol/CreateAccMgrUI +INT_PTR CreateAccMgrUI(WPARAM wParam, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////// +// + +// ME_SYSTEM_MODULESLOADED +int __cdecl SYSTEM_MODULESLOADED(WPARAM wParam, LPARAM lParam); +// ME_SYSTEM_PRESHUTDOWN +int __cdecl SYSTEM_PRESHUTDOWN(WPARAM wParam, LPARAM lParam); + +///////////////////////////////////////////////////////////////////////////// +// + +int hLangpack; + +const PROTOCOLDESCRIPTOR pluginPD = +{ + sizeof( PROTOCOLDESCRIPTOR ), + modname, + PROTOTYPE_PROTOCOL +}; + +static PLUGININFOEX pluginInfoEx = +{ + sizeof(PLUGININFOEX), + modname, + PLUGIN_MAKE_VERSION (0,0,0,18), + "Allows you to send and receive messages over Microsoft LAN. " + "WinPopup and Net Send replacement powered by Miranda IM.", + "Nikolay Raspopov", + "ryo-oh-ki@narod.ru", + " 2004-2010 Nikolay Raspopov", + "http://www.cherubicsoft.com/miranda/", + UNICODE_AWARE, + // {DE6EE412-ACE3-45db-A329-D618FABB4291} + {0xde6ee412, 0xace3, 0x45db, {0xa3, 0x29, 0xd6, 0x18, 0xfa, 0xbb, 0x42, 0x91}} +}; + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; + +HANDLE plugin_FnGetCaps = NULL; +HANDLE plugin_FnGetName = NULL; +HANDLE plugin_FnLoadIcon = NULL; +HANDLE plugin_FnSetStatus = NULL; +HANDLE plugin_FnGetStatus = NULL; +HANDLE plugin_FnGetAwayMsg = NULL; +HANDLE plugin_FnSetAwayMsg = NULL; +HANDLE plugin_FnGetInfo = NULL; +HANDLE plugin_FnSendMsg = NULL; +HANDLE plugin_FnRecvMessage = NULL; +HANDLE plugin_FnBasicSearch = NULL; +HANDLE plugin_FnAddToList = NULL; +HANDLE plugin_FnExplore = NULL; +HANDLE plugin_FnAddDialog = NULL; +HANDLE plugin_FnGetAvatarCaps = NULL; +HANDLE plugin_FnGetAvatarInfo = NULL; +HANDLE plugin_FnSetMyAvatar = NULL; +HANDLE plugin_FnGetMyAvatar = NULL; +HANDLE plugin_FnCreateAccMgrUI = NULL; +HANDLE plugin_SYSTEM_MODULESLOADED = NULL; +HANDLE plugin_SYSTEM_PRESHUTDOWN = NULL; +HANDLE plugin_OPT_INITIALISE = NULL; +HANDLE plugin_USERINFO_INITIALISE = NULL; + +///////////////////////////////////////////////////////////////////////////// +// DllLoader + +DllLoader pluginNetapi32 ( _T("netapi32.dll"), false); +DllLoader pluginAdvapi32 ( _T("advapi32.dll"), false); +FuncPtrType(NET_API_STATUS (NET_API_FUNCTION *) (LMSTR, DWORD, LPBYTE*) ) fnNetWkstaGetInfo; +FuncPtrType(DWORD (NET_API_FUNCTION *) (LPVOID) ) fnNetApiBufferFree; +FuncPtrType(DWORD (NET_API_FUNCTION *) (LPCWSTR, LPCWSTR, LPCWSTR, LPBYTE, DWORD) ) fnNetMessageBufferSend; +FuncPtrType(SC_HANDLE (WINAPI *) (LPCTSTR, LPCTSTR, DWORD) ) fnOpenSCManager; +FuncPtrType(SC_HANDLE (WINAPI *) (SC_HANDLE, LPCTSTR, DWORD) ) fnOpenService; +FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, LPSERVICE_STATUS) ) fnControlService; +FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, LPSERVICE_STATUS) ) fnQueryServiceStatus; +FuncPtrType(BOOL (WINAPI *) (SC_HANDLE) ) fnCloseServiceHandle; +FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, LPCTSTR*) ) fnStartService; +FuncPtrType(SC_LOCK (WINAPI *) (SC_HANDLE) ) fnLockServiceDatabase; +FuncPtrType(BOOL (WINAPI *) (SC_LOCK) ) fnUnlockServiceDatabase; +FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR) ) fnChangeServiceConfig; + +#define CreateHook( hService, szName, Function ) \ + _ASSERT( hService == NULL ); \ + hService = HookEvent( szName, Function ); \ + _ASSERT ( hService != NULL ); \ + if ( ! hService ) return 1; + +#define DestroyHook( hService ) \ + if ( hService ) { \ + UnhookEvent( hService ); \ + hService = NULL; \ + } + +#define CreateServiceFn( hService, szName, Function ) \ + _ASSERT( hService == NULL ); \ + hService = CreateServiceFunction( modname szName, Function ); \ + _ASSERT( hService != NULL ); \ + if ( ! hService ) return 1; + +#ifdef _DEBUG + #define DestroyServiceFn( hService ) \ + if( hService ) { \ + _ASSERT( DestroyServiceFunction( hService ) == 0 ); \ + hService = NULL; \ + } +#else // _DEBUG + #define DestroyServiceFn( hService ) \ + if( hService ) { \ + DestroyServiceFunction( hService ); \ + hService = NULL; \ + } +#endif // _DEBUG + + +INT_PTR Explore(WPARAM wParam, LPARAM /* lParam */) +{ + CString sNick = GetNick( (HANDLE)wParam ); + if ( pluginInstalled && ! sNick.IsEmpty() ) + { + // UNC : \\Nick + CString cmd( _T("\\\\") ); + cmd += sNick; + ShellExecute( NULL, NULL, cmd, NULL, NULL, SW_SHOWDEFAULT ); + } + return 0; +} + +INT_PTR AddDialog (WPARAM /* wParam */, LPARAM /* lParam */) +{ + AddDialog( NULL ); + return 0; +} + +INT_PTR GetCaps (WPARAM flagNum, LPARAM /* lParam */) +{ + INT_PTR nReturn = 0; + switch ( flagNum ) + { + case PFLAGNUM_1: + nReturn = PF1_IM | PF1_BASICSEARCH | PF1_MODEMSG | PF1_PEER2PEER; + break; + + case PFLAGNUM_2: + case PFLAGNUM_3: + nReturn = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | + PF2_LIGHTDND | PF2_HEAVYDND | PF2_FREECHAT | + PF2_ONTHEPHONE | PF2_OUTTOLUNCH; + break; + + case PFLAGNUM_4: + nReturn = PF4_AVATARS; + break; + + case PFLAGNUM_5: + nReturn = 0; + break; + + case PFLAG_UNIQUEIDTEXT: + nReturn = (INT_PTR)Translate ("Computer,User,Group"); + break; + + case PFLAG_UNIQUEIDSETTING: + nReturn = (INT_PTR)"Nick"; + break; + + case PFLAG_MAXLENOFMESSAGE: + // HANDLE hContact = (HANDLE) lParam; + nReturn = 0x7fffffff; + break; + } + return nReturn; +} + +INT_PTR GetName(WPARAM cchName, LPARAM szName) +{ + lstrcpynA( (char*) szName, modtitle, static_cast ( cchName ) ); + return 0; +} + +INT_PTR LoadIcon(WPARAM whichIcon, LPARAM /* lParam */) +{ + UINT id; + switch ( whichIcon & 0xFFFF ) + { + case PLI_PROTOCOL: + id = IDI_WINPOPUP; + break; + + case PLI_ONLINE: + id = IDI_ONLINE; + break; + + case PLI_OFFLINE: + id = IDI_OFFLINE; + break; + + default: + return 0; + } + return (INT_PTR)LoadImage (pluginModule, MAKEINTRESOURCE (id), IMAGE_ICON, + (whichIcon & PLIF_SMALL ? 16 : 32), (whichIcon & PLIF_SMALL ? 16 : 32), 0); +} + +INT_PTR SetStatus (WPARAM newStatus, LPARAM /* lParam */) +{ + if ( pluginInstalled && pluginCurrentStatus != (int)newStatus ) + { + LOG ("SetStatus from \"%s\" to \"%s\"", + STATUS2TEXT(pluginCurrentStatus), STATUS2TEXT(newStatus)); + + pluginRequestedStatus = newStatus; + switch (newStatus) { + case ID_STATUS_OFFLINE: + GotoOffline (); + break; + case ID_STATUS_FREECHAT: + case ID_STATUS_INVISIBLE: + newStatus = ID_STATUS_ONLINE; + case ID_STATUS_ONLINE: + case ID_STATUS_AWAY: + case ID_STATUS_DND: + case ID_STATUS_NA: + case ID_STATUS_OCCUPIED: + case ID_STATUS_ONTHEPHONE: + case ID_STATUS_OUTTOLUNCH: + default: + GotoOnline (); + break; + } + } + return 0; +} + +INT_PTR SetAwayMsg (WPARAM status_mode, LPARAM szMessage) +{ + pluginStatusMessage[ status_mode ] = ( szMessage ? (LPCSTR) szMessage : "" ); + return 0; +} + +INT_PTR GetAwayMsg(WPARAM /* wParam */, LPARAM lParam) +{ + CCSDATA *ccs = (CCSDATA*)lParam; + if ( pluginInstalled && ccs && ccs->hContact ) + { + if ( ContactData* data = new ContactData ) + { + data->hContact = ccs->hContact; + HANDLE cookie = data->cookie = GenerateCookie(); + mir_forkthread( GetAwayMsgThread, data ); + return (INT_PTR)cookie; + } + } + return 0; +} + +INT_PTR GetStatus (WPARAM /* wParam */, LPARAM /* lParam */) +{ + return (INT_PTR)pluginCurrentStatus; +} + +INT_PTR GetInfo (WPARAM /* flags */, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*)lParam; + if ( pluginInstalled && ccs && ccs->hContact ) + { + mir_forkthread( GetInfoThread, ccs->hContact ); + return 0; + } + return 1; +} + +INT_PTR RecvMessage (WPARAM /* flags */, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*) lParam; + if ( pluginInstalled && ccs && ccs->hContact && ccs->lParam) + { + PROTORECVEVENT *pre = (PROTORECVEVENT*) ccs->lParam; + + // + DBDeleteContactSetting (ccs->hContact, "CList", "Hidden"); + DBEVENTINFO ei = { 0 }; + ei.cbSize = sizeof (DBEVENTINFO); + ei.szModule = modname; + ei.timestamp = pre->timestamp; + ei.flags = (pre->flags & PREF_CREATEREAD) ? DBEF_READ : 0u; + ei.eventType = EVENTTYPE_MESSAGE; + ei.cbBlob = (DWORD)( lstrlenA (pre->szMessage) + 1 ); + ei.pBlob = (PBYTE) pre->szMessage; + CallService (MS_DB_EVENT_ADD, (WPARAM) ccs->hContact, (LPARAM) &ei); + } + return 0; +} + +INT_PTR SendMsg(WPARAM /* flags */, LPARAM lParam) +{ + CCSDATA* ccs = (CCSDATA*) lParam; + if ( pluginInstalled && ccs && ccs->hContact && ccs->lParam ) + { + if ( SendMsgData* data = new SendMsgData ) + { + data->hContact = ccs->hContact; + data->text = (LPCSTR)ccs->lParam; + HANDLE cookie = data->cookie = GenerateCookie(); + mir_forkthread( SendMsgThread, data ); + return (INT_PTR)cookie; + } + } + return 0; +} + +INT_PTR BasicSearch(WPARAM /* wParam */, LPARAM szId) +{ + if ( pluginInstalled && szId ) + { + return pluginSearch.StartSearch( CA2T( (LPCSTR)szId ) ); + } + return 0; +} + +INT_PTR AddToList(WPARAM flags, LPARAM lParam) +{ + PROTOSEARCHRESULT* psr = (PROTOSEARCHRESULT*) lParam; + if ( psr && psr->cbSize >= sizeof (PROTOSEARCHRESULT) && psr->nick && *psr->nick ) + { + CString sName( psr->nick ); + CString sNotes( psr->firstName ); + return (INT_PTR)AddToListByName( sName, flags, sNotes, false, false ); + } + return 0; +} + +INT_PTR GetAvatarCaps(WPARAM wParam, LPARAM lParam) +{ + switch ( wParam ) + { + case AF_MAXSIZE: + if ( POINT* size = (POINT*)lParam ) + { + size->x = 300; // -1 - - avs.dll + size->y = 300; // -1 - - avs.dll + } + break; + + case AF_PROPORTION: + return PIP_NONE; + + case AF_FORMATSUPPORTED: + switch ( lParam ) + { + case PA_FORMAT_UNKNOWN: + case PA_FORMAT_PNG: + case PA_FORMAT_JPEG: + case PA_FORMAT_ICON: + case PA_FORMAT_BMP: + case PA_FORMAT_GIF: + case PA_FORMAT_SWF: + case PA_FORMAT_XML: + return 1; + } + break; + + case AF_ENABLED: + return 1; + + case AF_DONTNEEDDELAYS: + return 1; + + case AF_MAXFILESIZE: + return MAX_AVATAR_SIZE; + + case AF_DELAYAFTERFAIL: + return 10 * 60 * 1000; // 10 + } + + return 0; +} + +INT_PTR GetAvatarInfo(WPARAM /*flags*/, LPARAM lParam) +{ + PROTO_AVATAR_INFORMATION* pai = (PROTO_AVATAR_INFORMATION*)lParam; + if ( pai && pai->cbSize >= sizeof( PROTO_AVATAR_INFORMATION ) ) + { + if ( ContactData* data = new ContactData ) + { + data->hContact = pai->hContact; + /*HANDLE cookie =*/ data->cookie = GenerateCookie(); + mir_forkthread( GetAvatarInfoThread, data ); + return GAIR_WAITFOR; + } + } + return GAIR_NOAVATAR; +} + +INT_PTR SetMyAvatar(WPARAM /*wParam*/, LPARAM lParam) +{ + CA2T szFilename( (LPCSTR)lParam ); + + TCHAR szPath[ MAX_PATH ]; + GetAvatarCache( szPath ); + + if ( szFilename ) + { + // + lstrcat( szPath, _T("MyAvatar") ); + lstrcat( szPath, _tcsrchr( szFilename, _T('.') ) ); + + if ( lstrcmpi( szPath, szFilename ) == 0 ) + { + // - + } + else + { + // - + SHFILEOPSTRUCT sfo = {}; + sfo.hwnd = GetDesktopWindow(); + sfo.wFunc = FO_COPY; + TCHAR szFrom[ MAX_PATH ] = {}; + lstrcpy( szFrom, szFilename ); + sfo.pFrom = szFrom; + sfo.pTo = szPath; + sfo.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_NORECURSION | + FOF_NOCONFIRMATION; + SHFileOperation( &sfo ); + } + + DBWriteContactSettingTString( NULL, modname, "AvatarFile", + _tcsrchr( szPath, _T('\\') ) + 1 ); + } + else + { + // + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( NULL, modname, "AvatarFile", &dbv ) ) + { + lstrcat( szPath, dbv.ptszVal ); + + SHFILEOPSTRUCT sfo = {}; + sfo.hwnd = GetDesktopWindow(); + sfo.wFunc = FO_DELETE; + sfo.pFrom = szPath; + sfo.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_NORECURSION | + FOF_NOCONFIRMATION; + SHFileOperation( &sfo ); + + DBFreeVariant( &dbv ); + + DBDeleteContactSetting( NULL, modname, "AvatarFile" ); + } + } + + return 0; +} + +INT_PTR GetMyAvatar(WPARAM wParam, LPARAM lParam) +{ + LPSTR szFilename = (LPSTR)wParam; + int nLength = (int)lParam; + bool ret = false; + + if ( szFilename == NULL || nLength < MAX_PATH ) + return -1; + + TCHAR szPath[ MAX_PATH ]; + GetAvatarCache( szPath ); + + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( NULL, modname, "AvatarFile", &dbv ) ) + { + lstrcat( szPath, dbv.ptszVal ); + + ret = ( GetFileAttributes( szPath ) != INVALID_FILE_ATTRIBUTES ); + + DBFreeVariant( &dbv ); + } + + if ( ! ret ) + return -1; + + lstrcpyA( szFilename, CT2A( szPath ) ); + + return 0; +} + +static INT_PTR CALLBACK DlgProcCreateAccMgrUI(HWND hwndDlg, UINT Msg, + WPARAM /*wParam*/, LPARAM /*lParam*/) +{ + switch ( Msg ) + { + case WM_INITDIALOG: + { + TranslateDialogDefault( hwndDlg ); + return TRUE; + } + } + return FALSE; +} + +INT_PTR CreateAccMgrUI(WPARAM /*wParam*/, LPARAM lParam) +{ + return (INT_PTR)CreateDialogParam( pluginModule, MAKEINTRESOURCE( IDD_CREATE ), + (HWND)lParam, DlgProcCreateAccMgrUI, 0 ); +} + +///////////////////////////////////////////////////////////////////////////// +// + +extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfoEx; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfoEx); + GetVersionEx( &pluginOS ); + + if (pluginNetapi32.LoadLibrary (pluginModule)) + { + pluginNetapi32.LoadFunc (fnNetWkstaGetInfo, "NetWkstaGetInfo"); + pluginNetapi32.LoadFunc (fnNetApiBufferFree, "NetApiBufferFree"); + pluginNetapi32.LoadFunc (fnNetMessageBufferSend, "NetMessageBufferSend"); + } + + if (pluginAdvapi32.LoadLibrary (pluginModule)) + { + pluginAdvapi32.LoadFunc (fnOpenSCManager, "OpenSCManagerW"); + pluginAdvapi32.LoadFunc (fnOpenService, "OpenServiceW"); + pluginAdvapi32.LoadFunc (fnStartService, "StartServiceW"); + pluginAdvapi32.LoadFunc (fnChangeServiceConfig, "ChangeServiceConfigW"); + pluginAdvapi32.LoadFunc (fnControlService, "ControlService"); + pluginAdvapi32.LoadFunc (fnQueryServiceStatus, "QueryServiceStatus"); + pluginAdvapi32.LoadFunc (fnCloseServiceHandle, "CloseServiceHandle"); + pluginAdvapi32.LoadFunc (fnLockServiceDatabase, "LockServiceDatabase"); + pluginAdvapi32.LoadFunc (fnUnlockServiceDatabase, "UnlockServiceDatabase"); + } + + _ASSERT( pluginInternalState == NULL ); + pluginInternalState = CreateEvent( NULL, TRUE, TRUE, NULL ); + _ASSERT( pluginInternalState != NULL ); + + INT_PTR retCallService = CallService (MS_PROTO_REGISTERMODULE, 0, (LPARAM) &pluginPD); + _ASSERT (retCallService != CALLSERVICE_NOTFOUND); + if ( retCallService == CALLSERVICE_NOTFOUND ) return 1; + + CreateServiceFn( plugin_FnGetCaps, PS_GETCAPS, GetCaps ); + CreateServiceFn( plugin_FnGetName, PS_GETNAME, GetName ); + CreateServiceFn( plugin_FnLoadIcon, PS_LOADICON, LoadIcon ); + CreateServiceFn( plugin_FnSetStatus, PS_SETSTATUS, SetStatus ); + CreateServiceFn( plugin_FnGetStatus, PS_GETSTATUS, GetStatus ); + CreateServiceFn( plugin_FnSetAwayMsg, PS_SETAWAYMSG, SetAwayMsg ); + CreateServiceFn( plugin_FnGetAwayMsg, PSS_GETAWAYMSG, GetAwayMsg ); + CreateServiceFn( plugin_FnGetInfo, PSS_GETINFO, GetInfo ); + CreateServiceFn( plugin_FnSendMsg, PSS_MESSAGE, SendMsg ); + CreateServiceFn( plugin_FnRecvMessage, PSR_MESSAGE, RecvMessage ); + CreateServiceFn( plugin_FnBasicSearch, PS_BASICSEARCH, BasicSearch ); + CreateServiceFn( plugin_FnAddToList, PS_ADDTOLIST, AddToList ); + CreateServiceFn( plugin_FnExplore, PS_EXPLORE, Explore ); + CreateServiceFn( plugin_FnAddDialog, PS_ADDDIALOG, AddDialog); + CreateServiceFn( plugin_FnGetAvatarCaps, PS_GETAVATARCAPS, GetAvatarCaps ); + CreateServiceFn( plugin_FnGetAvatarInfo, PS_GETAVATARINFO, GetAvatarInfo ); + CreateServiceFn( plugin_FnSetMyAvatar, PS_SETMYAVATAR, SetMyAvatar ); + CreateServiceFn( plugin_FnGetMyAvatar, PS_GETMYAVATAR, GetMyAvatar ); + CreateServiceFn( plugin_FnCreateAccMgrUI, PS_CREATEACCMGRUI, CreateAccMgrUI ); + + CreateHook( plugin_SYSTEM_MODULESLOADED, ME_SYSTEM_MODULESLOADED, SYSTEM_MODULESLOADED ); + CreateHook( plugin_SYSTEM_PRESHUTDOWN, ME_SYSTEM_PRESHUTDOWN, SYSTEM_PRESHUTDOWN ); + + + return 0; +} + +extern "C" int __declspec(dllexport) Unload() +{ +#ifdef CHAT_ENABLED + ChatUnregister(); +#endif // CHAT_ENABLED + + DestroyHook( plugin_USERINFO_INITIALISE ); + DestroyHook( plugin_OPT_INITIALISE ); + DestroyHook( plugin_SYSTEM_PRESHUTDOWN ); + DestroyHook( plugin_SYSTEM_MODULESLOADED ); + + DestroyServiceFn( plugin_FnExplore ); + DestroyServiceFn( plugin_FnAddDialog ); + DestroyServiceFn( plugin_FnGetCaps ); + DestroyServiceFn( plugin_FnGetName ); + DestroyServiceFn( plugin_FnLoadIcon ); + DestroyServiceFn( plugin_FnSetStatus ); + DestroyServiceFn( plugin_FnGetStatus ); + DestroyServiceFn( plugin_FnSetAwayMsg ); + DestroyServiceFn( plugin_FnGetAwayMsg ); + DestroyServiceFn( plugin_FnGetInfo ); + DestroyServiceFn( plugin_FnSendMsg ); + DestroyServiceFn( plugin_FnRecvMessage ); + DestroyServiceFn( plugin_FnBasicSearch ); + DestroyServiceFn( plugin_FnAddToList ); + DestroyServiceFn( plugin_FnGetAvatarCaps ); + DestroyServiceFn( plugin_FnGetAvatarInfo ); + DestroyServiceFn( plugin_FnSetMyAvatar ); + DestroyServiceFn( plugin_FnGetMyAvatar ); + DestroyServiceFn( plugin_FnCreateAccMgrUI ); + + if ( pluginNetLibUser != NULL ) + Netlib_CloseHandle( pluginNetLibUser ); + pluginNetLibUser = NULL; + + if ( pluginInternalState != NULL ) + CloseHandle( pluginInternalState ); + pluginInternalState = NULL; + + pluginNetapi32.FreeLibrary(); + pluginAdvapi32.FreeLibrary(); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// +// + +int __cdecl SYSTEM_MODULESLOADED (WPARAM /* wParam */, LPARAM /* lParam */) +{ + _ASSERT (pluginInstalled == true); + _ASSERT (pluginInitialized == false); + + _ASSERT (pluginNetLibUser == NULL); + const NETLIBUSER nlu = + { + sizeof( NETLIBUSER ), + modname, + modname, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0 + }; + pluginNetLibUser = (HANDLE)CallService( MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu ); + _ASSERT (pluginNetLibUser); + + CreateHook( plugin_OPT_INITIALISE, ME_OPT_INITIALISE, OPT_INITIALISE ); + CreateHook( plugin_USERINFO_INITIALISE, ME_USERINFO_INITIALISE, USERINFO_INITIALISE ); + + // + struct + { + int icon_id; + int status; + } + const StatusIcons [] = + { + { IDI_OFFLINE, ID_STATUS_OFFLINE }, + { IDI_ONLINE, ID_STATUS_ONLINE }, + { IDI_AWAY, ID_STATUS_AWAY }, + { IDI_DND, ID_STATUS_DND }, + { IDI_NA, ID_STATUS_NA }, + { IDI_OCCUPIED, ID_STATUS_OCCUPIED }, + { IDI_FREECHAT, ID_STATUS_FREECHAT }, + { IDI_INVISIBLE, ID_STATUS_INVISIBLE }, + { IDI_ONTHEPHONE, ID_STATUS_ONTHEPHONE }, + { IDI_OUTTOLUNCH, ID_STATUS_OUTTOLUNCH }, + { 0, 0 } + }; + TCHAR path [ MAX_PATH * 2 ] = { 0 }; + TCHAR icon [ 32 ] = { 0 }; + DWORD len = GetModuleFileName (pluginModule, path, MAX_PATH); + lstrcpy( path + len, _T(",-") ); + len += 2; + for (int i = 0; StatusIcons[i].icon_id ; i++) + { + wsprintf( path + len, _T("%d"), StatusIcons[i].icon_id ); + wsprintf( icon, modname_t _T("%d"), StatusIcons[i].status ); + DBVARIANT dbv = {}; + if ( ! DBGetContactSetting( NULL, "Icons", CT2A( icon ), &dbv ) ) + DBFreeVariant( &dbv ); + else + DBWriteContactSettingTString( NULL, "Icons", CT2A( icon ), path ); + } + + // + DWORD iMachineNameLength = MAX_COMPUTERNAME_LENGTH + 2; + GetComputerName( + pluginMachineName.GetBuffer( (int)iMachineNameLength ), &iMachineNameLength ); + pluginMachineName.ReleaseBuffer(); + SetNick( NULL, pluginMachineName ); + + // + DWORD iUserNameLength = UNLEN + 2; + GetUserName( + pluginUserName.GetBuffer( (int)iUserNameLength ), &iUserNameLength ); + pluginUserName.ReleaseBuffer(); + DBWriteContactSettingTString( NULL, modname, "User", pluginUserName ); + + // + if ( pluginOS.dwPlatformId == VER_PLATFORM_WIN32_NT ) + { + WKSTA_INFO_100* info = NULL; + NET_API_STATUS err = fnNetWkstaGetInfo (NULL, 100, (LPBYTE*) &info); + if (err == NERR_Success && info) + { + LPTSTR langroup = mir_u2t( info->wki100_langroup ); + pluginDomainName = langroup; + fnNetApiBufferFree (info); + mir_free( langroup ); + } + // ? + // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon + // DefaultDomainName + } + else + { + HKEY hKey = NULL; + if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, + _T("System\\CurrentControlSet\\Services\\VxD\\VNETSUP"), 0, KEY_READ, &hKey)) + { + DWORD type, size = MAX_PATH; + RegQueryValueEx (hKey, _T("Workgroup"), 0, &type, + (LPBYTE) pluginDomainName.GetBuffer (MAX_PATH + 1), &size); + pluginDomainName.ReleaseBuffer( (int)size ); + RegCloseKey (hKey); + } + } + DBWriteContactSettingTString (NULL, modname, "Workgroup", pluginDomainName); + + // Chat +#ifdef CHAT_ENABLED + pluginChatEnabled = ChatRegister(); +#endif // CHAT_ENABLED + + // + CLISTMENUITEM miExplore = + { + sizeof( CLISTMENUITEM ), + (LPSTR)TranslateT( "Explore" ), + CMIF_TCHAR, + 0, + (HICON)LoadImage( pluginModule, MAKEINTRESOURCE( IDI_EXPLORE ), + IMAGE_ICON, 16, 16, LR_SHARED ), + modname PS_EXPLORE, + NULL, + 0, + 0, + modname + }; + Menu_AddContactMenuItem(&miExplore); + + CLISTMENUITEM miAddContact = + { + sizeof( CLISTMENUITEM ), + NULL, + CMIF_TCHAR, + 500090000, + (HICON)LoadImage( pluginModule, MAKEINTRESOURCE( IDI_WINPOPUP ), + IMAGE_ICON, 16, 16, LR_SHARED ), + modname PS_ADDDIALOG, + NULL, + 0, + 0, + NULL + }; + miAddContact.ptszName = (LPTSTR)TranslateT( "Add contact..." ); + miAddContact.ptszPopupName = (LPTSTR)modtitle_t; + + HANDLE hMenuItem = Menu_AddMainMenuItem(&miAddContact); + // + miAddContact.flags = CMIM_ICON; + miAddContact.hIcon = (HICON)LoadImage( pluginModule, + MAKEINTRESOURCE( IDI_ADD_COMPUTER ), IMAGE_ICON, 16, 16, LR_SHARED ), + CallService( MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItem, (LPARAM)&miAddContact ); + + // (, ) + pluginInitialized = true; + + // + SetStatus( pluginRequestedStatus, 0 ); + + return 0; +} + +int __cdecl SYSTEM_PRESHUTDOWN (WPARAM /* wParam */, LPARAM /* lParam */) +{ + // (, ) + pluginInstalled = false; + + // , .. + // , + do + { + MSG msg; + while ( PeekMessage( &msg, NULL, NULL, NULL, PM_REMOVE ) ) + { + if ( IsDialogMessage( msg.hwnd, &msg ) ) continue; + TranslateMessage( &msg ); + DispatchMessage( &msg ); + } + } + while ( MsgWaitForMultipleObjects( 1, &pluginInternalState, FALSE, + INFINITE, QS_ALLINPUT ) == WAIT_OBJECT_0 + 1 ); + + return 0; +} diff --git a/plugins/!NotAdopted/WinPopup/src/services.h b/plugins/!NotAdopted/WinPopup/src/services.h new file mode 100644 index 0000000000..505f7fe409 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/services.h @@ -0,0 +1,34 @@ +/* + +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. +*/ + +// DllLoader +extern FuncPtrType(NET_API_STATUS (NET_API_FUNCTION *) (LMSTR, DWORD, LPBYTE*) ) fnNetWkstaGetInfo; +extern FuncPtrType(DWORD (NET_API_FUNCTION *) (LPVOID) ) fnNetApiBufferFree; +extern FuncPtrType(DWORD (NET_API_FUNCTION *) (LPCWSTR, LPCWSTR, LPCWSTR, LPBYTE, DWORD) ) fnNetMessageBufferSend; +extern FuncPtrType(SC_HANDLE (WINAPI *) (LPCTSTR, LPCTSTR, DWORD) ) fnOpenSCManager; +extern FuncPtrType(SC_HANDLE (WINAPI *) (SC_HANDLE, LPCTSTR, DWORD) ) fnOpenService; +extern FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, LPSERVICE_STATUS) ) fnControlService; +extern FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, LPSERVICE_STATUS) ) fnQueryServiceStatus; +extern FuncPtrType(BOOL (WINAPI *) (SC_HANDLE) ) fnCloseServiceHandle; +extern FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, LPCTSTR*) ) fnStartService; +extern FuncPtrType(SC_LOCK (WINAPI *) (SC_HANDLE) ) fnLockServiceDatabase; +extern FuncPtrType(BOOL (WINAPI *) (SC_LOCK) ) fnUnlockServiceDatabase; +extern FuncPtrType(BOOL (WINAPI *) (SC_HANDLE, DWORD, DWORD, DWORD, LPCTSTR, LPCTSTR, LPDWORD, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR) ) fnChangeServiceConfig; diff --git a/plugins/!NotAdopted/WinPopup/src/smbconst.h b/plugins/!NotAdopted/WinPopup/src/smbconst.h new file mode 100644 index 0000000000..32f6dd2851 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/smbconst.h @@ -0,0 +1,106 @@ +/* + +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. +*/ + +#define SMBmkdir 0x00 /* create directory */ +#define SMBrmdir 0x01 /* delete directory */ +#define SMBopen 0x02 /* open file */ +#define SMBcreate 0x03 /* create file */ +#define SMBclose 0x04 /* close file */ +#define SMBflush 0x05 /* flush file */ +#define SMBunlink 0x06 /* delete file */ +#define SMBmv 0x07 /* rename file */ +#define SMBgetatr 0x08 /* get file attributes */ +#define SMBsetatr 0x09 /* set file attributes */ +#define SMBread 0x0A /* read from file */ +#define SMBwrite 0x0B /* write to file */ +#define SMBlock 0x0C /* lock byte range */ +#define SMBunlock 0x0D /* unlock byte range */ +#define SMBctemp 0x0E /* create temporary file */ +#define SMBmknew 0x0F /* make new file */ +#define SMBchkpth 0x10 /* check directory path */ +#define SMBexit 0x11 /* process exit */ +#define SMBlseek 0x12 /* seek */ +#define SMBtcon 0x70 /* tree connect */ +#define SMBtconX 0x75 /* tree connect and X*/ +#define SMBtdis 0x71 /* tree disconnect */ +#define SMBnegprot 0x72 /* negotiate protocol */ +#define SMBdskattr 0x80 /* get disk attributes */ +#define SMBsearch 0x81 /* search directory */ +#define SMBsplopen 0xC0 /* open print spool file */ +#define SMBsplwr 0xC1 /* write to print spool file */ +#define SMBsplclose 0xC2 /* close print spool file */ +#define SMBsplretq 0xC3 /* return print queue */ +#define SMBsends 0xD0 /* send single block message */ +#define SMBsendb 0xD1 /* send broadcast message */ +#define SMBfwdname 0xD2 /* forward user name */ +#define SMBcancelf 0xD3 /* cancel forward */ +#define SMBgetmac 0xD4 /* get machine name */ +#define SMBsendstrt 0xD5 /* send start of multi-block message */ +#define SMBsendend 0xD6 /* send end of multi-block message */ +#define SMBsendtxt 0xD7 /* send text of multi-block message */ + +/* Core+ protocol */ +#define SMBlockread 0x13 /* Lock a range and read */ +#define SMBwriteunlock 0x14 /* Unlock a range then write */ +#define SMBreadbraw 0x1a /* read a block of data with no smb header */ +#define SMBwritebraw 0x1d /* write a block of data with no smb header */ +#define SMBwritec 0x20 /* secondary write request */ +#define SMBwriteclose 0x2c /* write a file then close it */ + +/* dos extended protocol */ +#define SMBreadBraw 0x1A /* read block raw */ +#define SMBreadBmpx 0x1B /* read block multiplexed */ +#define SMBreadBs 0x1C /* read block (secondary response) */ +#define SMBwriteBraw 0x1D /* write block raw */ +#define SMBwriteBmpx 0x1E /* write block multiplexed */ +#define SMBwriteBs 0x1F /* write block (secondary request) */ +#define SMBwriteC 0x20 /* write complete response */ +#define SMBsetattrE 0x22 /* set file attributes expanded */ +#define SMBgetattrE 0x23 /* get file attributes expanded */ +#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */ +#define SMBtrans 0x25 /* transaction - name, bytes in/out */ +#define SMBtranss 0x26 /* transaction (secondary request/response) */ +#define SMBioctl 0x27 /* IOCTL */ +#define SMBioctls 0x28 /* IOCTL (secondary request/response) */ +#define SMBcopy 0x29 /* copy */ +#define SMBmove 0x2A /* move */ +#define SMBecho 0x2B /* echo */ +#define SMBopenX 0x2D /* open and X */ +#define SMBreadX 0x2E /* read and X */ +#define SMBwriteX 0x2F /* write and X */ +#define SMBsesssetupX 0x73 /* Session Set Up & X (including User Logon) */ +#define SMBffirst 0x82 /* find first */ +#define SMBfunique 0x83 /* find unique */ +#define SMBfclose 0x84 /* find close */ +#define SMBinvalid 0xFE /* invalid command */ + +/* Extended 2.0 protocol */ +#define SMBtrans2 0x32 /* TRANS2 protocol set */ +#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */ +#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */ +#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */ +#define SMBulogoffX 0x74 /* user logoff */ + +/* NT SMB extensions. */ +#define SMBnttrans 0xA0 /* NT transact */ +#define SMBnttranss 0xA1 /* NT transact secondary */ +#define SMBntcreateX 0xA2 /* NT create and X */ +#define SMBntcancel 0xA4 /* NT cancel */ diff --git a/plugins/!NotAdopted/WinPopup/src/stdafx.cpp b/plugins/!NotAdopted/WinPopup/src/stdafx.cpp new file mode 100644 index 0000000000..d994fedc70 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/stdafx.cpp @@ -0,0 +1,22 @@ +/* + +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. +*/ + +#include "stdafx.h" diff --git a/plugins/!NotAdopted/WinPopup/src/stdafx.h b/plugins/!NotAdopted/WinPopup/src/stdafx.h new file mode 100644 index 0000000000..4c86a5164f --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/stdafx.h @@ -0,0 +1,122 @@ +/* + +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. +*/ + +// +#define WINVER 0x0500 // Windows 2000 compatible +#define _WIN32_WINNT 0x0500 // Windows 2000 compatible +#define _WIN32_WINDOWS 0x0500 // Windows 2000 compatible +#define _WIN32_IE 0x0500 // IE 5 compatible + +#define STRICT +#define WIN32_LEAN_AND_MEAN +#define NOCOMM +#define NOSERVICE +#define NOHELP +#define NOSOUND +#define NOPRINT + +//#define _ATL_NO_COM_SUPPORT +//#define _ATL_NO_EXCEPTIONS +//#define _ATL_NO_AUTOMATIC_NAMESPACE +//#define _ATL_CSTRING_NO_CRT +//#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS + +#define _CRT_SECURE_NO_WARNINGS + +// Common headers +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Miranda SDK headers +#include "statusmodes.h" +#include "newpluginapi.h" // uses m_plugins.h +#include "m_system.h" +#include "m_clist.h" +#include "m_database.h" +#include "m_langpack.h" +#include "m_netlib.h" // uses m_utils.h +#include "m_options.h" +#include "m_popup.h" +#include "m_protocols.h" +#include "m_protomod.h" +#include "m_protosvc.h" +#include "m_userinfo.h" +#include "m_chat.h" +#include "m_avatars.h" + +inline LPSTR lstrnchr(LPSTR s, const CHAR c, int n) throw () +{ + for (; n; --n, ++s) + if (c == *s) + return s; + return NULL; +} + +inline LPTSTR lstrnrchr(LPTSTR s, const TCHAR c, int n) throw () +{ + s += n; + for (; n; --n, --s) + if (c == *s) + return s; + return NULL; +} + +#include "resource.h" +#include "dllLoaderMinimal.h" +#include "network.h" +#include "winpopup_proto.h" +#include "services.h" +#include "mailslot.h" +#include "netbios_name.h" +#include "netbios.h" +#include "scanner.h" +#include "messenger.h" +#include "messagebox.h" +#include "search.h" +#include "chat.h" +#include "md5.h" +#include "options.h" +#include "user_info.h" +#include "add_dialog.h" +#include "processapi.h" +#include "smbconst.h" + +using namespace ATL; + +typedef class CComCritSecLock< CComAutoCriticalSection > CLock; + +#ifdef _DEBUG + #define ALMOST_INFINITE (INFINITE) // +#else + #define ALMOST_INFINITE (20000) // 20 +#endif diff --git a/plugins/!NotAdopted/WinPopup/src/user_info.cpp b/plugins/!NotAdopted/WinPopup/src/user_info.cpp new file mode 100644 index 0000000000..3f47e8cb80 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/user_info.cpp @@ -0,0 +1,325 @@ +/* + +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" + +#define WM_FILLTREE (WM_USER+75) + +typedef struct _FillTreeThreadData +{ + HMODULE hContact; + HWND hwndDlg; +} FillTreeThreadData; + +typedef struct _FillTreeData +{ + netbios_name_list nns; + CString host; + CString about; +} FillTreeData; + +typedef struct _DlgDataUserInfo +{ + HMODULE hContact; + HIMAGELIST hTreeImages; + bool bWorking; +} DlgDataUserInfo; + +static void FillTreeThread (LPVOID param) +{ + FillTreeThreadData* fttd = (FillTreeThreadData*)param; + + // + CString sNick = GetNick( fttd->hContact ); + if ( ! sNick.IsEmpty() ) + { + bool bGroup = IsGroup( fttd->hContact ); + + // + if ( FillTreeData* ftd = new FillTreeData ) + { + ftd->host = sNick; + + if ( ! bGroup ) + // NetBIOS- + pluginNetBIOS.GetNames( ftd->nns, ftd->host, false ); + + // + DWORD buf_size = 4096; + if ( NETRESOURCE* buf = (NETRESOURCE*)mir_alloc( buf_size ) ) + { + CString remote( _T("\\\\") ); + if ( bGroup ) + remote = (LPCTSTR)ftd->host; + else + remote += (LPCTSTR)ftd->host; + + NETRESOURCE nr = {}; + nr.dwScope = RESOURCE_GLOBALNET; + nr.lpRemoteName = const_cast (static_cast (remote)); + LPTSTR sys = NULL; + if ( WNetGetResourceInformation( &nr, buf, &buf_size, &sys ) == NO_ERROR ) + { + ftd->about = buf->lpComment; + DBWriteContactSettingTString( fttd->hContact, modname, + "About", ftd->about ); + } + + mir_free( buf ); + } + + // ... + if ( ! IsWindow( fttd->hwndDlg ) || + ! PostMessage( fttd->hwndDlg, WM_FILLTREE, 0, reinterpret_cast< LPARAM >( ftd ) ) ) + delete ftd; + } + } + + mir_free( fttd ); +} + +static INT_PTR CALLBACK DlgProcUserInfo (HWND hwndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + DlgDataUserInfo* data = reinterpret_cast (GetWindowLongPtr(hwndDlg, DWLP_USER)); + + switch (Msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault (hwndDlg); + + data = (DlgDataUserInfo*)mir_alloc( sizeof( DlgDataUserInfo ) ); + if ( ! data ) + return FALSE; + + SetWindowLongPtr (hwndDlg, DWLP_USER, reinterpret_cast (data)); + data->hTreeImages = ImageList_Create (16, 16, ILC_COLOR8 | ILC_MASK, 5, 0); + data->bWorking = false; + + 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_GOOD_NAME), IMAGE_ICON, 16, 16, LR_SHARED ))); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 2 + pluginModule, MAKEINTRESOURCE (IDI_GOOD_NAMES), IMAGE_ICON, 16, 16, LR_SHARED ))); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 3 + pluginModule, MAKEINTRESOURCE (IDI_LANA), IMAGE_ICON, 16, 16, LR_SHARED ))); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 4 + pluginModule, MAKEINTRESOURCE (IDI_COMPUTER_ERROR), IMAGE_ICON, 16, 16, LR_SHARED ))); + + TreeView_SetImageList (GetDlgItem (hwndDlg, IDC_TREE), data->hTreeImages, TVSIL_NORMAL); + + return TRUE; + } + + case WM_DESTROY: + { + SetWindowLongPtr (hwndDlg, DWLP_USER, NULL); + if (data) { + ImageList_Destroy (data->hTreeImages); + mir_free( data ); + } + break; + } + + case WM_FILLTREE: + // ... + if ( FillTreeData* ftd = reinterpret_cast (lParam) ) + { + if ( data ) + { + // + HWND hTree = GetDlgItem (hwndDlg, IDC_TREE); + TreeView_DeleteAllItems (hTree); + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = TVI_ROOT; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.pszText = const_cast (static_cast(ftd->host)); + tvis.item.iImage = tvis.item.iSelectedImage = + IsGroup( data->hContact ) ? 2 : + ( ftd->nns.GetCount() ? 0 : 4 ); + tvis.hParent = TreeView_InsertItem (hTree, &tvis); + if ( ftd->nns.GetCount() ) + { + for (POSITION pos = ftd->nns.GetHeadPosition (); pos;) + { + netbios_name& nname = ftd->nns.GetNext (pos); + CA2T textT( nname.GetANSIFullName() ); + tvis.item.pszText = (LPTSTR) (LPCTSTR) textT; + tvis.item.iImage = tvis.item.iSelectedImage = (nname.IsGroupName () ? 2 : 1); + TreeView_InsertItem (hTree, &tvis); + } + } + TreeView_Expand (hTree, tvis.hParent, TVE_EXPAND); + + SetDlgItemText (hwndDlg, IDC_ABOUT, ftd->about); + + data->bWorking = false; + } + delete ftd; + } + 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_INFOCHANGED: + { + // "Always Online" + BOOL b = DBGetContactSettingByte ( data->hContact, modname, + "AlwaysOnline", FALSE ); + CheckDlgButton (hwndDlg, IDC_ONLINE_CHECK, + (UINT)( b ? BST_CHECKED : BST_UNCHECKED ) ); + EnableWindow (GetDlgItem (hwndDlg, IDC_ONLINE_CHECK), + data->hContact != NULL ); + + // "Legacy online status detection" + CheckDlgButton( hwndDlg, IDC_CHECK00FORONLINE,(UINT)( + IsLegacyOnline( data->hContact ) ? BST_CHECKED : BST_UNCHECKED ) ); + EnableWindow( GetDlgItem( hwndDlg, IDC_CHECK00FORONLINE ), + data->hContact != NULL ); + + // "Group Contact" + CheckDlgButton (hwndDlg, IDC_GROUP, (UINT)( + IsGroup( data->hContact ) ? BST_CHECKED : BST_UNCHECKED ) ); + EnableWindow( GetDlgItem( hwndDlg, IDC_GROUP ), + data->hContact != NULL ); + + // NetBIOS- + if ( data && ! data->bWorking ) + { + HWND hTree = GetDlgItem (hwndDlg, IDC_TREE); + data->bWorking = true; + TreeView_DeleteAllItems (hTree); + TVINSERTSTRUCT tvis = { 0 }; + tvis.hParent = TVI_ROOT; + tvis.hInsertAfter = TVI_LAST; + tvis.item.mask = TVIF_TEXT; + tvis.item.pszText = TranslateT ("Retrieving..."); + TreeView_InsertItem (hTree, &tvis); + + SetDlgItemText (hwndDlg, IDC_ABOUT, _T("")); + + if ( FillTreeThreadData* fttd = (FillTreeThreadData*)mir_alloc( sizeof( FillTreeThreadData ) ) ) + { + fttd->hContact = data->hContact; + fttd->hwndDlg = hwndDlg; + mir_forkthread( FillTreeThread, fttd ); + } + } + break; + } + + case PSN_KILLACTIVE: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); + return TRUE; + + case PSN_APPLY: + { + BOOL f_now = (IsDlgButtonChecked (hwndDlg, IDC_ONLINE_CHECK) == + BST_CHECKED) ? TRUE : FALSE; + BOOL f_old = DBGetContactSettingByte ( data->hContact, modname, + "AlwaysOnline", FALSE ); + DBWriteContactSettingByte (data->hContact, modname, + "AlwaysOnline", (BYTE)( f_now ? TRUE : FALSE ) ); + if ( ! f_old && f_now ) + SetContactStatus( data->hContact, ID_STATUS_ONLINE, true ); + else if ( f_old && ! f_now ) + SetContactStatus( data->hContact, ID_STATUS_OFFLINE, true ); + + SetLegacyOnline( data->hContact, ( IsDlgButtonChecked( hwndDlg, + IDC_CHECK00FORONLINE ) == BST_CHECKED ) ); + + SetGroup( data->hContact, + IsDlgButtonChecked( hwndDlg, IDC_GROUP ) == BST_CHECKED ); + + SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR ); + return TRUE; + } + } + } + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDC_ONLINE_CHECK: + { + BOOL f_now = (IsDlgButtonChecked (hwndDlg, IDC_ONLINE_CHECK) == + BST_CHECKED) ? TRUE : FALSE; + BOOL f_old = DBGetContactSettingByte ( data->hContact, modname, + "AlwaysOnline", FALSE ); + + if ( f_old != f_now ) + PropSheet_Changed (GetParent (hwndDlg), hwndDlg); + else + PropSheet_UnChanged (GetParent (hwndDlg), hwndDlg); + + return TRUE; + } + + case IDC_CHECK00FORONLINE: + { + PropSheet_Changed (GetParent (hwndDlg), hwndDlg); + return TRUE; + } + + case IDC_GROUP: + { + PropSheet_Changed (GetParent (hwndDlg), hwndDlg); + return TRUE; + } + } + break; + } + } + return FALSE; +} + +int __cdecl USERINFO_INITIALISE (WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)lParam; + if ( ! hContact || ( IsMyContact( hContact ) /*&& ! IsChatRoom( hContact )*/ ) ) + { + OPTIONSDIALOGPAGE odp = {0}; + odp.cbSize = sizeof(odp); + odp.hInstance = pluginModule; + odp.pszTemplate = MAKEINTRESOURCEA( IDD_USERINFO ); + odp.ptszTitle = LPGENT(modtitle); + odp.flags = ODPF_TCHAR; + odp.pfnDlgProc = DlgProcUserInfo; + Options_AddPage(wParam, &odp); + } + return 0; +} diff --git a/plugins/!NotAdopted/WinPopup/src/user_info.h b/plugins/!NotAdopted/WinPopup/src/user_info.h new file mode 100644 index 0000000000..8b7b0b124e --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/user_info.h @@ -0,0 +1,22 @@ +/* + +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. +*/ + +int __cdecl USERINFO_INITIALISE (WPARAM wParam, LPARAM lParam); diff --git a/plugins/!NotAdopted/WinPopup/src/winpopup_proto.cpp b/plugins/!NotAdopted/WinPopup/src/winpopup_proto.cpp new file mode 100644 index 0000000000..53e8245ec6 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/winpopup_proto.cpp @@ -0,0 +1,1193 @@ +/* + +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" + +volatile WPARAM pluginRequestedStatus = ID_STATUS_OFFLINE; +volatile WPARAM pluginCurrentStatus = ID_STATUS_OFFLINE; +CIntStrMap pluginStatusMessage; +CString pluginMachineName; +CString pluginUserName; +CString pluginDomainName; +HMODULE pluginModule = NULL; +volatile bool pluginBusy = false; +volatile bool pluginInstalled = false; +volatile bool pluginInitialized = false; +HANDLE pluginNetLibUser = NULL; +HANDLE pluginInternalState = NULL; +bool pluginChatEnabled = false; +OSVERSIONINFO pluginOS = { sizeof( OSVERSIONINFO ) }; + +CComAutoCriticalSection pluginGuard; // : +CThreadContactMap pluginAwayThreadMap; // - +CThreadContactMap pluginAvatarThreadMap; // + +CString GetNick(HANDLE hContact) +{ + CString sNick; + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( hContact, modname, "Nick", &dbv ) ) + { + sNick = dbv.ptszVal; + DBFreeVariant( &dbv ); + } + return sNick; +} + +void SetNick(HANDLE hContact, LPCTSTR szNick) +{ + DBWriteContactSettingTString( hContact, modname, "Nick", szNick ); +} + +CComAutoCriticalSection _LOG_SECTION; + +int LOG(const char *fmt,...) +{ + CComCritSecLock< CComAutoCriticalSection > _Lock( _LOG_SECTION ); + + int ret = 0; + const int size = 512; + if ( char* szText = (char*)mir_alloc( size ) ) + { + *szText = 0; + va_list va; + va_start( va, fmt ); + mir_vsnprintf( szText, size, fmt, va ); + va_end( va ); + ret = CallService( MS_NETLIB_LOG, (WPARAM)pluginNetLibUser, (LPARAM)szText ); + mir_free( szText ); + } + return ret; +} + +void GetAvatarCache(LPTSTR szPath) +{ + // + if ( ServiceExists( MS_UTILS_REPLACEVARS ) ) + { + LPTSTR szAvatarCache = Utils_ReplaceVarsT( + _T("%miranda_avatarcache%\\") modname_t _T("\\") ); + if ( szAvatarCache && szAvatarCache != (LPTSTR)0x80000000 ) + { + lstrcpyn( szPath, szAvatarCache, MAX_PATH ); + + // + CallService( MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szPath ); + return; + } + } + + // + char szProfilePath[ MAX_PATH ], szProfileName[ MAX_PATH ]; + CallService( MS_DB_GETPROFILEPATH, MAX_PATH, (LPARAM)szProfilePath ); + CallService( MS_DB_GETPROFILENAME, MAX_PATH, (LPARAM)szProfileName ); + char *pos = strrchr( szProfileName, '.' ); + if ( lstrcmpA( pos, ".dat" ) == 0 ) + *pos = 0; + lstrcpy( szPath, CA2T( szProfilePath ) ); + lstrcat( szPath, _T("\\") ); + lstrcat( szPath, CA2T( szProfileName ) ); + lstrcat( szPath, _T("\\AvatarCache\\") modname_t _T("\\") ); + + // + CallService( MS_UTILS_CREATEDIRTREET, 0, (LPARAM)szPath ); + return; +} + +static LONG cookie = (LONG)GetTickCount(); + +HANDLE GenerateCookie() +{ + return (HANDLE)InterlockedIncrement( &cookie ); +} + +DWORD time() +{ + LARGE_INTEGER lft = {}; + GetSystemTimeAsFileTime ((FILETIME*) &lft); + return (DWORD) ((lft.QuadPart - 116444736000000000) / 10000000); +} + +bool IsMyContact(HANDLE hContact) +{ + if ( ! hContact ) + // + return false; + + char* proto = (char*)CallService( MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0 ); + if ( ! proto ) + // + return false; + + if ( lstrcmpA( proto, modname ) ) + // + return false; + + // + return true; +} + +void SetPluginStatus(WPARAM status) +{ + WPARAM old = pluginCurrentStatus; + pluginCurrentStatus = status; + if (pluginInstalled) + { + ProtoBroadcastAck (modname, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, + (HANDLE) old, (LPARAM) pluginCurrentStatus); + + if ( old != pluginCurrentStatus && + pluginCurrentStatus >= ID_STATUS_OFFLINE && + pluginCurrentStatus <= ID_STATUS_OUTTOLUNCH ) + { + pluginNetBIOS.BroadcastStatus(); + } + } +} + +bool InternalStartup() +{ + _ASSERT( pluginInstalled == true ); + + LOG ("Startup begin"); + + ResetEvent( pluginInternalState ); + + bool err = false; + + BYTE method = (BYTE) DBGetContactSettingByte (NULL, modname, "SendMethod", 0); + if ( method == 2 ) + { + // " " + if (pluginMessenger.Create (TRUE)) + err = true; + LOG ("Startup : Messenger"); + + // NetBIOS + if (!pluginNetBIOS.Create (FALSE)) + err = true; + LOG ("Startup : NetBIOS"); + } + else + { + // " " + if (pluginMessenger.Create (FALSE)) + err = true; + + // + if ( ! pluginMailslot.Create( MESSENGER_MAIL ) ) + err = true; + LOG ("Startup : Mailslot"); + + // NetBIOS + if (!pluginNetBIOS.Create (TRUE)) + err = true; + LOG ("Startup : NetBIOS"); + } + + // + if (!pluginScanner.Create ()) + err = true; + LOG ("Startup : Scanner"); + + LOG ("Startup end"); + + return !err; +} + +void InternalShutdown () +{ + LOG ("Shutdown begin"); + + // + pluginSearch.AskForDestroy(); + pluginMailslot.AskForDestroy(); + pluginScanner.AskForDestroy(); + pluginNetBIOS.AskForDestroy(); + pluginMessenger.AskForDestroy(); + + // () + pluginMailslot.Destroy (); + LOG ("Shutdown : Mailslot"); + + // (, ) + pluginSearch.Destroy(); + LOG ("Shutdown : Search"); + + // NetBIOS () + pluginNetBIOS.Destroy (); + LOG ("Shutdown : NetBIOS"); + + // (, ) + pluginScanner.Destroy (); + LOG ("Shutdown : Scanner"); + + // " " (, ) + pluginMessenger.Destroy (); + LOG ("Shutdown : Messenger"); + + LOG ("Shutdown end"); + SetEvent( pluginInternalState ); +} + +void GotoOnline () +{ + if ( pluginCurrentStatus != ID_STATUS_OFFLINE ) + { + // + if ( pluginCurrentStatus != ID_STATUS_CONNECTING ) + { + // + SetPluginStatus (pluginRequestedStatus); + return; + } + } + + SetPluginStatus (ID_STATUS_CONNECTING); + + if (!pluginInstalled || !pluginInitialized || pluginBusy) + // ( ) + return; + pluginBusy = true; + + // + mir_forkthread( GotoOnlineTread, NULL ); +} + +void GotoOffline() +{ + // + SetPluginStatus (ID_STATUS_OFFLINE); + + if (pluginBusy) + // + return; + pluginBusy = true; + + // + FOR_EACH_CONTACT( hContact ) { + SetContactStatus (hContact, ID_STATUS_OFFLINE, true); + } + + // + mir_forkthread( GotoOfflineTread, NULL ); +} + +void GotoOnlineTread(LPVOID /* status */) +{ + // + InternalStartup(); + pluginBusy = false; + Sleep( 1000 ); + + // + if ( ! pluginInstalled || pluginRequestedStatus == ID_STATUS_OFFLINE ) + // , + GotoOffline (); + else + // , + SetPluginStatus (pluginRequestedStatus); +} + +void GotoOfflineTread(LPVOID /* status */) +{ + // + InternalShutdown (); + pluginBusy = false; + Sleep( 1000 ); + + // + if ( pluginInstalled && pluginRequestedStatus != ID_STATUS_OFFLINE ) + // , + GotoOnline (); + else + // + SetPluginStatus (ID_STATUS_OFFLINE); +} + +void GetAwayMsgThread(LPVOID param) +{ + // "" + Sleep( 250 ); + + ContactData* data = (ContactData*)param; + + bool ret = false; + + bool bGroup = IsGroup( data->hContact ); + CString sNick = GetNick( data->hContact ); + if ( ! bGroup && ! sNick.IsEmpty() ) + { + ThreadEvent te = { CreateEvent( NULL, TRUE, FALSE, NULL ), data->cookie }; + + // + { + CLock oLock( pluginGuard ); + pluginAwayThreadMap.SetAt( data->hContact, te ); + } + + // - + ret = pluginNetBIOS.AskAway( netbios_name( sNick, 0x03, false ) ); + + // (3 ) + ret = ret && ( WaitForSingleObject( te.evt, 3000 ) == WAIT_OBJECT_0 ); + + // + { + CLock oLock( pluginGuard ); + pluginAwayThreadMap.Lookup( data->hContact, te ); + pluginAwayThreadMap.RemoveKey( data->hContact ); + } + + CloseHandle( te.evt ); + } + + if ( ! ret ) + { + // + ProtoBroadcastAck (modname, data->hContact, ACKTYPE_AWAYMSG, + ACKRESULT_SUCCESS /* ACKRESULT_FAILED */, data->cookie, (LPARAM)"" ); + LOG( "Get away message failed" ); + } + + delete data; +} + +void SetContactAway(HANDLE hContact, LPCSTR away) +{ + if ( ! pluginInstalled ) + return; + + // + bool ret = false; + ThreadEvent te = {}; + { + CLock oLock( pluginGuard ); + if ( pluginAwayThreadMap.Lookup( hContact, te ) ) + { + SetEvent( te.evt ); + ret = true; + } + } + + if ( ret ) + { + // - + ProtoBroadcastAck( modname, hContact, ACKTYPE_AWAYMSG, + ACKRESULT_SUCCESS, te.cookie, (LPARAM)away ); + } + else + { + // - + } +} + +void GetInfoThread(LPVOID param) +{ + // "" + Sleep( 500 ); + + HANDLE hContact = (HANDLE)param; + + ProtoBroadcastAck( modname, hContact, ACKTYPE_GETINFO, + ACKRESULT_SUCCESS, (HANDLE)0, 0 ); +} + +void Autoanswer(HANDLE hContact) +{ + switch ( pluginCurrentStatus ) + { + case ID_STATUS_AWAY: + case ID_STATUS_DND: + case ID_STATUS_NA: + case ID_STATUS_OCCUPIED: + case ID_STATUS_ONTHEPHONE: + case ID_STATUS_OUTTOLUNCH: + { + CString msg; + if ( pluginStatusMessage.Lookup( pluginCurrentStatus, msg ) ) + { + // + CString answer (TranslateT ("Auto-reply")); + answer += _T(":\r\n"); + answer += msg; + DWORD foo; + SendContactMessage( hContact, answer, foo ); + + // + DBEVENTINFO ei = {}; + ei.cbSize = sizeof (DBEVENTINFO); + ei.szModule = modname; + ei.timestamp = time(); + ei.flags = DBEF_SENT; + ei.eventType = EVENTTYPE_MESSAGE; + ei.cbBlob = (DWORD)answer.GetLength () + 1; + ei.pBlob = (PBYTE) (LPCTSTR) answer; + CallServiceSync( MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&ei ); + } + } + break; + } +} + +void ReceiveContactMessage(LPCTSTR msg_from, LPCTSTR msg_to, LPCTSTR msg_text, int msg_len) +{ + if ( ! pluginInstalled ) + return; + + CString from( msg_from ); + CString to( msg_to ); + CString text( msg_text, msg_len ); + + from.MakeUpper(); + to.MakeUpper(); + + // ? + if ( IsItMe( from ) ) + { + LOG ( "Ignoring my message." ); + return; + } + + // + Normalize( text ); + + // ? + if (DBGetContactSettingByte (NULL, modname, "Filter-dups", TRUE)) + { + // + static FILETIME last_time = { 0, 0 }; + FILETIME current_time; + GetSystemTimeAsFileTime (¤t_time); + ULONGLONG elapsed = + ((ULONGLONG) current_time.dwLowDateTime | + (ULONGLONG) current_time.dwHighDateTime << 32) - + ((ULONGLONG) last_time.dwLowDateTime | + (ULONGLONG) last_time.dwHighDateTime << 32); + + // MD5- + MD5Context ctx; + md5init (&ctx); + md5update (&ctx, (const unsigned char*)(LPCTSTR)from, + from.GetLength() * sizeof (TCHAR)); + unsigned char digest_from_current [16] = {0}; + static unsigned char digest_from_last [16] = {0}; + md5final (digest_from_current, &ctx); + + // MD5- + md5init (&ctx); + md5update (&ctx, (const unsigned char*)(LPCTSTR)text, + text.GetLength() * sizeof (TCHAR)); + unsigned char digest_text_current [16] = {0}; + static unsigned char digest_text_last [16] = {0}; + md5final (digest_text_current, &ctx); + + // 2 + if (elapsed < 20000000) + { + // + if (memcmp (digest_from_current, digest_from_last, 16) == 0) + { + // + if (memcmp (digest_text_current, digest_text_last, 16) == 0) + { + // + LOG ("Duplicate message detected"); + return; + } + } + } + last_time = current_time; + CopyMemory (digest_from_last, digest_from_current, 16); + CopyMemory (digest_text_last, digest_text_current, 16); + } + +#ifdef CHAT_ENABLED + if ( ! IsItMe( to ) && pluginChatEnabled ) // ? + { + // + if ( ChatNewSession( to ) ) + { + // + ATLVERIFY( ChatAddGroup( to, _T("Normal") ) ); + + // + ATLVERIFY( ChatJoinMe( to, _T("Normal") ) ); + + // " " + ATLVERIFY( ChatJoinUser( to, from, _T("Normal") ) ); + + // + ATLVERIFY( ChatInitDone( to ) ); + + // - + ATLVERIFY( ChatOnline( to ) ); + + // + ATLVERIFY( ChatMessage( to, from, text ) ); + } + } + else +#endif // CHAT_ENABLED + { + // + HANDLE hContact = AddToListByName( from, 0, NULL, false, false ); + if ( hContact ) + { + PROTORECVEVENT pre = { 0 }; + pre.timestamp = time (); + CT2A textA( text ); + pre.szMessage = (LPSTR)(LPCSTR)textA; + CCSDATA ccs = { 0 }; + ccs.szProtoService = PSR_MESSAGE; + ccs.hContact = hContact; + DBDeleteContactSetting (ccs.hContact, "CList", "Hidden"); + ccs.lParam = (LPARAM) ⪯ + CallServiceSync (MS_PROTO_CHAINRECV, 0, (LPARAM) &ccs); + + // + SetContactStatus( hContact, contact_scanner::ScanContact( hContact ), true ); + + // - + if ( DBGetContactSettingByte( NULL, modname, "Auto-answer", FALSE ) ) + Autoanswer( hContact ); + } + } +} + +void Normalize(CString& msg) +{ + enum { CR, LF, NOP }; + int line_break = NOP; + int i = 0; + for (; i < msg.GetLength (); ++i) + { + switch (msg [i]) + { + case _T('\r'): + case _T('\xb6'): + switch (line_break) + { + case CR: // CRCR + case LF: // LFCR + msg.Delete (i); + msg.Delete (i - 1); + msg.Insert (i - 1, _T('\r')); + msg.Insert (i, _T('\n')); + line_break = NOP; + break; + default: // xxCR + line_break = CR; + } + break; + case _T('\n'): + switch (line_break) + { + case CR: // CRLF + line_break = NOP; + break; + case LF: // LFLF + msg.Delete (i); + msg.Delete (i - 1); + msg.Insert (i - 1, _T('\r')); + msg.Insert (i, _T('\n')); + line_break = NOP; + break; + default: // xxLF + line_break = LF; + } + break; + default: + switch (line_break) + { + case CR: // CR LF + case LF: // LF CR + msg.Delete (i - 1); + msg.Insert (i - 1, _T('\r')); + msg.Insert (i, _T('\n')); + ++i; + break; + } + line_break = NOP; + } + } + switch (line_break) + { + case CR: // CR LF + case LF: // LF CR + msg.Delete (i - 1); + msg.Insert (i - 1, _T('\r')); + msg.Insert (i, _T('\n')); + break; + } +} + +HANDLE AddToListByName(const CString& sName, WPARAM flags, LPCTSTR about, bool bInteractive, bool bGroup) +{ + ip addr = INADDR_NONE; + CString sShortName( sName ); + + if ( ! bGroup ) + { + // IP + if ( addr == INADDR_NONE ) + addr = ResolveToIP( sShortName ); + + // NetBIOS- + if ( addr == INADDR_NONE ) + addr = pluginNetBIOS.FindNameIP( sName ); + + // + if ( addr == INADDR_NONE && bInteractive ) + { + if ( MessageBox( NULL, + TranslateT("Cannot resolve contacts IP-address. Add it anyway?"), + modname_t, MB_YESNO | MB_ICONQUESTION ) != IDYES ) + { + return NULL; + } + } + } + + // + HANDLE hContact = GetContact( sShortName ); + if ( ! hContact ) + { + // + hContact = (HANDLE)CallService( MS_DB_CONTACT_ADD, 0, 0 ); + if ( hContact ) + { + CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)modname ); + SetNick( hContact, sShortName ); + SetGroup( hContact, bGroup ); + DBWriteContactSettingTString( hContact, "CList", "MyHandle", sShortName ); + DBWriteContactSettingByte( hContact, "CList", "NotOnList", 1 ); + DBWriteContactSettingByte( hContact, "CList", "Hidden", 1 ); + SetContactIP( hContact, addr ); + SetElapsed( hContact, "IPTime" ); + if ( about ) + DBWriteContactSettingTString( hContact, modname, "About", about ); + + contact_scanner::ScanContact( hContact ); + } + } + if ( hContact && ! ( flags & PALF_TEMPORARY ) && + DBGetContactSettingByte( hContact, "CList", "NotOnList", 1 ) ) + { + // + DBDeleteContactSetting( hContact, "CList", "NotOnList" ); + DBDeleteContactSetting( hContact, "CList", "Hidden" ); + } + return hContact; +} + +DWORD GetElapsed (HANDLE hContact, const char* name) +{ + FILETIME current = {}; + GetSystemTimeAsFileTime (¤t); + LARGE_INTEGER currentL = {}; + currentL.LowPart = current.dwLowDateTime; + currentL.HighPart = (LONG)current.dwHighDateTime; + LARGE_INTEGER lastseenL = {}; + lastseenL.LowPart = DBGetContactSettingDword (hContact, modname, + CStringA (name) + "L", 0); + lastseenL.HighPart = (LONG)DBGetContactSettingDword (hContact, modname, + CStringA (name) + "H", 0); + return (DWORD) (((currentL.QuadPart - lastseenL.QuadPart) / 10000000L) & 0xffffffff); +} + +void SetElapsed (HANDLE hContact, const char* name) +{ + FILETIME current = {}; + GetSystemTimeAsFileTime (¤t); + DBWriteContactSettingDword (hContact, modname, + CStringA (name) + "L", current.dwLowDateTime); + DBWriteContactSettingDword (hContact, modname, + CStringA (name) + "H", current.dwHighDateTime); +} + +HANDLE GetContact (ip addr) +{ + // + FOR_EACH_CONTACT( hContact ) + { + // + ip contact_addr = DBGetContactSettingDword (hContact, modname, "IP", 0); + if (contact_addr && (contact_addr == addr)) + // + break; + } + return hContact; +} + +HANDLE GetContact (LPCTSTR name) +{ + // + FOR_EACH_CONTACT( hContact ) + { + // + CString sNick = GetNick( hContact ); + if ( ! sNick.IsEmpty() ) + { + // + if ( sNick.CompareNoCase( name ) == 0 ) + // + break; + } + } + return hContact; +} + +void SetContactStatus (HANDLE hContact, int status, bool simple) +{ + if ( ! pluginInstalled ) + return; + + SetElapsed (hContact, "LastSeen"); + +#ifdef CHAT_ENABLED + if ( IsChatRoom( hContact ) ) + { + CString sSession = GetChatSession( hContact ); + if ( pluginChatEnabled && ! sSession.IsEmpty() ) + { + if ( status != ID_STATUS_OFFLINE ) + ChatOnline( sSession ); + else + ChatOffline( sSession ); + } + } + else +#endif // CHAT_ENABLED + { + int ns = DBGetContactSettingWord (hContact, modname, "Status", -1); + if ( ns != status ) + { + // + if ( ! simple ) + // + DBWriteContactSettingWord (hContact, modname, "Status", (WORD) status); + else if ( ns == -1 || ns == ID_STATUS_OFFLINE || status != ID_STATUS_ONLINE ) + // + DBWriteContactSettingWord (hContact, modname, "Status", (WORD) status); + } + } +} + +void GetAvatarInfoThread(LPVOID param) +{ + // "" + Sleep( 500 ); + + ContactData* data = (ContactData*)param; + + bool ret = false; + ThreadEvent te = { CreateEvent( NULL, TRUE, FALSE, NULL ), data->cookie }; + PROTO_AVATAR_INFORMATION pai = { sizeof( PROTO_AVATAR_INFORMATION ), data->hContact }; + + TCHAR szPath[ MAX_PATH ]; + GetAvatarCache( szPath ); + + // + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( data->hContact, modname, "AvatarFile", &dbv ) ) + { + lstrcat( szPath, dbv.ptszVal ); + + if ( GetFileAttributes( szPath ) != INVALID_FILE_ATTRIBUTES ) + { + ret = true; + + lstrcpyA( pai.filename, CT2A( szPath ) ); + + // + LPCTSTR szExt = _tcsrchr( dbv.ptszVal, _T('.') ); + if ( ! szExt ) + { + pai.format = PA_FORMAT_UNKNOWN; + } + else if ( lstrcmpi( szExt, _T(".png") ) == 0 || lstrcmpi( szExt, _T(".dat") ) == 0 ) + { + pai.format = PA_FORMAT_PNG; + } + else if ( lstrcmpi( szExt, _T(".jpg") ) == 0 ) + { + pai.format = PA_FORMAT_JPEG; + } + else if ( lstrcmpi( szExt, _T(".ico") ) == 0 ) + { + pai.format = PA_FORMAT_ICON; + } + else if ( lstrcmpi( szExt, _T(".bmp") ) == 0 ) + { + pai.format = PA_FORMAT_BMP; + } + else if ( lstrcmpi( szExt, _T(".gif") ) == 0 ) + { + pai.format = PA_FORMAT_GIF; + } + else if ( lstrcmpi( szExt, _T(".swf") ) == 0 ) + { + pai.format = PA_FORMAT_SWF; + } + else if ( lstrcmpi( szExt, _T(".xml") ) == 0 ) + { + pai.format = PA_FORMAT_XML; + } + else + { + pai.format = PA_FORMAT_UNKNOWN; + } + } + DBFreeVariant( &dbv ); + } + if ( ret ) + { + ProtoBroadcastAck( modname, data->hContact, ACKTYPE_AVATAR, + ACKRESULT_SUCCESS, &pai, 0 ); + LOG( "Returned cached avatar." ); + } + else + { + bool bGroup = IsGroup( data->hContact ); + CString sNick = GetNick( data->hContact ); + if ( ! bGroup && ! sNick.IsEmpty() ) + { + // + ProtoBroadcastAck( modname, data->hContact, ACKTYPE_AVATAR, + ACKRESULT_SENTREQUEST, &pai, 0 ); + + // + { + CLock oLock( pluginGuard ); + pluginAvatarThreadMap.SetAt( data->hContact, te ); + } + + ret = pluginNetBIOS.AskAvatar( netbios_name( sNick, 0x03 ) ); + + // (3 ) + ret = ret && ( WaitForSingleObject( te.evt, 3000 ) == WAIT_OBJECT_0 ); + + // + { + CLock oLock( pluginGuard ); + pluginAvatarThreadMap.Lookup( data->hContact, te ); + pluginAvatarThreadMap.RemoveKey( data->hContact ); + } + } + if ( ! ret ) + { + ProtoBroadcastAck( modname, data->hContact, ACKTYPE_AVATAR, + ACKRESULT_FAILED, &pai, 0 ); + LOG( "Get avatar failed" ); + } + } + + if ( te.evt ) + CloseHandle( te.evt ); + + delete data; +} + +void SetContactAvatar(HANDLE hContact, LPCVOID pBuffer, DWORD nLength) +{ + if ( ! pluginInstalled ) + return; + + PROTO_AVATAR_INFORMATION pai = { sizeof( PROTO_AVATAR_INFORMATION ), hContact }; + + CString sFilename, sNick = GetNick( hContact ); + if ( sNick.IsEmpty() || sNick.FindOneOf( _T("/\\*?:|\"<>%") ) != -1 ) + { + // + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( hContact, modname, "AvatarFile", &dbv ) ) + { + sFilename = dbv.ptszVal; + DBFreeVariant( &dbv ); + } + else + // + sFilename.Format( _T("%08x_avt"), (DWORD)hContact ); + } + else + // + sFilename.Format( _T("%s_%08x_avt"), sNick, (DWORD)hContact ); + + // + if ( ! memcmp( pBuffer, "%PNG", 4 ) ) + { + pai.format = PA_FORMAT_PNG; + sFilename += _T(".png"); + } + else if ( *(DWORD*)pBuffer == 0xE0FFD8FFul || *(DWORD*)pBuffer == 0xE1FFD8FFul ) + { + pai.format = PA_FORMAT_JPEG; + sFilename += _T(".jpg"); + } + else if ( *(DWORD*)pBuffer == 0x00010000 ) + { + pai.format = PA_FORMAT_ICON; + sFilename += _T(".ico"); + } + else if ( ! memcmp( pBuffer, "BM", 2 ) ) + { + pai.format = PA_FORMAT_BMP; + sFilename += _T(".bmp"); + } + else if ( ! memcmp( pBuffer, "GIF", 3 ) ) + { + pai.format = PA_FORMAT_GIF; + sFilename += _T(".gif"); + } + else if ( ! memcmp( pBuffer, "CWS", 3 ) ) + { + pai.format = PA_FORMAT_SWF; + sFilename += _T(".swf"); + } + else if ( ! memcmp( pBuffer, "hContact, data->text, dwLastError ) ) + { + ProtoBroadcastAck ( modname, data->hContact, ACKTYPE_MESSAGE, + ACKRESULT_SUCCESS, data->cookie, 0 ); + } + else + { + // + CString msg, buf; + GetErrorMessage (dwLastError, buf); + msg.Format( _T("%s\r\n%s"), TranslateT ("Cannot send message"), (LPCTSTR)buf); + ProtoBroadcastAck (modname, data->hContact, ACKTYPE_MESSAGE, + ACKRESULT_FAILED, data->cookie, (LPARAM)(LPCTSTR)msg ); + + // + WarningBox( data->hContact, dwLastError, TranslateT("Cannot send message") ); + } + + delete data; +} + +bool IsItMe(LPCTSTR name) +{ + return ! pluginMachineName.CompareNoCase( name ) || + ! pluginUserName.CompareNoCase( name ); +} + +void EnumWorkgroups(CAtlList< CString >& lst, LPNETRESOURCE hRoot) +{ + HANDLE hEnum = NULL; + DWORD res = WNetOpenEnum( RESOURCE_GLOBALNET, RESOURCETYPE_ANY, + RESOURCEUSAGE_CONTAINER, hRoot, &hEnum ); + if ( res == NO_ERROR ) + { + for (;;) + { + DWORD cCount = 1; + DWORD BufferSize = 4096; + char* Buffer = (char*)mir_alloc( BufferSize ); + if ( ! Buffer ) + break; + res = WNetEnumResource( hEnum, &cCount, Buffer, &BufferSize ); + if ( res == NO_ERROR ) + { + LPNETRESOURCE lpnr = (LPNETRESOURCE)Buffer; + if ( lpnr->dwDisplayType == RESOURCEDISPLAYTYPE_DOMAIN ) + { + CharUpper ( lpnr->lpRemoteName ); + lst.AddTail( lpnr->lpRemoteName ); + } + else if ( ( lpnr->dwUsage & 0xffff ) == RESOURCEUSAGE_CONTAINER ) + { + EnumWorkgroups( lst, lpnr ); + } + mir_free( Buffer ); + } + else + { + mir_free( Buffer ); + break; + } + } + WNetCloseEnum (hEnum); + } +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID /*lpReserved*/) +{ + pluginModule = hModule; + return TRUE; +} diff --git a/plugins/!NotAdopted/WinPopup/src/winpopup_proto.h b/plugins/!NotAdopted/WinPopup/src/winpopup_proto.h new file mode 100644 index 0000000000..6016a583f8 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/src/winpopup_proto.h @@ -0,0 +1,318 @@ +/* + +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. +*/ + +// Miranda IM +// +// : +// Nick String - (.) +// User String - (.) +// Workgroup String - (.) +// Auto-answer BYTE - - (-: 0) +// Filter-dups BYTE - (-: 1) +// SendMethod BYTE - : 0 - mailslot, 1 - NetBIOS, 2 - Messenger (-: 0) +// RegisterNick BYTE - NetBIOS Nick<01> Nick<03> (-: 1) +// RegisterUser BYTE - NetBIOS User<03> (-: 1) +// RegisterStatus BYTE - NetBIOS MNS_STATUS (-: 1) +// Check00ForOnline BYTE - NetBIOS Nick<00> , ( : 0) ( AlwaysCheck00ForOnline) +// AvatarFile String - +// +// : +// Nick String - +// IP DWORD - +// RealIP DWORD - ( IP) +// IPTimeL DWORD - +// IPTimeH DWORD +// LastSeenL DWORD - +// LastSeenH DWORD +// PingCounter WORD - ( ) +// Status WORD - +// About String - +// AlwaysOnline BYTE - online- +// Check00ForOnline BYTE - NetBIOS Nick<00> ( : 0) +// AvatarFile String - +// Group BYTE - 1/0 - +// +// : +// ChatRoom BYTE - 1/0 - +// ChatRoomID String - , +// +// CList ( ) : +// MyHandle String - (. ) +// NotOnList BYTE - +// Hidden BYTE - +// +// Icons ( ) : +// WinPopup Protocol40071 String - +// WinPopup Protocol40072 String - +// WinPopup Protocol40073 String - +// WinPopup Protocol40074 String - +// WinPopup Protocol40075 String - +// WinPopup Protocol40076 String - +// WinPopup Protocol40077 String - +// WinPopup Protocol40078 String - +// WinPopup Protocol40079 String - +// WinPopup Protocol40080 String - + +// +#define modname "WinPopup Protocol" +#define modname_t _T( modname ) +// +#define modtitle "WinPopup" +#define modtitle_t _T( modtitle ) +// " " +#define T_STOP_ERROR TranslateT("Cannot stop Messenger service") +// " " +#define T_START_ERROR TranslateT("Cannot start Messenger service") +// " " +#define T_ENABLE_ERROR TranslateT("Cannot enable Messenger service") +// " " +#define T_CREATE_ERROR TranslateT("Cannot create receiving mailslot") +// "" +#define T_ERROR TranslateT("Error") +// Messenger +#define MESSENGER _T("Messenger") +// Messenger +#define MESSENGER_MAIL _T("messngr") +// IP (3 ) +#define MAX_TRUSTED_IP_TIME 3*60*60 +// ( 30 ) +#define MIN_PING_INTERVAL 30 + +typedef struct _ContactData +{ + HANDLE cookie; // + HANDLE hContact; // +} ContactData; + +typedef struct _SendMsgData +{ + HANDLE cookie; // + HANDLE hContact; // + CString text; +} SendMsgData; + +typedef struct _ThreadEvent +{ + HANDLE evt; // + HANDLE cookie; // +} ThreadEvent; + +typedef CAtlMap < WPARAM, CString > CIntStrMap; +typedef CAtlMap < HANDLE, ThreadEvent > CThreadContactMap; + +// ANSI OEM +class COemString +{ +public: + COemString(LPCTSTR ansi) : + len( (size_t)lstrlen( ansi ) + 1 ), + pos( 0 ) + { + oem = (LPSTR)mir_alloc( len ); + CharToOemBuff( ansi, oem, (DWORD)len ); + } + + ~COemString() + { + mir_free( oem ); + } + + inline operator LPCSTR() const + { + return oem + pos; + } + + // ( null) + inline int GetLength() const + { + return (int)( len - pos - 1 ); + } + + // "" + inline void CutFromStart(int n) + { + if ( GetLength() > n ) + pos += n; + else + pos = len - 1; + } + +protected: + size_t len; + size_t pos; + LPSTR oem; +}; + +// OEM ANSI +class CAnsiString +{ +public: + CAnsiString(LPCSTR oem) : + len( lstrlenA( oem ) + 1 ), + pos( 0 ) + { + ansi = (LPTSTR)mir_alloc( len * sizeof( TCHAR ) ); + OemToCharBuff( oem, ansi, (DWORD)len ); + } + ~CAnsiString() + { + mir_free( ansi ); + } + inline operator LPCTSTR() const + { + return ansi + pos; + } + // ( null) + inline int GetLength() const + { + return len - pos - 1; + } + // "" + inline void CutFromStart(int n) + { + if ( len - pos - 1 > n ) + pos += n; + else + pos = len - 1; + } +protected: + int len; + int pos; + LPTSTR ansi; +}; + +extern volatile WPARAM pluginRequestedStatus; // +extern volatile WPARAM pluginCurrentStatus; // +extern CIntStrMap pluginStatusMessage; // +extern CString pluginMachineName; // +extern CString pluginUserName; // +extern CString pluginDomainName; // +extern HMODULE pluginModule; // +extern volatile bool pluginInstalled; // , + // false + // +extern volatile bool pluginInitialized; // +extern HANDLE pluginNetLibUser; // NetLib +extern HANDLE pluginInternalState; // ( - ) +extern bool pluginChatEnabled; // Chat-? +extern OSVERSIONINFO pluginOS; // + +// +CString GetNick(HANDLE hContact); +// +void SetNick(HANDLE hContact, LPCTSTR szNick); +// NetLib +int LOG(const char *fmt,...); +// +void GetAvatarCache(LPTSTR szPath); +// "" +HANDLE GenerateCookie(); +// Win32 API time() ( CRT) +DWORD time(); +// +bool IsMyContact(HANDLE hContact); +// +void SetPluginStatus(WPARAM status); +// +bool InternalStartup(); +// +void InternalShutdown(); +// Online +void GotoOnline(); +// Offline +void GotoOffline(); +// Online +void GotoOnlineTread(LPVOID status); +// Offline +void GotoOfflineTread(LPVOID status); +// - +void GetAwayMsgThread(LPVOID param); +// +void GetInfoThread(LPVOID param); +// +void Autoanswer(HANDLE hContact); +// , , Miranda IM +void ReceiveContactMessage(LPCTSTR msg_from, LPCTSTR msg_to, LPCTSTR msg_text, int msg_len); +// ( IP-) +HANDLE AddToListByName (const CString& sName, WPARAM flags, LPCTSTR notes, bool bInteractive, bool bGroup); +// "nameL" | ("nameH" << 32) +DWORD GetElapsed(HANDLE hContact, const char* name); +// "LastSeen" +void SetElapsed(HANDLE hContact, const char* name); +// "IP" +HANDLE GetContact(ip addr); +// "Nick" +HANDLE GetContact(LPCTSTR name); +// (simple == true - online/offline) +void SetContactStatus(HANDLE hContact, int status, bool simple); +// - +void SetContactAway(HANDLE hContact, LPCSTR away); +// +void SetContactAvatar(HANDLE hContact, LPCVOID pBuffer, DWORD nLength); +// IP- ( , ) +ip GetContactIP(HANDLE hContact); +// "IP" +void SetContactIP(HANDLE hContact, ip addr); +// ? +bool IsGroup(HANDLE hContact); +// +void SetGroup(HANDLE hContact, bool bGroup); +// -? +bool IsLegacyOnline(HANDLE hContact); +// - +void SetLegacyOnline(HANDLE hContact, bool bOnline); +// +bool SendContactMessage(HANDLE hContact, LPCTSTR msg, DWORD& err); +// +void SendMsgThread(LPVOID param); +// +void GetAvatarInfoThread(LPVOID param); +// ? +bool IsItMe(LPCTSTR name); +// +void Normalize(CString& msg); +// / +void EnumWorkgroups(CAtlList< CString >& lst, LPNETRESOURCE hRoot = NULL); + +// +#define FOR_EACH_CONTACT(h) \ + HANDLE h = (HANDLE)CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); \ + for ( ; h != NULL; \ + h = (HANDLE)CallService( MS_DB_CONTACT_FINDNEXT, (WPARAM)h, 0 ) ) \ + if ( IsMyContact( h ) ) + +// () +#define STATUS2TEXT(s) \ + ((((s) == ID_STATUS_OFFLINE) ? "Offline" : \ + (((s) == ID_STATUS_ONLINE) ? "Online" : \ + (((s) == ID_STATUS_AWAY) ? "Away" : \ + (((s) == ID_STATUS_DND) ? "DND" : \ + (((s) == ID_STATUS_NA) ? "NA" : \ + (((s) == ID_STATUS_OCCUPIED) ? "Occupied" : \ + (((s) == ID_STATUS_FREECHAT) ? "Free to chat" : \ + (((s) == ID_STATUS_INVISIBLE) ? "Invisible" : \ + (((s) == ID_STATUS_ONTHEPHONE) ? "On the phone" : \ + (((s) == ID_STATUS_OUTTOLUNCH) ? "Out to lunch" : \ + (((s) == ID_STATUS_IDLE) ? "Idle" : \ + (((s) == (ID_STATUS_CONNECTING + 0)) ? "Connecting 1" : \ + (((s) == (ID_STATUS_CONNECTING + 1)) ? "Connecting 2" : \ + (((s) < (ID_STATUS_CONNECTING + MAX_CONNECT_RETRIES)) ? "Connecting > 2" : \ + "Unknown"))))))))))))))) diff --git a/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj b/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj new file mode 100644 index 0000000000..db0552d894 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj @@ -0,0 +1,239 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + WinPopup + {56F4BA4F-5155-4D7A-99BB-F7EA0A854CCE} + + + + DynamicLibrary + v110_xp + Unicode + true + + + DynamicLibrary + v110_xp + Unicode + + + DynamicLibrary + v110_xp + Unicode + true + + + DynamicLibrary + v110_xp + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)64\Plugins\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(SolutionDir)$(Configuration)64\Obj\$(ProjectName)\ + true + + + + Disabled + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + Level3 + EditAndContinue + + + comctl32.lib;Mpr.lib;WSock32.Lib;Netapi32.lib;%(AdditionalDependencies) + true + Windows + 0x18a30000 + $(ProfileDir)..\..\bin11\lib + false + $(IntDir)$(TargetName).lib + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + Disabled + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + _DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebugDLL + true + Fast + Use + Level3 + + + comctl32.lib;Mpr.lib;WSock32.Lib;Netapi32.lib;%(AdditionalDependencies) + true + Windows + 0x18a30000 + $(ProfileDir)..\..\bin11\lib + false + $(IntDir)$(TargetName).lib + + + _DEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + Full + AnySuitable + true + Size + true + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Fast + Use + Level3 + + + comctl32.lib;Mpr.lib;WSock32.Lib;Netapi32.lib;%(AdditionalDependencies) + Windows + true + true + 0x18a30000 + $(ProfileDir)..\..\bin11\lib + false + $(IntDir)$(TargetName).lib + true + /PDBALTPATH:%_PDB% %(AdditionalOptions) + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + Full + AnySuitable + true + Size + true + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Fast + Use + Level3 + + + comctl32.lib;Mpr.lib;WSock32.Lib;Netapi32.lib;%(AdditionalDependencies) + Windows + true + true + 0x18a30000 + $(ProfileDir)..\..\bin11\lib + false + $(IntDir)$(TargetName).lib + true + /PDBALTPATH:%_PDB% %(AdditionalOptions) + + + NDEBUG;%(PreprocessorDefinitions) + ..\..\include\msapi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Create + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj.filters b/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj.filters new file mode 100644 index 0000000000..5eb2d84b9b --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/winpopup_proto_11.vcxproj.filters @@ -0,0 +1,134 @@ + + + + + {3f0eb0de-d451-401b-998d-dd94abf740f1} + cpp;c;cxx;def;odl;idl;hpj;bat;asm + + + {2f7a74ab-999c-4ca0-8eae-670c4cdb4a3f} + h;hpp;hxx;hm;inl;inc + + + {e2eb5ca3-1f0c-45fb-a578-5e34c13777de} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + \ No newline at end of file -- cgit v1.2.3