From 67010ebc31ce45e6c42d2c31d983f3988bb320e1 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 20 Mar 2013 13:04:46 +0000 Subject: added some old plugins git-svn-id: http://svn.miranda-ng.org/main/trunk@4123 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/!NotAdopted/BuddyPounce/InstallScript.xml | 25 + plugins/!NotAdopted/BuddyPounce/buddypounce.dll | Bin 0 -> 45056 bytes plugins/!NotAdopted/BuddyPounce/buddypounce.dsp | 127 ++ plugins/!NotAdopted/BuddyPounce/buddypounce.dsw | 29 + plugins/!NotAdopted/BuddyPounce/buddypounce.ncb | Bin 0 -> 66560 bytes plugins/!NotAdopted/BuddyPounce/buddypounce.opt | Bin 0 -> 51712 bytes plugins/!NotAdopted/BuddyPounce/buddypounce.plg | 38 + .../!NotAdopted/BuddyPounce/buddypounce_readme.txt | 83 ++ plugins/!NotAdopted/BuddyPounce/dialog.c | 668 +++++++++++ plugins/!NotAdopted/BuddyPounce/headers.h | 101 ++ plugins/!NotAdopted/BuddyPounce/icon1.ico | Bin 0 -> 2166 bytes plugins/!NotAdopted/BuddyPounce/main.c | 300 +++++ plugins/!NotAdopted/BuddyPounce/resource.aps | Bin 0 -> 41088 bytes plugins/!NotAdopted/BuddyPounce/resource.h | 81 ++ plugins/!NotAdopted/BuddyPounce/resource.rc | 312 +++++ .../MagneticWindows/MagneticWindows.cpp | 184 +++ .../MagneticWindows/MagneticWindows.dsp | 146 +++ .../MagneticWindows/MagneticWindows.dsw | 29 + .../MagneticWindows/MagneticWindowsCore.cpp | 464 ++++++++ .../MagneticWindows/MagneticWindowsCore.h | 45 + plugins/!NotAdopted/MagneticWindows/Options.cpp | 128 ++ plugins/!NotAdopted/MagneticWindows/Options.h | 18 + plugins/!NotAdopted/MagneticWindows/Options.rc | 113 ++ .../MagneticWindows/SnapToListService.cpp | 64 + .../MagneticWindows/SnapToListService.h | 5 + .../MagneticWindows/m_MagneticWindows.h | 86 ++ plugins/!NotAdopted/MagneticWindows/resource.h | 25 + .../!NotAdopted/MessagePopup/AggressiveOptimize.h | 165 +++ plugins/!NotAdopted/MessagePopup/MsgPopup.dsp | 124 ++ plugins/!NotAdopted/MessagePopup/MsgPopup.dsw | 29 + plugins/!NotAdopted/MessagePopup/MsgPopup.rc | 134 +++ plugins/!NotAdopted/MessagePopup/MsgPopup.txt | 63 + plugins/!NotAdopted/MessagePopup/common.h | 63 + plugins/!NotAdopted/MessagePopup/main.cpp | 272 +++++ plugins/!NotAdopted/MessagePopup/options.cpp | 131 +++ plugins/!NotAdopted/MessagePopup/options.h | 22 + plugins/!NotAdopted/MessagePopup/resource.h | 34 + plugins/!NotAdopted/WinPopup/add_dialog.cpp | 74 ++ plugins/!NotAdopted/WinPopup/add_dialog.h | 25 + plugins/!NotAdopted/WinPopup/chat.cpp | 337 ++++++ plugins/!NotAdopted/WinPopup/chat.h | 44 + plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h | 338 ++++++ plugins/!NotAdopted/WinPopup/icons/add.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/away.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/bad_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/bad_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/computer.ico | Bin 0 -> 1406 bytes .../!NotAdopted/WinPopup/icons/computer_error.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/dnd.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/explore.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/freechat.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/good_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/good_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/invisible.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/lana.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/na.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/occupied.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/offline.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/online.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/onthephone.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/other_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/other_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/outtolunch.ico | Bin 0 -> 2550 bytes .../!NotAdopted/WinPopup/icons/overlay/away.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/freechat.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/invisible.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/icons/overlay/na.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/occupied.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/icons/overlay/onphone.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/outtolunch.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/icons/winpopup_proto.ico | Bin 0 -> 9062 bytes plugins/!NotAdopted/WinPopup/m_uninstaller.h | 703 +++++++++++ plugins/!NotAdopted/WinPopup/m_updater.h | 117 ++ plugins/!NotAdopted/WinPopup/mailslot.cpp | 313 +++++ plugins/!NotAdopted/WinPopup/mailslot.h | 48 + plugins/!NotAdopted/WinPopup/md5.h | 222 ++++ plugins/!NotAdopted/WinPopup/messagebox.cpp | 232 ++++ plugins/!NotAdopted/WinPopup/messagebox.h | 29 + plugins/!NotAdopted/WinPopup/messenger.cpp | 469 ++++++++ plugins/!NotAdopted/WinPopup/messenger.h | 54 + plugins/!NotAdopted/WinPopup/netbios.cpp | 1065 +++++++++++++++++ plugins/!NotAdopted/WinPopup/netbios.h | 134 +++ plugins/!NotAdopted/WinPopup/netbios_name.cpp | 640 ++++++++++ plugins/!NotAdopted/WinPopup/netbios_name.h | 157 +++ plugins/!NotAdopted/WinPopup/network.cpp | 88 ++ plugins/!NotAdopted/WinPopup/network.h | 31 + plugins/!NotAdopted/WinPopup/options.cpp | 392 +++++++ plugins/!NotAdopted/WinPopup/options.h | 24 + plugins/!NotAdopted/WinPopup/processapi.cpp | 578 ++++++++++ plugins/!NotAdopted/WinPopup/processapi.h | 264 +++++ plugins/!NotAdopted/WinPopup/resource.h | 66 ++ plugins/!NotAdopted/WinPopup/scanner.cpp | 218 ++++ plugins/!NotAdopted/WinPopup/scanner.h | 49 + plugins/!NotAdopted/WinPopup/sdk/m_avatars.h | 359 ++++++ plugins/!NotAdopted/WinPopup/sdk/m_chat.h | 685 +++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_clist.h | 637 ++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_database.h | 1199 +++++++++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_langpack.h | 114 ++ plugins/!NotAdopted/WinPopup/sdk/m_netlib.h | 832 +++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_options.h | 138 +++ plugins/!NotAdopted/WinPopup/sdk/m_plugins.h | 85 ++ plugins/!NotAdopted/WinPopup/sdk/m_popup.h | 424 +++++++ plugins/!NotAdopted/WinPopup/sdk/m_protocols.h | 487 ++++++++ plugins/!NotAdopted/WinPopup/sdk/m_protomod.h | 136 +++ plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h | 775 +++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_system.h | 631 ++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_userinfo.h | 76 ++ plugins/!NotAdopted/WinPopup/sdk/m_utils.h | 573 +++++++++ plugins/!NotAdopted/WinPopup/sdk/newpluginapi.h | 291 +++++ plugins/!NotAdopted/WinPopup/sdk/statusmodes.h | 52 + plugins/!NotAdopted/WinPopup/search.cpp | 330 ++++++ plugins/!NotAdopted/WinPopup/search.h | 60 + plugins/!NotAdopted/WinPopup/services.cpp | 1003 ++++++++++++++++ plugins/!NotAdopted/WinPopup/services.h | 36 + plugins/!NotAdopted/WinPopup/smbconst.h | 108 ++ plugins/!NotAdopted/WinPopup/stdafx.cpp | 22 + plugins/!NotAdopted/WinPopup/stdafx.h | 136 +++ plugins/!NotAdopted/WinPopup/user_info.cpp | 334 ++++++ plugins/!NotAdopted/WinPopup/user_info.h | 24 + plugins/!NotAdopted/WinPopup/winpopup_proto.cpp | 1217 ++++++++++++++++++++ plugins/!NotAdopted/WinPopup/winpopup_proto.def | 27 + plugins/!NotAdopted/WinPopup/winpopup_proto.h | 322 ++++++ plugins/!NotAdopted/WinPopup/winpopup_proto.rc | 251 ++++ plugins/!NotAdopted/WinPopup/winpopup_proto_7.sln | 21 + .../!NotAdopted/WinPopup/winpopup_proto_7.vcproj | 406 +++++++ .../!NotAdopted/WinPopup/winpopup_proto_9.icproj | 37 + plugins/!NotAdopted/WinPopup/winpopup_proto_9.sln | 28 + .../!NotAdopted/WinPopup/winpopup_proto_9.vcproj | 773 +++++++++++++ .../!NotAdopted/WinPopup/winpopup_proto_pack.cmd | 6 + .../!NotAdopted/WinPopup/winpopup_proto_readme.txt | 245 ++++ .../!NotAdopted/WinPopup/winpopup_proto_todo.txt | 9 + .../WinPopup/winpopup_proto_translation.txt | 43 + 133 files changed, 23751 insertions(+) create mode 100644 plugins/!NotAdopted/BuddyPounce/InstallScript.xml create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.dll create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.dsp create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.dsw create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.ncb create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.opt create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce.plg create mode 100644 plugins/!NotAdopted/BuddyPounce/buddypounce_readme.txt create mode 100644 plugins/!NotAdopted/BuddyPounce/dialog.c create mode 100644 plugins/!NotAdopted/BuddyPounce/headers.h create mode 100644 plugins/!NotAdopted/BuddyPounce/icon1.ico create mode 100644 plugins/!NotAdopted/BuddyPounce/main.c create mode 100644 plugins/!NotAdopted/BuddyPounce/resource.aps create mode 100644 plugins/!NotAdopted/BuddyPounce/resource.h create mode 100644 plugins/!NotAdopted/BuddyPounce/resource.rc create mode 100644 plugins/!NotAdopted/MagneticWindows/MagneticWindows.cpp create mode 100644 plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsp create mode 100644 plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsw create mode 100644 plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.cpp create mode 100644 plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.h create mode 100644 plugins/!NotAdopted/MagneticWindows/Options.cpp create mode 100644 plugins/!NotAdopted/MagneticWindows/Options.h create mode 100644 plugins/!NotAdopted/MagneticWindows/Options.rc create mode 100644 plugins/!NotAdopted/MagneticWindows/SnapToListService.cpp create mode 100644 plugins/!NotAdopted/MagneticWindows/SnapToListService.h create mode 100644 plugins/!NotAdopted/MagneticWindows/m_MagneticWindows.h create mode 100644 plugins/!NotAdopted/MagneticWindows/resource.h create mode 100644 plugins/!NotAdopted/MessagePopup/AggressiveOptimize.h create mode 100644 plugins/!NotAdopted/MessagePopup/MsgPopup.dsp create mode 100644 plugins/!NotAdopted/MessagePopup/MsgPopup.dsw create mode 100644 plugins/!NotAdopted/MessagePopup/MsgPopup.rc create mode 100644 plugins/!NotAdopted/MessagePopup/MsgPopup.txt create mode 100644 plugins/!NotAdopted/MessagePopup/common.h create mode 100644 plugins/!NotAdopted/MessagePopup/main.cpp create mode 100644 plugins/!NotAdopted/MessagePopup/options.cpp create mode 100644 plugins/!NotAdopted/MessagePopup/options.h create mode 100644 plugins/!NotAdopted/MessagePopup/resource.h create mode 100644 plugins/!NotAdopted/WinPopup/add_dialog.cpp create mode 100644 plugins/!NotAdopted/WinPopup/add_dialog.h create mode 100644 plugins/!NotAdopted/WinPopup/chat.cpp create mode 100644 plugins/!NotAdopted/WinPopup/chat.h create mode 100644 plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h create mode 100644 plugins/!NotAdopted/WinPopup/icons/add.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/bad_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/bad_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/computer.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/computer_error.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/explore.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/good_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/good_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/lana.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/offline.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/online.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/onthephone.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/other_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/other_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico create mode 100644 plugins/!NotAdopted/WinPopup/m_uninstaller.h create mode 100644 plugins/!NotAdopted/WinPopup/m_updater.h create mode 100644 plugins/!NotAdopted/WinPopup/mailslot.cpp create mode 100644 plugins/!NotAdopted/WinPopup/mailslot.h create mode 100644 plugins/!NotAdopted/WinPopup/md5.h create mode 100644 plugins/!NotAdopted/WinPopup/messagebox.cpp create mode 100644 plugins/!NotAdopted/WinPopup/messagebox.h create mode 100644 plugins/!NotAdopted/WinPopup/messenger.cpp create mode 100644 plugins/!NotAdopted/WinPopup/messenger.h create mode 100644 plugins/!NotAdopted/WinPopup/netbios.cpp create mode 100644 plugins/!NotAdopted/WinPopup/netbios.h create mode 100644 plugins/!NotAdopted/WinPopup/netbios_name.cpp create mode 100644 plugins/!NotAdopted/WinPopup/netbios_name.h create mode 100644 plugins/!NotAdopted/WinPopup/network.cpp create mode 100644 plugins/!NotAdopted/WinPopup/network.h create mode 100644 plugins/!NotAdopted/WinPopup/options.cpp create mode 100644 plugins/!NotAdopted/WinPopup/options.h create mode 100644 plugins/!NotAdopted/WinPopup/processapi.cpp create mode 100644 plugins/!NotAdopted/WinPopup/processapi.h create mode 100644 plugins/!NotAdopted/WinPopup/resource.h create mode 100644 plugins/!NotAdopted/WinPopup/scanner.cpp create mode 100644 plugins/!NotAdopted/WinPopup/scanner.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_avatars.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_chat.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_clist.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_database.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_langpack.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_netlib.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_options.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_plugins.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_popup.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protocols.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protomod.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_system.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_userinfo.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_utils.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/newpluginapi.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/statusmodes.h create mode 100644 plugins/!NotAdopted/WinPopup/search.cpp create mode 100644 plugins/!NotAdopted/WinPopup/search.h create mode 100644 plugins/!NotAdopted/WinPopup/services.cpp create mode 100644 plugins/!NotAdopted/WinPopup/services.h create mode 100644 plugins/!NotAdopted/WinPopup/smbconst.h create mode 100644 plugins/!NotAdopted/WinPopup/stdafx.cpp create mode 100644 plugins/!NotAdopted/WinPopup/stdafx.h create mode 100644 plugins/!NotAdopted/WinPopup/user_info.cpp create mode 100644 plugins/!NotAdopted/WinPopup/user_info.h create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.cpp create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.def create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.h create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.rc create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_7.sln create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_7.vcproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.icproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.sln create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.vcproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_pack.cmd create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_readme.txt create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_todo.txt create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_translation.txt (limited to 'plugins/!NotAdopted') diff --git a/plugins/!NotAdopted/BuddyPounce/InstallScript.xml b/plugins/!NotAdopted/BuddyPounce/InstallScript.xml new file mode 100644 index 0000000000..55252c2908 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/InstallScript.xml @@ -0,0 +1,25 @@ + + + + Buddy Pounce + Jonathan Gordon + 0.3 + plugin + + + + Main Files + buddypounce.dll + + + + Documentation and Translation + buddypounce_readme.txt + + + + + buddypounce_readme.txt + + + \ No newline at end of file diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.dll b/plugins/!NotAdopted/BuddyPounce/buddypounce.dll new file mode 100644 index 0000000000..5acf868e4d Binary files /dev/null and b/plugins/!NotAdopted/BuddyPounce/buddypounce.dll differ diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.dsp b/plugins/!NotAdopted/BuddyPounce/buddypounce.dsp new file mode 100644 index 0000000000..a61754e2fd --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/buddypounce.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="buddypounce" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=buddypounce - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "buddypounce.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "buddypounce.mak" CFG="buddypounce - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "buddypounce - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "buddypounce - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "buddypounce - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BUDDYPOUNCE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BUDDYPOUNCE_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0xc09 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 + +!ELSEIF "$(CFG)" == "buddypounce - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BUDDYPOUNCE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BUDDYPOUNCE_EXPORTS" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0xc09 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"d:\mim\plugins\buddypounce.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "buddypounce - Win32 Release" +# Name "buddypounce - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\dialog.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\headers.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.dsw b/plugins/!NotAdopted/BuddyPounce/buddypounce.dsw new file mode 100644 index 0000000000..3b2222d700 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/buddypounce.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "buddypounce"=.\buddypounce.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.ncb b/plugins/!NotAdopted/BuddyPounce/buddypounce.ncb new file mode 100644 index 0000000000..9b90dbd9e8 Binary files /dev/null and b/plugins/!NotAdopted/BuddyPounce/buddypounce.ncb differ diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.opt b/plugins/!NotAdopted/BuddyPounce/buddypounce.opt new file mode 100644 index 0000000000..6cb2b12472 Binary files /dev/null and b/plugins/!NotAdopted/BuddyPounce/buddypounce.opt differ diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce.plg b/plugins/!NotAdopted/BuddyPounce/buddypounce.plg new file mode 100644 index 0000000000..13b190b1ed --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/buddypounce.plg @@ -0,0 +1,38 @@ + + +
+

Build Log

+

+--------------------Configuration: buddypounce - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP121.tmp" with contents +[ +/nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BUDDYPOUNCE_EXPORTS" /Fp"Release/buddypounce.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"D:\mim_sources\buddypounce\dialog.c" +"D:\mim_sources\buddypounce\main.c" +] +Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP121.tmp" +Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP122.tmp" with contents +[ +kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:no /pdb:"Release/buddypounce.pdb" /machine:I386 /out:"Release/buddypounce.dll" /implib:"Release/buddypounce.lib" +.\Release\dialog.obj +.\Release\main.obj +.\Release\resource.res +] +Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP122.tmp" +

Output Window

+Compiling... +dialog.c +win2k.h +main.c +Linking... + Creating library Release/buddypounce.lib and object Release/buddypounce.exp + + + +

Results

+buddypounce.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/plugins/!NotAdopted/BuddyPounce/buddypounce_readme.txt b/plugins/!NotAdopted/BuddyPounce/buddypounce_readme.txt new file mode 100644 index 0000000000..a84612a1ab --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/buddypounce_readme.txt @@ -0,0 +1,83 @@ +Buddy Pounce +------------- + +Buddy Pounce allows you to send a message to a contact automatically when they change status (i.e from offline) if you are expecting to be away form the computer. +This bassically adds "Offline Messaging" to protocols that dont have it (i.e MSN) + +HOW To use it. +--------------- +Right click the contact you want to send the message to. choose the Buddy Pounce item. +If you havnt edited the options yet you will be at the "simple" window. by default any message you type here will be sent to the contact when they change status. (dont worry the default behaviour can be changed in the options). +Pressing the "advanced >>" button will open the advanced window. Here you have full power of when to send the message. +Firstly, make sure the contact you want to send to is selected in the drop list at the top right. +next type your message. +Now the fun begins..... + +The Settings Explained... +- "send if My Status Is..." - selecting this will open up a window with 10 check boxes. basically the message will only be sent if your status matches any checked statuses here. +- "Send if they change status to..." - bassicaly the same as above, cept it will only send if they changed to a checked status +----------- the next 3 options can all be set to 0 to ignore them +- "Reuse Pounce" - if this is set to anything but 0 the messsage will be sent the next X times the contact changes to the specified status +- "Give Up Delay" - will not try to send the message if the contact doesnt change to the specified status after X days +- "Confirmation Window" - with this set, a window will popup asking you if you want to send the message. It will automatically be sent in X seconds if you dont press cancel. if its set to 1024 then it will never send unless you press OK (sort of useless then...) + +(the advanced dialog has 2 buttons... delete pounce which deletes the pounce ! :O, and load deafults which overwrights any settings with the default ones from the options.) +the simple window uses the default options to send the message... + +Explanation of options window +----------------------------- +"Use Advanced Dialog" - if this is checked then the advanced window will be automatically opened +"Show Delivery Messages" - if this is checked a window will poup saying the message was un/successfully sent to the contact. +"Default Settings" - excatly the same as the settings as explained above... any values set here will be used as the values for the "simple" window, and will be automatically set when u load the buddy pounce windw. + + +FOR DEVELOPERS: +--------------- + +in the of-chance you want to setup a pounce in your own plugins i have added 2 service funcitons you can use. +call both of these like CallService(SERVICE, (WPARAM)hContact, (LPARAM)message) +where hContact is the HANDLE to a valid contact, and message is a pointer to a string to use as the message +"BuddyPounce/AddSimplePounce" - which sets a new pounce using the message u supply and the defalt settings +"BuddyPounce/AddToPounce" - which adds your text to an exsisnting pounce message, or call the above service if 1 doesnt exsist. +it doesnt really matter which u call, but to check if a message exsists check if the string (hContact, "buddypounce", "PounceMsg") exsists.. +if you want to setup an "advanced" pounce you will have to setup the other settings manually... email me @ jdgordy@gmail.com for info...) + +Translation: +------------ +the following strings can be translated.... +Send If My Status Is... +Send If They Change Status to... +Reuse Pounce +Give Up delay +Confirmation Window +Send a File +Send If My Status Is +Any +Online +NA +Occupied +DND +Free For Chat +Invisible +On The Phone +Out To Lunch +Send If Their Status changes +From Offline +To Online +To NA +To Occupied +To DND +To Free For Chat +To Invisible +To On The Phone +To Out To Lunch +The Message (%d Characters) **** make sure u keep the %d in this 1 +Pounce being sent to %s in %d seconds **** and the %s and %d in the same order in this 1 + +the dialogs also need to be translated but im falling asleep and want to relase the plugin... + + +Change-log: +----------- +0.3 +- completly re-written \ No newline at end of file diff --git a/plugins/!NotAdopted/BuddyPounce/dialog.c b/plugins/!NotAdopted/BuddyPounce/dialog.c new file mode 100644 index 0000000000..8ba7f132e3 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/dialog.c @@ -0,0 +1,668 @@ +#include "headers.h" + +void populateSettingsList(HWND hwnd2List) +{ + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Send If My Status Is...")); + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Send If They Change Status to...")); + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)"----------------------------"); + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Reuse Pounce")); + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Give Up delay")); + SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Confirmation Window")); +// SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)"----------------------------")); +// SendMessage(hwnd2List, LB_ADDSTRING, 0, (LPARAM)Translate("Send a File")); +} + +void populateContacts(HANDLE BPhContact,HWND hwnd2CB) +{ + HANDLE hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + char name[300], *szProto; + int index, selectedIndex = 0; + while (hContact) + { + szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (szProto && (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM)) + { + _snprintf(name, 300, "%s (%s)", (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0), szProto); + index = SendMessage(hwnd2CB, CB_ADDSTRING, 0, (LPARAM)name); + SendMessage(hwnd2CB, CB_SETITEMDATA, index, (LPARAM)hContact); + if (BPhContact == hContact) SendMessage(hwnd2CB, CB_SETCURSEL, index, 0); + } + hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0); + } +} + + +void saveLastSetting(HANDLE hContact, HWND hwnd) +{ + char number[8], string[1024]; + switch (DBGetContactSettingByte(hContact, modname, "LastSetting", 2)) // nothing to do + { + case 0: // Send If My Status Is... + break; + case 1: // Send If They Change status to + break; + case 2: // ------, fall through + case 6: // nothing to do... + break; + case 3: // Reuse Pounce + GetDlgItemText(hwnd, IDC_SETTINGNUMBER, number, 8); + DBWriteContactSettingByte(hContact, modname, "Reuse", (BYTE)atoi(number)); + break; + case 4: // Give Up delay + GetDlgItemText(hwnd, IDC_SETTINGNUMBER, number, 8); + DBWriteContactSettingByte(hContact, modname, "GiveUpDays", (BYTE)atoi(number)); + { + time_t today = time(NULL); + DBWriteContactSettingDword(hContact, modname, "GiveUpDate", (DWORD)(atoi(number)*SECONDSINADAY)); + } + break; + case 5: // confirm window + GetDlgItemText(hwnd, IDC_SETTINGNUMBER, number, 8); + DBWriteContactSettingByte(hContact, modname, "ConfirmTimeout", (BYTE)atoi(number)); + break; + + case 7: // send a file + GetDlgItemText(hwnd, IDC_SETTINGTEXT, string, 1024); + DBWriteContactSettingString(hContact, modname, "FileToSend", string); + break; + } +} + +void hideAll(HWND hwnd) +{ + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDC_BUTTON), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGTEXT), SW_HIDE); +} + +void getDefaultMessage(HWND hwnd, UINT control, HANDLE hContact) +{ + DBVARIANT dbv; + if (!DBGetContactSetting(hContact,modname, "PounceMsg", &dbv)) + SetDlgItemText(hwnd, control, dbv.pszVal); + else if (!DBGetContactSetting(NULL,modname, "PounceMsg", &dbv)) + SetDlgItemText(hwnd, control, dbv.pszVal); + DBFreeVariant(&dbv); +} +BOOL CALLBACK StatusModesDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + struct windowInfo *wi = (struct windowInfo *)lParam; + SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)wi); + TranslateDialogDefault(hwnd); + + } + return FALSE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + { + struct windowInfo *wi = (struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA); + char type[32]; + int flag = 0; + GetDlgItemText(hwnd, IDC_CHECK1, type, 32); + flag = (IsDlgButtonChecked(hwnd, IDC_CHECK1)) + |(IsDlgButtonChecked(hwnd, IDC_CHECK2)<<1) + |(IsDlgButtonChecked(hwnd, IDC_CHECK3)<<2) + |(IsDlgButtonChecked(hwnd, IDC_CHECK4)<<3) + |(IsDlgButtonChecked(hwnd, IDC_CHECK5)<<4) + |(IsDlgButtonChecked(hwnd, IDC_CHECK6)<<5) + |(IsDlgButtonChecked(hwnd, IDC_CHECK7)<<6) + |(IsDlgButtonChecked(hwnd, IDC_CHECK8)<<7) + |(IsDlgButtonChecked(hwnd, IDC_CHECK9)<<8) + |(IsDlgButtonChecked(hwnd, IDC_CHECK10)<<9); + if (!strcmp(type, "Any")) + { + if (LOWORD(wParam) == IDOK) + DBWriteContactSettingWord(wi->hContact, modname, "SendIfMyStatusIsFLAG", (WORD)flag); + wi->SendIfMy = 0; + } + else + { + if (LOWORD(wParam) == IDOK) + DBWriteContactSettingWord(wi->hContact, modname, "SendIfTheirStatusIsFLAG", (WORD)flag); + wi->SendWhenThey = 0; + } + DestroyWindow(hwnd); + } + break; + } + break; + } + return FALSE; +} +void statusModes(struct windowInfo *wi, int myStatusMode) // myStatusMode=1 sendIfMyStatusFlag +{ + int statusFlag; + HWND hwnd; + + if (myStatusMode) + { + if (wi->SendIfMy) { SetForegroundWindow(wi->SendIfMy); return; } + else + { + hwnd = wi->SendIfMy = CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_STATUSMODES),0,StatusModesDlgProc, (LPARAM)wi); + statusFlag = DBGetContactSettingWord(wi->hContact, modname, "SendIfMyStatusIsFLAG", 0); + SetWindowText(hwnd, Translate("Send If My Status Is")); + SetDlgItemText(hwnd, IDC_CHECK1, Translate("Any")); + SetDlgItemText(hwnd, IDC_CHECK2, Translate("Online")); + SetDlgItemText(hwnd, IDC_CHECK3, Translate("Away")); + SetDlgItemText(hwnd, IDC_CHECK4, Translate("NA")); + SetDlgItemText(hwnd, IDC_CHECK5, Translate("Occupied")); + SetDlgItemText(hwnd, IDC_CHECK6, Translate("DND")); + SetDlgItemText(hwnd, IDC_CHECK7, Translate("Free For Chat")); + SetDlgItemText(hwnd, IDC_CHECK8, Translate("Invisible")); + SetDlgItemText(hwnd, IDC_CHECK9, Translate("On The Phone")); + SetDlgItemText(hwnd, IDC_CHECK10, Translate("Out To Lunch")); + } + } + else + { + if (wi->SendWhenThey) { SetForegroundWindow(wi->SendWhenThey); return; } + else + { + hwnd = wi->SendWhenThey = CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_STATUSMODES),0,StatusModesDlgProc, (LPARAM)wi); + statusFlag = DBGetContactSettingWord(wi->hContact, modname, "SendIfTheirStatusIsFLAG", 0); + SetWindowText(hwnd, Translate("Send If Their Status changes")); + SetDlgItemText(hwnd, IDC_CHECK1, Translate("From Offline")); + SetDlgItemText(hwnd, IDC_CHECK2, Translate("To Online")); + SetDlgItemText(hwnd, IDC_CHECK3, Translate("To Away")); + SetDlgItemText(hwnd, IDC_CHECK4, Translate("To NA")); + SetDlgItemText(hwnd, IDC_CHECK5, Translate("To Occupied")); + SetDlgItemText(hwnd, IDC_CHECK6, Translate("To DND")); + SetDlgItemText(hwnd, IDC_CHECK7, Translate("To Free For Chat")); + SetDlgItemText(hwnd, IDC_CHECK8, Translate("To Invisible")); + SetDlgItemText(hwnd, IDC_CHECK9, Translate("To On The Phone")); + SetDlgItemText(hwnd, IDC_CHECK10, Translate("To Out To Lunch")); + } + } + CheckDlgButton(hwnd, IDC_CHECK1, statusFlag&ANY); + CheckDlgButton(hwnd, IDC_CHECK2, (statusFlag&ONLINE)>>1); + CheckDlgButton(hwnd, IDC_CHECK3, (statusFlag&AWAY)>>2); + CheckDlgButton(hwnd, IDC_CHECK4, (statusFlag&NA)>>3); + CheckDlgButton(hwnd, IDC_CHECK5, (statusFlag&OCCUPIED)>>4); + CheckDlgButton(hwnd, IDC_CHECK6, (statusFlag&DND)>>5); + CheckDlgButton(hwnd, IDC_CHECK7, (statusFlag&FFC)>>6); + CheckDlgButton(hwnd, IDC_CHECK8, (statusFlag&INVISIBLE)>>7); + CheckDlgButton(hwnd, IDC_CHECK9, (statusFlag&PHONE)>>8); + CheckDlgButton(hwnd, IDC_CHECK10, (statusFlag&LUNCH)>>9); +} + +void deletePounce(HANDLE hContact) +{ + DBDeleteContactSetting(hContact,modname, "PounceMsg"); + DBDeleteContactSetting(hContact,modname, "SendIfMyStatusIsFLAG"); + DBDeleteContactSetting(hContact,modname, "SendIfTheirStatusIsFLAG"); + DBDeleteContactSetting(hContact,modname, "Reuse"); + DBDeleteContactSetting(hContact, modname, "GiveUpDays"); + DBDeleteContactSetting(hContact, modname, "GiveUpDate"); + DBDeleteContactSetting(hContact, modname, "ConfirmTimeout"); + DBDeleteContactSetting(hContact, modname, "FileToSend"); +} + + +BOOL CALLBACK BuddyPounceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + struct windowInfo *wi = (struct windowInfo *)malloc(sizeof(struct windowInfo)); + char msg[1024]; + if (!wi) { msg("error......","Buddy Pounce"); DestroyWindow(hwnd); } + TranslateDialogDefault(hwnd); + wi->hContact = (HANDLE)lParam; + wi->SendIfMy = 0; + wi->SendWhenThey = 0; + SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)wi); + getDefaultMessage(hwnd, IDC_MESSAGE, wi->hContact); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))); + SetDlgItemText(hwnd, GRP_MSG, msg); + populateSettingsList(GetDlgItem(hwnd, IDC_SETTINGS)); + populateContacts(wi->hContact, GetDlgItem(hwnd,IDC_CONTACTS)); + SendMessage(GetDlgItem(hwnd,IDC_SPIN), UDM_SETRANGE, 0, (LPARAM) MAKELONG ((short) 1024, (short) 0)); + DBWriteContactSettingByte(wi->hContact, modname, "LastSetting", 0); + } + return FALSE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_MESSAGE: + { + if (HIWORD(wParam) == EN_CHANGE) + { + int length; + char msg[1024]; + length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE)); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), length); + SetDlgItemText(hwnd, GRP_MSG, msg); + } + } + break; + case IDC_SIMPLE: + case IDOK: + { + char *text; + HANDLE hContact = (HANDLE)SendMessage(GetDlgItem(hwnd, IDC_CONTACTS), CB_GETITEMDATA, SendMessage(GetDlgItem(hwnd, IDC_CONTACTS), CB_GETCURSEL,0,0),0); + int length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))+1; + if (length>1) + { + text = (char*)malloc(length); + if (!text) { msg("Couldnt Allocate enough memory",""); break; } + GetDlgItemText(hwnd, IDC_MESSAGE, text, length); + DBWriteContactSettingString(hContact, modname, "PounceMsg", text); + free(text); + } + else DBDeleteContactSetting(hContact, modname, "PounceMsg"); + saveLastSetting(hContact, hwnd); + } // fall through + if (LOWORD(wParam) == IDC_SIMPLE) + CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_POUNCE_SIMPLE),0,BuddyPounceSimpleDlgProc, (LPARAM)((struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA))->hContact); + // fall through + case IDCANCEL: + { + struct windowInfo *wi = (struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA); + if (wi->SendIfMy) DestroyWindow(wi->SendIfMy); + if (wi->SendWhenThey) DestroyWindow(wi->SendWhenThey); + free(wi); + DestroyWindow(hwnd); + } + break; + case IDC_DELETE: + { + HANDLE hContact = ((struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA))->hContact; + deletePounce(hContact); + SetDlgItemText(hwnd, IDC_MESSAGE, ""); + SetDlgItemText(hwnd, GRP_MSG, "The Message (0 Characters)"); + } + break; + case IDC_DEFAULT: + { + HANDLE hContact = ((struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA))->hContact; + char msg[1024]; + getDefaultMessage(hwnd, IDC_MESSAGE, hContact); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))); + SetDlgItemText(hwnd, GRP_MSG, msg); + DBWriteContactSettingWord(hContact,modname, "SendIfMyStatusIsFLAG", (WORD)DBGetContactSettingWord(NULL, modname, "SendIfMyStatusIsFLAG",0)); + DBWriteContactSettingWord(hContact,modname, "SendIfTheirStatusIsFLAG", (WORD)DBGetContactSettingWord(NULL, modname, "SendIfTheirStatusIsFLAG",0)); + DBWriteContactSettingByte(hContact,modname, "Reuse",(BYTE)DBGetContactSettingByte(NULL, modname, "Reuse",0)); + DBWriteContactSettingByte(hContact, modname, "GiveUpDays", (BYTE)DBGetContactSettingByte(NULL, modname, "GiveUpDays",0)); + DBWriteContactSettingDword(hContact, modname, "GiveUpDate", (DWORD)DBGetContactSettingDword(NULL, modname, "GiveUpDate",0)); + DBWriteContactSettingByte(hContact, modname, "ConfirmTimeout", (BYTE)DBGetContactSettingByte(NULL, modname, "ConfirmTimeout",0)); + } + break; + case IDC_SETTINGS: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + struct windowInfo *wi = (struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA); + int item = SendMessage(GetDlgItem(hwnd, IDC_SETTINGS), LB_GETCURSEL, 0, 0); + char temp[5]; + saveLastSetting(wi->hContact, hwnd); + hideAll(hwnd); + switch (item) + { + case 0: // Send If My Status Is... + statusModes(wi, 1); + break; + case 1: // Send If They Change status to + statusModes(wi, 0); + break; + case 3: // Reuse Pounce + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Reuse this message? (0 to use it once)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Times"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "Reuse", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + case 4: // Give Up delay + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Giveup after.. (0 to not giveup)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Days"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "GiveUpDays", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + case 5: // confirm window + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Show confirmation window? (0 to not Show)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Seconds to wait before sending"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "ConfirmTimeout", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + + case 7: // send a file + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Send a file"); + ShowWindow(GetDlgItem(hwnd, IDC_BUTTON), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGTEXT), SW_SHOW); + break; + } + DBWriteContactSettingByte(wi->hContact, modname, "LastSetting", (BYTE)item); + } + break; + } + break; + } + return FALSE; +} + +BOOL CALLBACK BuddyPounceSimpleDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + HANDLE hContact = (HANDLE)lParam; + char msg[1024]; + TranslateDialogDefault(hwnd); + SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)lParam); + + getDefaultMessage(hwnd, IDC_MESSAGE, hContact); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))); + SetDlgItemText(hwnd, GRP_MSG, msg); + + } + return FALSE; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_MESSAGE: + { + if (HIWORD(wParam) == EN_CHANGE) + { + int length; + char msg[1024]; + length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE)); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), length); + SetDlgItemText(hwnd, GRP_MSG, msg); + } + } + break; + case IDC_ADVANCED: + // fall through + case IDOK: + { + char *text; + HANDLE hContact = (HANDLE)GetWindowLong(hwnd,GWL_USERDATA); + int length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))+1; + if (length>1) + { + text = (char*)malloc(length); + if (!text) { msg("Couldnt Allocate enough memory",""); break; } + GetDlgItemText(hwnd, IDC_MESSAGE, text, length); + + } + else DBDeleteContactSetting(hContact, modname, "PounceMsg"); + } // fall through + case IDCANCEL: + if (LOWORD(wParam) == IDC_ADVANCED) + CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_POUNCE),0,BuddyPounceDlgProc, GetWindowLong(hwnd,GWL_USERDATA)); + DestroyWindow(hwnd); + break; + return FALSE; + } + break; + } + return FALSE; +} + +BOOL CALLBACK BuddyPounceOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) + { + case WM_INITDIALOG: + { + struct windowInfo *wi = (struct windowInfo *)malloc(sizeof(struct windowInfo)); + char msg[1024]; + TranslateDialogDefault(hwnd); + wi->hContact = 0; + wi->SendIfMy = 0; + wi->SendWhenThey = 0; + SetWindowLong(hwnd,GWL_USERDATA,(LPARAM)wi); + + getDefaultMessage(hwnd, IDC_MESSAGE, wi->hContact); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))); + SetDlgItemText(hwnd, GRP_MSG, msg); + populateSettingsList(GetDlgItem(hwnd, IDC_SETTINGS)); + SendMessage(GetDlgItem(hwnd,IDC_SPIN), UDM_SETRANGE, 0, (LPARAM) MAKELONG ((short) 1024, (short) 0)); + CheckDlgButton(hwnd, IDC_USEADVANCED, DBGetContactSettingByte(NULL, modname, "UseAdvanced", 0)); + CheckDlgButton(hwnd, IDC_SHOWDELIVERYMSGS, DBGetContactSettingByte(NULL, modname, "ShowDeliveryMessages", 1)); + DBWriteContactSettingByte(wi->hContact, modname, "LastSetting", 0); + } + return FALSE; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { + char *text; + struct windowInfo *wi = (struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA); + HANDLE hContact = ((struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA))->hContact; + int length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE))+1; + if (length>1) + { + text = (char*)malloc(length); + if (!text) { msg("Couldnt Allocate enough memory",""); break; } + GetDlgItemText(hwnd, IDC_MESSAGE, text, length); + DBWriteContactSettingString(hContact, modname, "PounceMsg", text); + free(text); + } + else DBDeleteContactSetting(hContact, modname, "PounceMsg"); + DBWriteContactSettingByte(NULL, modname, "UseAdvanced", (BYTE)IsDlgButtonChecked(hwnd, IDC_USEADVANCED)); + DBWriteContactSettingByte(NULL, modname, "ShowDeliveryMessages", (BYTE)IsDlgButtonChecked(hwnd, IDC_SHOWDELIVERYMSGS)); + + if (wi->SendIfMy) DestroyWindow(wi->SendIfMy); + if (wi->SendWhenThey) DestroyWindow(wi->SendWhenThey); + } + break; + } + break; + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)) + { + case IDC_MESSAGE: + { + if (HIWORD(wParam) == EN_CHANGE) + { + int length; + char msg[1024]; + length = GetWindowTextLength(GetDlgItem(hwnd, IDC_MESSAGE)); + _snprintf(msg, 1024, Translate("The Message (%d Characters)"), length); + SetDlgItemText(hwnd, GRP_MSG, msg); + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + } + } + break; + case IDC_SHOWDELIVERYMSGS: + case IDC_USEADVANCED: + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + break; + case IDC_SETTINGS: + if (HIWORD(wParam) == LBN_SELCHANGE) + { + struct windowInfo *wi = (struct windowInfo *)GetWindowLong(hwnd,GWL_USERDATA); + int item = SendMessage(GetDlgItem(hwnd, IDC_SETTINGS), LB_GETCURSEL, 0, 0); + char temp[5]; + SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); + saveLastSetting(wi->hContact, hwnd); + hideAll(hwnd); + switch (item) + { + case 0: // Send If My Status Is... + statusModes(wi, 1); + break; + case 1: // Send If They Change status to + statusModes(wi, 0); + break; + case 3: // Reuse Pounce + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Reuse this message? (0 to use it once)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Times"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "Reuse", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + case 4: // Give Up delay + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Giveup after.. (0 to not giveup)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Days"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "GiveUpDays", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + case 5: // confirm window + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Show confirmation window? (0 to not Show)"); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG2), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG2, "Seconds to wait before sending"); + SetDlgItemText(hwnd, IDC_SETTINGNUMBER, itoa(DBGetContactSettingByte(wi->hContact, modname, "ConfirmTimeout", 0), temp, 10)); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGNUMBER), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SPIN), SW_SHOW); + break; + + case 7: // send a file + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGMSG), SW_SHOW); + SetDlgItemText(hwnd, IDC_SETTINGMSG, "Send a file"); + ShowWindow(GetDlgItem(hwnd, IDC_BUTTON), SW_SHOW); + ShowWindow(GetDlgItem(hwnd, IDC_SETTINGTEXT), SW_SHOW); + break; + } + DBWriteContactSettingByte(wi->hContact, modname, "LastSetting", (BYTE)item); + } + break; + } + break; + } + return FALSE; +} + + + +BOOL CALLBACK SendPounceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_INITDIALOG: + { + DBVARIANT dbv; + struct SendPounceDlgProcStruct *spdps = (struct SendPounceDlgProcStruct *)lParam; + if (!spdps) DestroyWindow(hwnd); + TranslateDialogDefault(hwnd); + spdps->timer = DBGetContactSettingByte(spdps->hContact, modname, "ConfirmTimeout", 0); + SetWindowLong(hwnd,GWL_USERDATA,(WPARAM)spdps); + if (DBGetContactSetting(spdps->hContact,modname,"PounceMsg",&dbv)) DestroyWindow(hwnd); + SetDlgItemText(hwnd,IDC_MESSAGE,dbv.pszVal); + DBFreeVariant(&dbv); + SetTimer(hwnd,1,1000,NULL); + SendMessage(hwnd,WM_TIMER,0,0); + } + break; + case WM_TIMER: + { + struct SendPounceDlgProcStruct *spdps = (struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA); + char message[1024]; + _snprintf(message,sizeof(message),Translate("Pounce being sent to %s in %d seconds"),CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)spdps->hContact, 0),spdps->timer); + SetDlgItemText(hwnd,LBL_CONTACT ,message); + spdps->timer--; + + if (spdps->timer == -1) + { + KillTimer(hwnd,1); + SendPounce(spdps->message, ((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA))->hContact); + free((char*)((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA))->message); + free((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA)); + DestroyWindow(hwnd); + } + break; + } + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + KillTimer(hwnd,1); + SendPounce(((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA))->message, ((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA))->hContact); + // fall through + case IDCANCEL: + KillTimer(hwnd,1); + free(((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA))->message); + free((struct SendPounceDlgProcStruct *)GetWindowLong(hwnd, GWL_USERDATA)); + DestroyWindow(hwnd); + break; + } + break; + } + return 0; +} + + +BOOL CALLBACK PounceSentDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)GetWindowLong(hwnd,GWL_USERDATA); + switch(msg) { + case WM_INITDIALOG: + { + DBVARIANT dbv; + SetWindowLong(hwnd,GWL_USERDATA,(WPARAM)lParam); + TranslateDialogDefault(hwnd); + hContact = (HANDLE)lParam; + if (DBGetContactSetting(hContact,modname,"PounceMsg",&dbv)) DestroyWindow(hwnd); + SetDlgItemText(hwnd,IDC_MESSAGE,dbv.pszVal); + DBFreeVariant(&dbv); + } + break; + case WM_COMMAND: + switch(LOWORD(wParam)) { + case IDOK: + { + char text[2048]; + GetWindowText(GetDlgItem(hwnd,IDOK),text,16); + if (!strcmp(text,Translate("Retry"))) + { + GetWindowText(GetDlgItem(hwnd,IDC_MESSAGE),text,2048); + SendPounce(text,hContact); + } + } + // fall through + case IDCANCEL: + DestroyWindow(hwnd); + break; + } + break; + } + return 0; +} +void CreateMessageAcknowlegedWindow(HANDLE hContact, int SentSuccess) +{ + HWND hwnd = CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_CONFIRMSEND),0,PounceSentDlgProc, (LPARAM)hContact); + char msg[256]; + if (SentSuccess) + { + _snprintf(msg,256,Translate("Message successfully sent to %s"),CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0) ); + SetWindowText(GetDlgItem(hwnd,IDOK),"OK"); + ShowWindow(GetDlgItem(hwnd,IDCANCEL),0); + } + else + { + _snprintf(msg,256,Translate("Message failed to send to %s"),CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0)); + SetWindowText(GetDlgItem(hwnd,IDOK),"Retry"); + } + SetWindowText(GetDlgItem(hwnd,LBL_CONTACT),msg); + SetWindowText(hwnd,modFullname); +} \ No newline at end of file diff --git a/plugins/!NotAdopted/BuddyPounce/headers.h b/plugins/!NotAdopted/BuddyPounce/headers.h new file mode 100644 index 0000000000..ca943de5e7 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/headers.h @@ -0,0 +1,101 @@ +#ifndef _COMMONHEADERS_H +#define _COMMONHEADERS_H +#pragma warning( disable : 4786 ) // limitation in MSVC's debugger. +//===================================================== +// Includes +//===================================================== + + +#include +#include +#include +#include +#include +#include +#include +#include "../miranda_src/SDK/Headers_c/newpluginapi.h" +#include "../miranda_src/SDK/Headers_c/m_clist.h" +#include "../miranda_src/SDK/Headers_c/m_clui.h" +#include "../miranda_src/SDK/Headers_c/m_skin.h" +#include "../miranda_src/SDK/Headers_c/m_langpack.h" +#include "../miranda_src/SDK/Headers_c/m_protomod.h" +#include "../miranda_src/SDK/Headers_c/m_database.h" +#include "../miranda_src/SDK/Headers_c/m_system.h" +#include "../miranda_src/SDK/Headers_c/m_protocols.h" +#include "../miranda_src/SDK/Headers_c/m_userinfo.h" +#include "../miranda_src/SDK/Headers_c/m_options.h" +#include "../miranda_src/SDK/Headers_c/m_protosvc.h" +#include "../miranda_src/SDK/Headers_c/m_utils.h" +#include "../miranda_src/SDK/Headers_c/m_ignore.h" +#include "../miranda_src/SDK/Headers_c/m_clc.h" +#include "../miranda_src/SDK/Headers_c/m_history.h" +//#include "../miranda_src/SDK/Headers_c/win2k.h" +#include "../miranda_src/SDK/Headers_c/m_popup.h" +#include "../miranda_src/SDK/Headers_c/m_file.h" +#include "../miranda_src/SDK/Headers_c/m_uninstaller.h" +#include "resource.h" + +#ifndef NDEBUG +#define _CRTDBG_MAP_ALLOC +#include +#define new new(_NORMAL_BLOCK, __FILE__, __LINE__) +#endif +//======================================================= +// Definitions +//======================================================= +#define modname "buddypounce" +#define modFullname "Buddy Pounce" +#define msg(a,b) MessageBox(0,a,b,MB_OK) + +#define SECONDSINADAY 86400 + +/* flags for the sending and recieving.... */ +#define ANY 1 +#define ONLINE 2 +#define AWAY 4 +#define NA 8 +#define OCCUPIED 16 +#define DND 32 +#define FFC 64 +#define INVISIBLE 128 +#define PHONE 256 +#define LUNCH 512 + +//======================================================= +// Variables +//======================================================= +PLUGINLINK *pluginLink; +HINSTANCE hInst; + +struct windowInfo { + HANDLE hContact; + HWND SendIfMy; + HWND SendWhenThey; +}; + +struct SendPounceDlgProcStruct { + HANDLE hContact; + int timer; + char *message; +}; +//======================================================= +// Functions +//======================================================= + +// main.c +void SendPounce(char* text, HANDLE hContact); + +//dialog.c +BOOL CALLBACK BuddyPounceDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK BuddyPounceSimpleDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK BuddyPounceOptionsDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK SendPounceDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +void CreateMessageAcknowlegedWindow(HANDLE hContact, int SentSuccess); + +#ifndef NDEBUG +#include +#define new new(_NORMAL_BLOCK, __FILE__, __LINE__) +#endif +#pragma comment(lib,"comctl32.lib") + +#endif //_COMMONHEADERS_H \ No newline at end of file diff --git a/plugins/!NotAdopted/BuddyPounce/icon1.ico b/plugins/!NotAdopted/BuddyPounce/icon1.ico new file mode 100644 index 0000000000..246d817416 Binary files /dev/null and b/plugins/!NotAdopted/BuddyPounce/icon1.ico differ diff --git a/plugins/!NotAdopted/BuddyPounce/main.c b/plugins/!NotAdopted/BuddyPounce/main.c new file mode 100644 index 0000000000..15c1e9cb10 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/main.c @@ -0,0 +1,300 @@ +#include "headers.h" + +PLUGININFO pluginInfo={ + sizeof(PLUGININFO), + "Buddy Pounce", + PLUGIN_MAKE_VERSION(0,3,2,1), + "Allows you to send a message to contacts if they change status and your not there to say hi. Bassically offline messaging for protocols that dont have it.", + "Jonathan Gordon", + "ICQ 98791178, MSN jonnog@hotmail.com", + "© 2004 Jonathan Gordon, jdgordy@gmail.com", + "http://jdgordy.tk", // www + 0, //not transient + 0 //doesn't replace anything built-in +}; + +//======================== +// WINAPI DllMain +//======================== + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} +//======================== +// MirandaPluginInfo +//======================== + + +__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +//=================== +// MainInit +//=================== + +int MainInit(WPARAM wParam,LPARAM lParam) +{ + return 0; +} +HANDLE hWindowList; + +int MsgAck(WPARAM wParam,LPARAM lParam) +{ + ACKDATA *ack=(ACKDATA*)lParam; + + if (ack && ack->cbSize==sizeof(ACKDATA) + && ack->type==ACKTYPE_MESSAGE + && ack->hProcess==(HANDLE)WindowList_Find(hWindowList,ack->hContact)) + { + if (DBGetContactSettingByte(NULL, modname, "ShowDeliveryMessages", 1)) + CreateMessageAcknowlegedWindow(ack->hContact,ack->result == ACKRESULT_SUCCESS); + if (ack->result == ACKRESULT_SUCCESS) + { + // wrtie it to the DB + DBEVENTINFO dbei = { 0 }; + DBVARIANT dbv; + int reuse = DBGetContactSettingByte(ack->hContact,modname, "Reuse", 0); + if (!DBGetContactSetting(ack->hContact, modname, "PounceMsg", &dbv) && (dbv.pszVal[0] != '\0')) + { + + dbei.cbSize = sizeof(dbei); + dbei.eventType = EVENTTYPE_MESSAGE; + dbei.flags = DBEF_SENT; + dbei.szModule = ack->szModule; + dbei.timestamp = time(NULL); + dbei.cbBlob = lstrlenA(dbv.pszVal) + 1; + dbei.pBlob = (PBYTE) dbv.pszVal; + CallService(MS_DB_EVENT_ADD, (WPARAM) ack->hContact, (LPARAM) & dbei); + } + // check to reuse + if (reuse >1) + DBWriteContactSettingByte(ack->hContact,modname, "Reuse", (BYTE)(reuse-1)); + else + { + DBWriteContactSettingByte(ack->hContact,modname, "Reuse", 0); + DBWriteContactSettingString(ack->hContact,modname, "PounceMsg",""); + } + } + WindowList_Remove(hWindowList,(HWND)ack->hProcess); + } + return 0; +} + +int BuddyPounceOptInit(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp,sizeof(odp)); + odp.cbSize=sizeof(odp); + odp.position=0; + odp.hInstance=hInst; + odp.pszTemplate=MAKEINTRESOURCE(IDD_OPTIONS); + odp.pszGroup= "Plugins"; + odp.pszTitle="Buddy Pounce"; + odp.pfnDlgProc=BuddyPounceOptionsDlgProc; + odp.expertOnlyControls=NULL; + CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp); + + return 0; +} + +int statusCheck(int statusFlag, int status) +{ + if (statusFlag == ANY || !statusFlag) return 1; + switch(status) + { + case ID_STATUS_OFFLINE: + return 0; + case ID_STATUS_ONLINE: + return (statusFlag & ONLINE); + case ID_STATUS_AWAY: + return (statusFlag & AWAY); + case ID_STATUS_NA: + return (statusFlag & NA); + case ID_STATUS_OCCUPIED: + return (statusFlag & OCCUPIED); + case ID_STATUS_DND: + return (statusFlag & DND); + case ID_STATUS_FREECHAT: + return (statusFlag & FFC); + case ID_STATUS_INVISIBLE: + return (statusFlag & INVISIBLE); + case ID_STATUS_OUTTOLUNCH: + return (statusFlag & LUNCH); + case ID_STATUS_ONTHEPHONE: + return (statusFlag & PHONE); + } + return 0; +} +int CheckDate(HANDLE hContact) +{ + time_t curtime = time (NULL); + if(!DBGetContactSettingByte(hContact,modname,"GiveUpDays",0)) + return 1; + if(DBGetContactSettingByte(hContact,modname,"GiveUpDays",0) && ( abs(DBGetContactSettingDword(hContact,modname,"GiveUpDate",0)) > curtime)) + return 1; + return 0; +} + +void SendPounce(char* text, HANDLE hContact) +{ + HANDLE hSendId; + if (hSendId = (HANDLE)CallContactService(hContact, PSS_MESSAGE, 0, (LPARAM)text)) + WindowList_Add(hWindowList,(HWND)hSendId,hContact); +} + +int UserOnlineSettingChanged(WPARAM wParam,LPARAM lParam) +{ + DBCONTACTWRITESETTING *cws=(DBCONTACTWRITESETTING*)lParam; + int newStatus,oldStatus; + DBVARIANT dbv; + HANDLE hContact; + char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO,(WPARAM)wParam,0); + char* message; + if((HANDLE)wParam==NULL || strcmp(cws->szSetting,"Status")) return 0; + if (szProto && (CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0) & PF1_IM)) + { + newStatus=cws->value.wVal; + oldStatus=DBGetContactSettingWord((HANDLE)wParam,"UserOnline","OldStatus",ID_STATUS_OFFLINE); + + if ( ( newStatus != oldStatus ) && ( (HANDLE)wParam != NULL) && ( newStatus != ID_STATUS_OFFLINE) ) + { + hContact=(HANDLE)wParam; + if (!DBGetContactSetting(hContact, modname, "PounceMsg", &dbv) && (dbv.pszVal[0] != '\0')) + { + // check my status + if (statusCheck(DBGetContactSettingWord(hContact, modname, "SendIfMyStatusIsFLAG", 0), CallProtoService(szProto, PS_GETSTATUS,0,0)) + // check the contacts status + && statusCheck(DBGetContactSettingWord(hContact, modname, "SendIfTheirStatusIsFLAG", 0), newStatus) ) + { + // check if we r giving up after x days + if (CheckDate(hContact)) + { + + if (DBGetContactSettingByte(hContact, modname, "ConfirmTimeout", 0)) + { + struct SendPounceDlgProcStruct *spdps = (struct SendPounceDlgProcStruct *)malloc(sizeof(struct SendPounceDlgProcStruct)); + message = strdup(dbv.pszVal); // will get free()ed in the send confirm window proc + spdps->hContact = hContact; + spdps->message = message; + CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_CONFIRMSEND),0,SendPounceDlgProc, (LPARAM)spdps); + // set the confirmation window to send the msg when the timeout is done + } + else SendPounce(dbv.pszVal, hContact); + } + } + } + + } + } + DBFreeVariant(&dbv); + return 0; +} +HANDLE hHookSettingChanged = NULL; +HANDLE hHookoptsinit = NULL; +HANDLE hHookAck = NULL; + +int BuddyPounceMenuCommand(WPARAM wParam,LPARAM lParam) +{ + if (DBGetContactSettingByte(NULL, modname, "UseAdvanced", 0) || DBGetContactSettingByte((HANDLE)wParam, modname, "UseAdvanced", 0)) + CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_POUNCE),0,BuddyPounceDlgProc, wParam); + else CreateDialogParam(hInst,MAKEINTRESOURCE(IDD_POUNCE_SIMPLE),0,BuddyPounceSimpleDlgProc, wParam); + return 0; +} + +int AddSimpleMessage(WPARAM wParam,LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + char* message = (char*)lParam; + time_t today = time(NULL); + DBWriteContactSettingString(hContact, modname, "PounceMsg", message); + DBWriteContactSettingWord(hContact, modname, "SendIfMyStatusIsFLAG", (WORD)DBGetContactSettingWord(NULL, modname, "SendIfMyStatusIsFLAG",1)); + DBWriteContactSettingWord(hContact, modname, "SendIfTheirStatusIsFLAG", (WORD)DBGetContactSettingWord(NULL, modname, "SendIfTheirStatusIsFLAG",1)); + DBWriteContactSettingByte(hContact, modname, "Reuse", (BYTE)DBGetContactSettingByte(NULL, modname, "Reuse",0)); + DBWriteContactSettingByte(hContact, modname, "GiveUpDays", (BYTE)DBGetContactSettingByte(NULL, modname, "GiveUpDays",0)); + DBWriteContactSettingDword(hContact, modname, "GiveUpDate", (DWORD)(DBGetContactSettingByte(hContact, modname, "GiveUpDays",0)*SECONDSINADAY)); + return 0; +} + +int AddToPounce(WPARAM wParam,LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + char* message = (char*)lParam; + DBVARIANT dbv; + if (!DBGetContactSetting(hContact, modname, "PounceMsg",&dbv)) + { + char* newPounce = (char*)malloc(strlen(dbv.pszVal) + strlen(message) + 1); + if (!newPounce) return 1; + strcpy(newPounce, dbv.pszVal); + strcat(newPounce, message); + DBWriteContactSettingString(hContact, modname, "PounceMsg", newPounce); + free(newPounce); + DBFreeVariant(&dbv); + } + else AddSimpleMessage((WPARAM)hContact, (LPARAM)message); + return 0; +} + +//=========================== +// Load (hook ModulesLoaded) +//=========================== +int __declspec(dllexport) Load(PLUGINLINK *link) +{ + CLISTMENUITEM mi; + pluginLink = link; + hHookSettingChanged =HookEvent(ME_DB_CONTACT_SETTINGCHANGED,UserOnlineSettingChanged); + hHookoptsinit = HookEvent(ME_OPT_INITIALISE,BuddyPounceOptInit); + hHookAck = HookEvent(ME_PROTO_ACK,MsgAck); + CreateServiceFunction("BuddyPounce/MenuCommand",BuddyPounceMenuCommand); + hWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0); + + /* service funcitons for other devs... */ + CreateServiceFunction("BuddyPounce/AddSimplePounce",AddSimpleMessage); // add a simple pounce to a contact + CreateServiceFunction("BuddyPounce/AddToPounce",AddToPounce); // add to the exsisitng pounce, if there isnt 1 then add a new simple pounce. + /* ******************************************************** */ + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize=sizeof(mi); + mi.position=10; + mi.flags=0; + mi.hIcon= LoadIcon(hInst,MAKEINTRESOURCE(IDI_POUNCE)); + mi.pszName="&Buddy Pounce"; + mi.pszService="BuddyPounce/MenuCommand"; + mi.pszContactOwner=NULL; + + CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi); + + { // known modules list + DBVARIANT dbv; + if (DBGetContactSetting(NULL,"KnownModules","Buddy Pounce", &dbv)) + DBWriteContactSettingString(NULL,"KnownModules","Buddy Pounce",modname); + DBFreeVariant(&dbv); + } + return 0; +} + + +int __declspec(dllexport) Unload(void) +{ + if (hHookSettingChanged) + UnhookEvent(hHookSettingChanged); + return 0; +} + +//uninstall support +int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup) +{ + // Delete Files + const char* apszFiles[] = {"buddypounce_readme.txt", 0}; + PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles); + + if((ppup->bDoDeleteSettings == TRUE) && (ppup->bIsMirandaRunning == TRUE)) + { + PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)modname, (LPARAM)NULL); + } + return 0; +} \ No newline at end of file diff --git a/plugins/!NotAdopted/BuddyPounce/resource.aps b/plugins/!NotAdopted/BuddyPounce/resource.aps new file mode 100644 index 0000000000..1701ee4649 Binary files /dev/null and b/plugins/!NotAdopted/BuddyPounce/resource.aps differ diff --git a/plugins/!NotAdopted/BuddyPounce/resource.h b/plugins/!NotAdopted/BuddyPounce/resource.h new file mode 100644 index 0000000000..dfa9c1bb14 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/resource.h @@ -0,0 +1,81 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// +#define IDC_DELETE 5 +#define IDC_DEFAULT 6 +#define IDD_POUNCE 101 +#define IDI_POUNCE 104 +#define IDD_CONFIRMSEND 105 +#define IDD_POUNCE_SIMPLE 108 +#define IDD_STATUSMODES 109 +#define IDD_OPTIONS 110 +#define IDC_MESSAGE 1000 +#define CHK_OFFLINE 1003 +#define CHK_ONLINE 1004 +#define CHK_AWAY 1005 +#define CHK_NA 1006 +#define CHK_OCCUPIED 1007 +#define CHK_DND 1008 +#define CHK_FFC 1009 +#define CHK_PHONE 1010 +#define CHK_LUNCH 1011 +#define CHK_ANYSTATUS 1012 +#define CHK_ONLINE2 1013 +#define CHK_AWAY2 1014 +#define CHK_NA2 1015 +#define CHK_OCCUPIED2 1016 +#define CHK_DND2 1017 +#define CHK_FFC2 1018 +#define CHK_PHONE2 1019 +#define CHK_LUNCH2 1020 +#define CHK_REUSE 1028 +#define IDC_REUSETIMES 1029 +#define CHK_GIVEUP 1030 +#define IDC_GIVEUPDAYS 1031 +#define LBL_CONTACT 1034 +#define CHK_POUNCESETUP 1036 +#define CHK_CONFIRM 1037 +#define IDC_TIMEOUT 1038 +#define GRP_DEFAULT 1040 +#define GRP_MSG 1041 +#define GRP_SENDON 1042 +#define GRP_SENDIF 1043 +#define GRP_SETTINGS 1044 +#define IDC_STATICTIMES 1045 +#define IDC_STATICDAYS 1046 +#define IDC_STATICWAIT 1047 +#define IDC_STATICSECONDS 1048 +#define IDC_SETTINGMSG 1061 +#define IDC_SETTINGNUMBER 1066 +#define IDC_SPIN 1067 +#define IDC_SETTINGTEXT 1068 +#define IDC_BUTTON 1069 +#define IDC_SETTINGS 1075 +#define IDC_CONTACTS 1076 +#define IDC_ADVANCED 1078 +#define IDC_SIMPLE 1080 +#define IDC_CHECK1 1081 +#define IDC_CHECK2 1082 +#define IDC_CHECK3 1083 +#define IDC_CHECK4 1084 +#define IDC_CHECK5 1085 +#define IDC_CHECK6 1086 +#define IDC_CHECK7 1087 +#define IDC_CHECK8 1088 +#define IDC_CHECK9 1089 +#define IDC_CHECK10 1090 +#define IDC_SETTINGMSG2 1095 +#define IDC_USEADVANCED 1096 +#define IDC_SHOWDELIVERYMSGS 1097 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 112 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1098 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/!NotAdopted/BuddyPounce/resource.rc b/plugins/!NotAdopted/BuddyPounce/resource.rc new file mode 100644 index 0000000000..992f3cb1e3 --- /dev/null +++ b/plugins/!NotAdopted/BuddyPounce/resource.rc @@ -0,0 +1,312 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_CONFIRMSEND DIALOG DISCARDABLE 0, 0, 257, 100 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Confirm Pounce send" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Send",IDOK,51,79,50,14 + PUSHBUTTON "Cancel",IDCANCEL,154,79,50,14 + LTEXT "Pounce being sent to",LBL_CONTACT,7,7,243,8 + EDITTEXT IDC_MESSAGE,7,18,243,59,ES_MULTILINE | ES_READONLY | + WS_VSCROLL +END + +IDD_POUNCE DIALOG DISCARDABLE 0, 0, 314, 146 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Buddy Pounce" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_MESSAGE,8,15,161,60,ES_MULTILINE | ES_AUTOVSCROLL | + ES_WANTRETURN | WS_VSCROLL + DEFPUSHBUTTON "OK",IDOK,72,129,21,14 + PUSHBUTTON "Cancel",IDCANCEL,106,129,33,14 + GROUPBOX "The Message:",GRP_MSG,4,4,171,76 + PUSHBUTTON "Delete Pounce",IDC_DELETE,154,129,58,14 + PUSHBUTTON "Load default Settings",IDC_DEFAULT,230,129,78,14 + GROUPBOX "Setting Value",IDC_STATIC,4,83,171,43,WS_DISABLED + LTEXT "Setting text...........",IDC_SETTINGMSG,8,92,144,8,NOT + WS_VISIBLE | WS_TABSTOP + EDITTEXT IDC_SETTINGNUMBER,16,106,42,12,ES_NUMBER | NOT + WS_VISIBLE + CONTROL "Spin2",IDC_SPIN,"msctls_updown32",UDS_WRAP | + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | NOT WS_VISIBLE | + WS_TABSTOP,47,106,11,12 + EDITTEXT IDC_SETTINGTEXT,16,106,153,12,ES_AUTOHSCROLL | NOT + WS_VISIBLE + PUSHBUTTON "...",IDC_BUTTON,155,90,14,12,NOT WS_VISIBLE + GROUPBOX "Settings",IDC_STATIC,179,35,129,91 + LISTBOX IDC_SETTINGS,183,46,119,72,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + GROUPBOX "Contact To Send Pounce To",IDC_STATIC,179,4,129,28 + COMBOBOX IDC_CONTACTS,183,15,119,30,CBS_DROPDOWNLIST | CBS_SORT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "<< Simple",IDC_SIMPLE,8,129,50,14 + LTEXT "",IDC_SETTINGMSG2,65,106,104,8,NOT WS_VISIBLE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_CONFIRMSEND, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 250 + TOPMARGIN, 7 + BOTTOMMARGIN, 93 + END + + IDD_POUNCE, DIALOG + BEGIN + LEFTMARGIN, 4 + RIGHTMARGIN, 308 + VERTGUIDE, 8 + VERTGUIDE, 16 + VERTGUIDE, 169 + VERTGUIDE, 175 + VERTGUIDE, 179 + VERTGUIDE, 183 + VERTGUIDE, 302 + BOTTOMMARGIN, 143 + HORZGUIDE, 4 + HORZGUIDE, 15 + HORZGUIDE, 106 + HORZGUIDE, 118 + HORZGUIDE, 126 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_POUNCE ICON DISCARDABLE "icon1.ico" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_POUNCE_SIMPLE DIALOG DISCARDABLE 0, 0, 186, 90 +STYLE DS_MODALFRAME | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | WS_VISIBLE | + WS_CAPTION | WS_SYSMENU +CAPTION "Buddy Pounce" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_MESSAGE,13,17,158,43,ES_MULTILINE | ES_AUTOHSCROLL | + ES_WANTRETURN | WS_VSCROLL | WS_HSCROLL + DEFPUSHBUTTON "OK",IDOK,7,69,50,14 + PUSHBUTTON "Cancel",IDCANCEL,68,69,50,14 + PUSHBUTTON "Advanced >>",IDC_ADVANCED,129,69,50,14 + GROUPBOX "The Message",GRP_MSG,7,7,172,59 +END + +IDD_STATUSMODES DIALOG DISCARDABLE 0, 0, 186, 103 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION | + WS_SYSMENU +CAPTION "Dialog" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,82,50,14 + PUSHBUTTON "Cancel",IDCANCEL,129,82,50,14 + GROUPBOX "Static",GRP_MSG,7,7,172,73 + CONTROL "Check1",IDC_CHECK1,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,17,74,10 + CONTROL "Check1",IDC_CHECK2,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,30,74,10 + CONTROL "Check1",IDC_CHECK3,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,42,74,10 + CONTROL "Check1",IDC_CHECK4,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,54,74,10 + CONTROL "Check1",IDC_CHECK5,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,66,74,10 + CONTROL "Check1",IDC_CHECK6,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,93,17,81,10 + CONTROL "Check1",IDC_CHECK7,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,93,30,81,10 + CONTROL "Check1",IDC_CHECK8,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,93,42,81,10 + CONTROL "Check1",IDC_CHECK9,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,93,54,81,10 + CONTROL "Check1",IDC_CHECK10,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,93,66,81,10 +END + +IDD_OPTIONS DIALOG DISCARDABLE 0, 0, 314, 240 +STYLE WS_CHILD +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Use Advanced Dialog",IDC_USEADVANCED,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,18,85,10 + EDITTEXT IDC_MESSAGE,15,73,157,60,ES_MULTILINE | ES_AUTOVSCROLL | + ES_WANTRETURN | WS_VSCROLL + GROUPBOX "The Message: (Characters: )",GRP_MSG,13,63,165, + 76 + GROUPBOX "Setting Value",IDC_STATIC,13,142,165,43,WS_DISABLED + LTEXT "Setting text...........",IDC_SETTINGMSG,15,151,144,8, + NOT WS_VISIBLE | WS_TABSTOP + EDITTEXT IDC_SETTINGNUMBER,20,164,42,12,ES_NUMBER | NOT + WS_VISIBLE + CONTROL "Spin2",IDC_SPIN,"msctls_updown32",UDS_WRAP | + UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | + UDS_ARROWKEYS | UDS_NOTHOUSANDS | NOT WS_VISIBLE | + WS_TABSTOP,51,164,11,12 + EDITTEXT IDC_SETTINGTEXT,20,164,152,12,ES_AUTOHSCROLL | NOT + WS_VISIBLE + PUSHBUTTON "...",IDC_BUTTON,159,148,14,12,NOT WS_VISIBLE + GROUPBOX "Settings",IDC_STATIC,183,63,118,122 + LISTBOX IDC_SETTINGS,187,74,109,103,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_HSCROLL | WS_TABSTOP + LTEXT "",IDC_SETTINGMSG2,69,164,104,8,NOT WS_VISIBLE + GROUPBOX "Default Settings These settings are also used when sending a ""Simple"" pounce", + IDC_STATIC,7,51,300,142 + CONTROL "Show Delivery Messages",IDC_SHOWDELIVERYMSGS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,30,95,10 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_POUNCE_SIMPLE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + TOPMARGIN, 7 + BOTTOMMARGIN, 83 + END + + IDD_STATUSMODES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 179 + VERTGUIDE, 14 + VERTGUIDE, 88 + VERTGUIDE, 93 + VERTGUIDE, 174 + TOPMARGIN, 7 + BOTTOMMARGIN, 96 + HORZGUIDE, 17 + HORZGUIDE, 30 + HORZGUIDE, 42 + HORZGUIDE, 54 + HORZGUIDE, 66 + END + + IDD_OPTIONS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 307 + VERTGUIDE, 13 + VERTGUIDE, 172 + VERTGUIDE, 178 + VERTGUIDE, 183 + VERTGUIDE, 187 + VERTGUIDE, 296 + VERTGUIDE, 301 + TOPMARGIN, 7 + BOTTOMMARGIN, 233 + HORZGUIDE, 63 + HORZGUIDE, 73 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/!NotAdopted/MagneticWindows/MagneticWindows.cpp b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.cpp new file mode 100644 index 0000000000..153289166f --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.cpp @@ -0,0 +1,184 @@ +#include "MagneticWindowsCore.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Magnetic Windows +// +// Autor: Michael Kunz +// EMail: Michael.Kunz@s2005.tu-chemnitz.de +// +// +// thanks to: pescuma +// +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Variables +/////////////////////////////////////////////////////////////////////////////////////////////////// + +PLUGININFO pluginInfo = { + sizeof(PLUGININFO), + "Magnetic Windows", + PLUGIN_MAKE_VERSION(0,0,3,2), + "Makes the main contactlist and the chat windows snapping to the desktop border and to each other.", + "Michael Kunz", + "Michael.Kunz@s2005.TU-Cemnitz.de", + "(c) 2006 Michael Kunz", + "http://addons.miranda-im.org/details.php?action=viewfile&id=2871", + 0, + 0 +}; + +PLUGINLINK * pluginLink; + +HANDLE hLoadedHook, hShootDownHook, hAddService, hRemService, hWindowEventHook; + +HINSTANCE hInst; +//char ModuleName[256]; +char ModuleName[] = "MagneticWindows"; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Plugin Functions +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +//For other Plugins to start snapping for other Windows +int SnapPluginWindowStart(WPARAM wParam, LPARAM lParam) { + + if (!WindowOpen((HWND)wParam)) return 1; + + return 0; +} +//For other Plugins to stop snapping for other Windows +int SnapPluginWindowStop(WPARAM wParam, LPARAM lParam) { + + if (!WindowClose((HWND)wParam)) return 1; + + return 0; +} + +int PluginMessageWindowEvent(WPARAM wParam, LPARAM lParam) { + MessageWindowEventData* Data; + HWND hWndParent, hWnd; + + Data = (MessageWindowEventData*)(lParam); + + switch (Data->uType) { + case MSG_WINDOW_EVT_OPEN: + hWnd = Data->hwndWindow; + //WindowOpen(hWnd); + hWndParent = GetParent(hWnd); + while ((hWndParent != 0) && (hWndParent != GetDesktopWindow()) && (IsWindowVisible(hWndParent))) { + hWnd = hWndParent; + hWndParent = GetParent(hWnd); + } + + WindowOpen(hWnd); + break; + + case MSG_WINDOW_EVT_CLOSING: + WindowClose(Data->hwndWindow); + break; + + default: + break; + } + + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Main Functions +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +int SnapPluginStart(WPARAM wParam, LPARAM lParam) { + + LoadOptions(); + + hWindowEventHook = HookEvent(ME_MSG_WINDOWEVENT, PluginMessageWindowEvent); + + WindowOpen((HWND)CallService(MS_CLUI_GETHWND,0,0)); + return 0; +} + +int SnapPluginShootDown(WPARAM wParam, LPARAM lParam) { + UnhookEvent(hWindowEventHook); + UnhookEvent(hLoadedHook); + UnhookEvent(hShootDownHook); + UnhookEvent(hInitOptionsHook); + + WindowCloseAll(); + + DestroyServiceFunction(hAddService); + DestroyServiceFunction(hRemService); + DestroyServiceFunction(hSnapToListService); + + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Exportet Functions +/////////////////////////////////////////////////////////////////////////////////////////////////// + +extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink = link; + + hLoadedHook = HookEvent(ME_SYSTEM_MODULESLOADED, SnapPluginStart); + hShootDownHook = HookEvent(ME_SYSTEM_PRESHUTDOWN, SnapPluginShootDown); + hInitOptionsHook = HookEvent(ME_OPT_INITIALISE, InitOptions); + + hAddService = CreateServiceFunction(MS_MW_ADDWINDOW, SnapPluginWindowStart); + hRemService = CreateServiceFunction(MS_MW_REMWINDOW, SnapPluginWindowStop); + hSnapToListService = CreateServiceFunction(MS_MW_SNAPTOLIST, SnapToList); + + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + return 0; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// DLL MAIN +/////////////////////////////////////////////////////////////////////////////////////////////////// + + +extern "C" bool APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + hInst = hModule; + + +/* char * Temp; + char * l,i; + + Temp = (char*) malloc(2048); + GetModuleFileName(hModule, Temp, 2048); + + l = Temp; + i = Temp; + + while (i != 0) { + if ((*i) == '\') l = i + 1; + i++; + } + + memcpy(ModuleName, l, i-l); + free(Temp); + */ + + return true; +} diff --git a/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsp b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsp new file mode 100644 index 0000000000..6f4a4e3dcf --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsp @@ -0,0 +1,146 @@ +# Microsoft Developer Studio Project File - Name="MagneticWindows" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=MagneticWindows - Win32 Debug +!MESSAGE Dies ist kein gьltiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und fьhren Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "MagneticWindows.mak". +!MESSAGE +!MESSAGE Sie kцnnen beim Ausfьhren von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "MagneticWindows.mak" CFG="MagneticWindows - Win32 Debug" +!MESSAGE +!MESSAGE Fьr die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "MagneticWindows - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "MagneticWindows - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "MagneticWindows - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAGNETICWINDOWS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /GB /Zp4 /MT /W4 /GR- /GX /O2 /Oy- /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAGNETICWINDOWS_EXPORTS" /FR /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 + +!ELSEIF "$(CFG)" == "MagneticWindows - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAGNETICWINDOWS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MAGNETICWINDOWS_EXPORTS" /FR /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "MagneticWindows - Win32 Release" +# Name "MagneticWindows - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\MagneticWindows.cpp +# End Source File +# Begin Source File + +SOURCE=.\MagneticWindowsCore.cpp +# End Source File +# Begin Source File + +SOURCE=.\Options.cpp +# End Source File +# Begin Source File + +SOURCE=.\Options.rc +# End Source File +# Begin Source File + +SOURCE=.\SnapToListService.cpp +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\m_MagneticWindows.h +# End Source File +# Begin Source File + +SOURCE=.\MagneticWindowsCore.h +# End Source File +# Begin Source File + +SOURCE=.\Options.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\SnapToListService.h +# End Source File +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsw b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsw new file mode 100644 index 0000000000..36019647d8 --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/MagneticWindows.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELЦSCHT WERDEN! + +############################################################################### + +Project: "MagneticWindows"=".\MagneticWindows.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.cpp b/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.cpp new file mode 100644 index 0000000000..044dcc098e --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.cpp @@ -0,0 +1,464 @@ +#include "MagneticWindowsCore.h" + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Variables +/////////////////////////////////////////////////////////////////////////////////////////////////// + +TWorkingVariables Globals = { + NULL, + NULL, + 0,0, + false,false +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Functions +/////////////////////////////////////////////////////////////////////////////////////////////////// + +int Abs(int a) { + if (a < 0) return (-a); + return a; +} + + +PDockingWindow FindDockingWindow(HWND hWnd) { + PDockingWindow i; + + i = Globals.WindowList; + + while (i != NULL) { + + if (i->hWnd == hWnd) return i; + + i = i->Next; + }; + + return NULL; +} + + +void DockWindowRect(HWND hWnd, bool Sizing, RECT& GivenRect, int SizingEdge, int MouseX = 0, int MouseY = 0) { + POINT p; + int diffX, diffY; + RECT tmpRect, frmRect; + int W, H; + int XPos, YPos; + int tmpXPos, tmpYPos; + int tmpMouseX, tmpMouseY; + bool FoundX, FoundY; + + PRectList ActRect; + + diffX = Options.SnapWidth; + diffY = Options.SnapWidth; + + tmpRect = GivenRect; + frmRect = GivenRect; + + FoundX = false; + FoundY = false; + + if (!Sizing) { + GetCursorPos(&p); + if (Globals.SnappedX) { + tmpMouseX = p.x - tmpRect.left; + OffsetRect(&tmpRect, tmpMouseX - MouseX, 0); + OffsetRect(&GivenRect, tmpMouseX - MouseX, 0); + } else { + MouseX = p.x - tmpRect.left; + } + if (Globals.SnappedY) { + tmpMouseY = p.y - tmpRect.top; + OffsetRect(&tmpRect, 0, tmpMouseY - MouseY); + OffsetRect(&GivenRect, 0, tmpMouseY - MouseY); + } else { + MouseY = p.y - tmpRect.top; + } + } + + W = tmpRect.right - tmpRect.left; + H = tmpRect.bottom - tmpRect.top; + + if (!Sizing) { + ActRect = Globals.Rects; + while (ActRect != NULL) { + if ((tmpRect.left >= (ActRect->Rect.left - Options.SnapWidth)) && + (tmpRect.left <= (ActRect->Rect.left + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) & + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpRect.left - ActRect->Rect.left) < diffX)) + { + GivenRect.left = ActRect->Rect.left; + GivenRect.right = GivenRect.left + W; + + diffX = Abs(tmpRect.left - ActRect->Rect.left); + + FoundX = true; + } else + if ((ActRect != Globals.Rects) && + (tmpRect.left >= (ActRect->Rect.right - Options.SnapWidth)) && + (tmpRect.left <= (ActRect->Rect.right + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) && + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpRect.left - ActRect->Rect.right) < diffX)) + { + GivenRect.left = ActRect->Rect.right; + GivenRect.right = GivenRect.left + W; + + diffX = Abs(tmpRect.left - ActRect->Rect.right); + + FoundX = true; + } else + if ((ActRect != Globals.Rects) && + (tmpRect.right >= (ActRect->Rect.left - Options.SnapWidth)) && + (tmpRect.right <= (ActRect->Rect.left + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) && + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpRect.right - ActRect->Rect.left) < diffX)) + { + GivenRect.right = ActRect->Rect.left; + GivenRect.left = GivenRect.right - W; + + diffX = Abs(tmpRect.right - ActRect->Rect.left); + + FoundX = true; + } else + if ((tmpRect.right >= (ActRect->Rect.right - Options.SnapWidth)) && + (tmpRect.right <= (ActRect->Rect.right + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) && + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpRect.right - ActRect->Rect.right) < diffX)) + { + GivenRect.right = ActRect->Rect.right; + GivenRect.left = GivenRect.right - W; + + diffX = Abs(tmpRect.right - ActRect->Rect.right); + + FoundX = true; + } + + + if ((tmpRect.top >= (ActRect->Rect.top - Options.SnapWidth)) && + (tmpRect.top <= (ActRect->Rect.top + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpRect.top - ActRect->Rect.top) < diffY)) + { + GivenRect.top = ActRect->Rect.top; + GivenRect.bottom = GivenRect.top + H; + + diffY = Abs(tmpRect.top - ActRect->Rect.top); + + FoundY = true; + } else + if ((ActRect != Globals.Rects) && + (tmpRect.top >= (ActRect->Rect.bottom - Options.SnapWidth)) && + (tmpRect.top <= (ActRect->Rect.bottom + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpRect.top - ActRect->Rect.bottom) < diffY)) + { + GivenRect.top = ActRect->Rect.bottom; + GivenRect.bottom = GivenRect.top + H; + + diffY = Abs(tmpRect.top - ActRect->Rect.bottom); + + FoundY = true; + } else + if ((ActRect != Globals.Rects) && + (tmpRect.bottom >= (ActRect->Rect.top - Options.SnapWidth)) && + (tmpRect.bottom <= (ActRect->Rect.top + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpRect.bottom - ActRect->Rect.top) < diffY)) + { + GivenRect.bottom = ActRect->Rect.top; + GivenRect.top = GivenRect.bottom - H; + + diffY = Abs(tmpRect.bottom - ActRect->Rect.top); + + FoundY = true; + } else + if ((tmpRect.bottom >= (ActRect->Rect.bottom - Options.SnapWidth)) && + (tmpRect.bottom <= (ActRect->Rect.bottom + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpRect.bottom - ActRect->Rect.bottom) < diffY)) + { + GivenRect.bottom = ActRect->Rect.bottom; + GivenRect.top = GivenRect.bottom - H; + + diffY = Abs(tmpRect.bottom - ActRect->Rect.bottom); + + FoundY = true; + } + + ActRect = ActRect->Next; + } //next rect + + Globals.SnappedX = FoundX; + Globals.SnappedY = FoundY; + } + else //Sizing + { + if ((SizingEdge == WMSZ_LEFT) || + (SizingEdge == WMSZ_TOPLEFT) || + (SizingEdge == WMSZ_BOTTOMLEFT)) + { + XPos = GivenRect.left; + } else { + XPos = GivenRect.right; + } + + if ((SizingEdge == WMSZ_TOP) || + (SizingEdge == WMSZ_TOPLEFT) || + (SizingEdge == WMSZ_TOPRIGHT)) + { + YPos = GivenRect.top; + } else { + YPos = GivenRect.bottom; + } + + tmpXPos = XPos; + tmpYPos = YPos; + + ActRect = Globals.Rects; + while (ActRect != NULL) { + if ((tmpXPos >= (ActRect->Rect.left - Options.SnapWidth)) && + (tmpXPos <= (ActRect->Rect.left + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) && + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpXPos - ActRect->Rect.left) < diffX)) + { + XPos = ActRect->Rect.left; + + diffX = Abs(tmpXPos - ActRect->Rect.left); + } else + if ((tmpXPos >= (ActRect->Rect.right - Options.SnapWidth)) && + (tmpXPos <= (ActRect->Rect.right + Options.SnapWidth)) && + ((tmpRect.top - Options.SnapWidth) < ActRect->Rect.bottom) && + ((tmpRect.bottom + Options.SnapWidth) > ActRect->Rect.top) && + (Abs(tmpXPos - ActRect->Rect.right) < diffX)) + { + XPos = ActRect->Rect.right; + + diffX = Abs(tmpXPos - ActRect->Rect.right); + } + + if ((tmpYPos >= (ActRect->Rect.top - Options.SnapWidth)) && + (tmpYPos <= (ActRect->Rect.top + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpYPos - ActRect->Rect.top) < diffY)) + { + YPos = ActRect->Rect.top; + + diffY = Abs(tmpYPos - ActRect->Rect.top); + } else + if ((tmpYPos >= (ActRect->Rect.bottom - Options.SnapWidth)) && + (tmpYPos <= (ActRect->Rect.bottom + Options.SnapWidth)) && + ((tmpRect.left - Options.SnapWidth) < ActRect->Rect.right) && + ((tmpRect.right + Options.SnapWidth) > ActRect->Rect.left) && + (Abs(tmpYPos - ActRect->Rect.bottom) < diffY)) + { + YPos = ActRect->Rect.bottom; + + diffY = Abs(tmpYPos - ActRect->Rect.bottom); + } + + ActRect = ActRect->Next; + } //Next rect + + if ((SizingEdge == WMSZ_LEFT) || + (SizingEdge == WMSZ_TOPLEFT) || + (SizingEdge == WMSZ_BOTTOMLEFT)) + { + GivenRect.left = XPos; + } else { + GivenRect.right = XPos; + } + if ((SizingEdge == WMSZ_TOP) || + (SizingEdge == WMSZ_TOPLEFT) || + (SizingEdge == WMSZ_TOPRIGHT)) + { + GivenRect.top = YPos; + } else { + GivenRect.bottom = YPos; + } + } +} + + +void GetFrmRects(HWND ForWindow) { +PDockingWindow i; +PRectList Rect, l; + + Rect = Globals.Rects; + while (Rect != NULL) { + l = Rect; + Rect = Rect->Next; + free(l); + } + + Rect = (PRectList)malloc(sizeof(TRectList)); + Rect->Next = NULL; + Globals.Rects = Rect; + + SystemParametersInfo(SPI_GETWORKAREA, 0, &(Rect->Rect), 0); + i = Globals.WindowList; + + while (i != NULL) { + if ((i->hWnd != ForWindow) && IsWindowVisible(i->hWnd)) { + l = Rect; + Rect = (PRectList)malloc(sizeof(TRectList)); + Rect->Next = NULL; + l->Next = Rect; + + GetWindowRect(i->hWnd, &(Rect->Rect)); + } + + i = i->Next; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Subclass Window Proc +/////////////////////////////////////////////////////////////////////////////////////////////////// + +LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { + PDockingWindow i; + + RECT r; + POINT p; + + WNDPROC OldRun; + + i = FindDockingWindow(hWnd); + + OldRun = NULL; + + if (i != NULL) { //else we have a problem + OldRun = i->OldWindowProc; + + if (Options.DoSnap) { + switch (Msg) { + case WM_ENTERSIZEMOVE: { + if (Options.ScriverWorkAround) + keybd_event(VK_CONTROL, 0, 0, 0); + + GetWindowRect(hWnd, &r); + GetCursorPos(&p); + Globals.MouseX = p.x - r.left; + Globals.MouseY = p.y - r.top; + + GetFrmRects(hWnd); + + break; + } + case WM_EXITSIZEMOVE: { + if (Options.ScriverWorkAround) + keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); + + break; + } + case WM_SIZING: + case WM_MOVING: { + r = *((PRECT)lParam); + if (Msg == WM_SIZING) { + DockWindowRect(hWnd, true, r, wParam); + } else { + DockWindowRect(hWnd, false, r, wParam, Globals.MouseX, Globals.MouseY); + } + + (*(PRECT)lParam) = r; + + if (Msg == WM_SIZING) { + return 1; + } + + break; + } + } //switch + } //if dosnap + + if (OldRun != NULL) { + if (IsWindowUnicode(hWnd)) { + return CallWindowProcW(OldRun, hWnd, Msg, wParam, lParam); + } else { + return CallWindowProcA(OldRun, hWnd, Msg, wParam, lParam); + } + } + } + + return 0; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// exportet Functions +/////////////////////////////////////////////////////////////////////////////////////////////////// + +bool WindowOpen(HWND hWnd) { + PDockingWindow i; + + if ((hWnd != 0) && (FindDockingWindow(hWnd) == NULL)) { + i = (PDockingWindow)malloc(sizeof(TDockingWindow)); + i->Next = Globals.WindowList; + i->hWnd = hWnd; + Globals.WindowList = i; + + if (IsWindowUnicode(hWnd)) { + i->OldWindowProc = (WNDPROC) GetWindowLongW(hWnd, GWL_WNDPROC); + SetWindowLongW(hWnd, GWL_WNDPROC, (LONG)(&WindowProc)); + } else { + i->OldWindowProc = (WNDPROC) GetWindowLongA(hWnd, GWL_WNDPROC); + SetWindowLongA(hWnd, GWL_WNDPROC, (LONG)(&WindowProc)); + } + + return true; + } + return false; +} + +bool WindowClose(HWND hWnd) { + PDockingWindow i, l; + + l = NULL; + i = Globals.WindowList; + + while ((i != NULL) && (i->hWnd != hWnd)) { + l = i; + i = i->Next; + } + + if (i != NULL) { + if (l == NULL) { + Globals.WindowList = i->Next; + } else { + l->Next = i->Next; + } + + if (IsWindowUnicode(hWnd)) { + SetWindowLongW(hWnd, GWL_WNDPROC, (LONG) (i->OldWindowProc)); + } else { + SetWindowLongA(hWnd, GWL_WNDPROC, (LONG) (i->OldWindowProc)); + } + + free(i); + + return true; + } + + return false; +} +bool WindowCloseAll() { + PDockingWindow i, l; + i = Globals.WindowList; + while (i != NULL) { + l = i; + WindowClose(i->hWnd); + i = i->Next; + free(l); + } + return true; +} \ No newline at end of file diff --git a/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.h b/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.h new file mode 100644 index 0000000000..63d9b6a5e3 --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/MagneticWindowsCore.h @@ -0,0 +1,45 @@ +#include +#include +#include +#include "../include/newpluginapi.h" +#include "../include/m_clist.h" +#include "../include/m_clui.h" +#include "../include/m_message.h" +#include "../include/m_system.h" +#include "../include/m_options.h" +#include "../include/m_plugins.h" +#include "../include/m_database.h" +#include "../include/m_langpack.h" +#include "m_MagneticWindows.h" +#include "SnapToListService.h" +#include "Options.h" +#include "resource.h" + + +typedef + struct TDockingWindow { + HWND hWnd; + WNDPROC OldWindowProc; + TDockingWindow* Next; + } TDockingWindow, *PDockingWindow; +typedef + struct TRectList { + RECT Rect; + TRectList* Next; + } TRectList, *PRectList; +typedef + struct { + PDockingWindow WindowList; + PRectList Rects; + int MouseX, MouseY; + bool SnappedX, SnappedY; + } TWorkingVariables; + + + +extern HINSTANCE hInst; +extern char ModuleName []; + +bool WindowOpen(HWND); +bool WindowClose(HWND); +bool WindowCloseAll(); \ No newline at end of file diff --git a/plugins/!NotAdopted/MagneticWindows/Options.cpp b/plugins/!NotAdopted/MagneticWindows/Options.cpp new file mode 100644 index 0000000000..163c39f34c --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/Options.cpp @@ -0,0 +1,128 @@ +#include "MagneticWindowsCore.h" + +HANDLE hInitOptionsHook; +TOptions Options = { + true, + cDefaultSnapWidth, + false +}; + + +int CALLBACK OptionsDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + + char str[64]; + + switch (msg) { + case WM_INITDIALOG: { + TranslateDialogDefault(hwndDlg); + + CheckDlgButton(hwndDlg, IDC_CHK_SNAP, Options.DoSnap?BST_CHECKED:BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_SLIDER_SNAPWIDTH, TBM_SETRANGE, FALSE, MAKELONG(1,32)); + SendDlgItemMessage(hwndDlg, IDC_SLIDER_SNAPWIDTH, TBM_SETPOS, TRUE, Options.SnapWidth); + + wsprintf(str, Translate("%d pix"), Options.SnapWidth); + SetDlgItemText(hwndDlg, IDC_TXT_SNAPWIDTH, str); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_SNAPWIDTH), Options.DoSnap); + EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_SNAPWIDTH), Options.DoSnap); + + CheckDlgButton(hwndDlg, IDC_CHK_SCRIVERWORKAROUND, Options.ScriverWorkAround?BST_CHECKED:BST_UNCHECKED); + + break; + } + case WM_HSCROLL: { + _snprintf(str, 64, Translate("%d pix"), SendDlgItemMessage(hwndDlg, IDC_SLIDER_SNAPWIDTH, TBM_GETPOS, 0, 0)); + SetDlgItemText(hwndDlg, IDC_TXT_SNAPWIDTH, str); + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + + case WM_COMMAND: { + WORD idCtrl = LOWORD(wParam), wNotifyCode = HIWORD(wParam); + + switch(idCtrl) { + case IDC_CHK_SNAP: { + if (wNotifyCode == BN_CLICKED) { + + + EnableWindow(GetDlgItem(hwndDlg, IDC_SLIDER_SNAPWIDTH), IsDlgButtonChecked(hwndDlg, IDC_CHK_SNAP)); + EnableWindow(GetDlgItem(hwndDlg, IDC_TXT_SNAPWIDTH), IsDlgButtonChecked(hwndDlg, IDC_CHK_SNAP)); + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + } + case IDC_CHK_SCRIVERWORKAROUND: { + if (wNotifyCode == BN_CLICKED) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + } + } + break; + } + + case WM_NOTIFY: { //Here we have pressed either the OK or the APPLY button. + switch(((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadOptions(); + break; + + case PSN_APPLY: { + Options.DoSnap = (IsDlgButtonChecked(hwndDlg, IDC_CHK_SNAP) == TRUE); + Options.SnapWidth = SendDlgItemMessage(hwndDlg, IDC_SLIDER_SNAPWIDTH, TBM_GETPOS, 0, 0); + Options.ScriverWorkAround = (IsDlgButtonChecked(hwndDlg, IDC_CHK_SCRIVERWORKAROUND) == TRUE); + + DBWriteContactSettingByte(NULL, ModuleName, "DoSnap", Options.DoSnap); + DBWriteContactSettingByte(NULL, ModuleName, "SnapWidth", Options.SnapWidth); + DBWriteContactSettingByte(NULL, ModuleName, "ScriverWorkAround", Options.ScriverWorkAround); + + break; + } + } + break; + } + + break; + + } + default: + + break; + } + return 0; + +} + +int InitOptions(WPARAM wParam, LPARAM lParam) { + OPTIONSDIALOGPAGE Opt = { 0 }; + + Opt.cbSize = sizeof(Opt); +// Opt.position = 0; + Opt.pszTitle = "Magnetic Windows"; + Opt.pfnDlgProc = &OptionsDlgProc; + Opt.pszTemplate = (char *) MAKEINTRESOURCE(IDD_OPT_MAGNETICWINDOWS); + Opt.hInstance = hInst; +// Opt.hIcon = 0; + Opt.pszGroup = "Customize"; +// Opt.groupPosition = 0; +// Opt.hGroupIcon = 0; + Opt.flags = ODPF_BOLDGROUPS; +// Opt.nIDBottomSimpleControl = 0; +// Opt.nIDRightSimpleControl = 0; +// Opt.expertOnlyControls = NULL; +// Opt.nExpertOnlyControls = 0; + + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)(&Opt)); + + return 0; +} + +void LoadOptions() { + Options.DoSnap = DBGetContactSettingByte(NULL, ModuleName, "DoSnap", TRUE); + Options.SnapWidth = DBGetContactSettingByte(NULL, ModuleName, "SnapWidth", cDefaultSnapWidth); + Options.ScriverWorkAround = DBGetContactSettingByte(NULL, ModuleName, "ScriverWorkAround", FALSE); +} \ No newline at end of file diff --git a/plugins/!NotAdopted/MagneticWindows/Options.h b/plugins/!NotAdopted/MagneticWindows/Options.h new file mode 100644 index 0000000000..ebb5458d4a --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/Options.h @@ -0,0 +1,18 @@ + +#define cDefaultSnapWidth 12 + +typedef + struct TOptions { + bool DoSnap; + int SnapWidth; + bool ScriverWorkAround; +} TOptions; + +extern HANDLE hInitOptionsHook; +extern TOptions Options; + + +int CALLBACK OptionsDlgProc(HWND, UINT, WPARAM, LPARAM); + +int InitOptions(WPARAM, LPARAM); +void LoadOptions(); \ No newline at end of file diff --git a/plugins/!NotAdopted/MagneticWindows/Options.rc b/plugins/!NotAdopted/MagneticWindows/Options.rc new file mode 100644 index 0000000000..5968a21cb7 --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/Options.rc @@ -0,0 +1,113 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Deutsch (Deutschland) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU) +#ifdef _WIN32 +LANGUAGE LANG_GERMAN, SUBLANG_GERMAN +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Deutsch (Deutschland) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Englisch (USA) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_MAGNETICWINDOWS DIALOGEX 0, 0, 275, 80 +STYLE DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Magnetic Windows",IDC_MAINFRAME,8,8,258,64,WS_GROUP + CONTROL "",IDC_SLIDER_SNAPWIDTH,"msctls_trackbar32",TBS_BOTH | + TBS_NOTICKS | WS_TABSTOP,108,24,96,12 + CONTROL "Snap windows",IDC_CHK_SNAP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,18,24,84,12 + LTEXT "15 pix",IDC_TXT_SNAPWIDTH,216,24,42,12,SS_CENTERIMAGE + CONTROL "For Scriver users: automatically hold down the CTRL key while moving/sizing. (make sure you use Scriver!)", + IDC_CHK_SCRIVERWORKAROUND,"Button",BS_AUTOCHECKBOX | + BS_MULTILINE | WS_TABSTOP,18,44,239,20,WS_EX_TRANSPARENT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPT_MAGNETICWINDOWS, DIALOG + BEGIN + RIGHTMARGIN, 273 + BOTTOMMARGIN, 79 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Englisch (USA) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/!NotAdopted/MagneticWindows/SnapToListService.cpp b/plugins/!NotAdopted/MagneticWindows/SnapToListService.cpp new file mode 100644 index 0000000000..5fc9f66268 --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/SnapToListService.cpp @@ -0,0 +1,64 @@ +#include "MagneticWindowsCore.h" + + +HANDLE hSnapToListService; + + +int SnapToList(WPARAM wParam, LPARAM Align) { + HWND hWnd, hWndList; + RECT WndRect, ListRect; + RECT AlignRect; + RECT ResultRect; + + hWnd = (HWND)wParam; + + hWndList = (HWND)CallService(MS_CLUI_GETHWND,0,0); + GetWindowRect(hWnd, &WndRect); + GetWindowRect(hWndList, &ListRect); + + AlignRect = ListRect; + if ((!(MS_MW_STL_List_Left & Align)) && (MS_MW_STL_List_Right & Align)) { + AlignRect.left = AlignRect.right; + } else + if ((MS_MW_STL_List_Left & Align) && (!(MS_MW_STL_List_Right & Align))) { + AlignRect.right = AlignRect.left; + } + + if ((!(MS_MW_STL_List_Top & Align)) && (MS_MW_STL_List_Bottom & Align)) { + AlignRect.top = AlignRect.bottom; + } else + if ((MS_MW_STL_List_Top & Align) && (!(MS_MW_STL_List_Bottom & Align))) { + AlignRect.bottom = AlignRect.top; + } + + ResultRect = WndRect; + if ((MS_MW_STL_Wnd_Left & Align) && (MS_MW_STL_Wnd_Right & Align)) { + ResultRect.left = AlignRect.left; + ResultRect.right = AlignRect.right; + } else + if ((!(MS_MW_STL_Wnd_Left & Align)) && (MS_MW_STL_Wnd_Right & Align)) { + ResultRect.left = AlignRect.right - (WndRect.right - WndRect.left); + ResultRect.right = AlignRect.right; + } else + if ((MS_MW_STL_Wnd_Left & Align) && (!(MS_MW_STL_Wnd_Right & Align))) { + ResultRect.left = AlignRect.left; + ResultRect.right = AlignRect.left + (WndRect.right - WndRect.left); + } + + if ((MS_MW_STL_Wnd_Top & Align) && (MS_MW_STL_Wnd_Bottom & Align)) { + ResultRect.top = AlignRect.top; + ResultRect.bottom = AlignRect.bottom; + } else + if ((!(MS_MW_STL_Wnd_Top & Align)) && (MS_MW_STL_Wnd_Bottom & Align)) { + ResultRect.top = AlignRect.bottom - (WndRect.bottom - WndRect.top); + ResultRect.bottom = AlignRect.bottom; + } else + if ((MS_MW_STL_Wnd_Top & Align) && (!(MS_MW_STL_Wnd_Bottom & Align))) { + ResultRect.top = AlignRect.top; + ResultRect.bottom = AlignRect.top + (WndRect.bottom - WndRect.top); + } + + MoveWindow(hWnd, ResultRect.left, ResultRect.top, ResultRect.right-ResultRect.left, ResultRect.bottom-ResultRect.top, true); + + return 0; +} \ No newline at end of file diff --git a/plugins/!NotAdopted/MagneticWindows/SnapToListService.h b/plugins/!NotAdopted/MagneticWindows/SnapToListService.h new file mode 100644 index 0000000000..27db7246cd --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/SnapToListService.h @@ -0,0 +1,5 @@ + + +extern HANDLE hSnapToListService; + +int SnapToList(WPARAM, LPARAM); diff --git a/plugins/!NotAdopted/MagneticWindows/m_MagneticWindows.h b/plugins/!NotAdopted/MagneticWindows/m_MagneticWindows.h new file mode 100644 index 0000000000..e011c773fd --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/m_MagneticWindows.h @@ -0,0 +1,86 @@ +#ifndef __M_MAGNETICWINDOWS_H__ +#define __M_MAGNETICWINDOWS_H__ + +//#include "../include/newpluginapi.h" + +// For other Plugins to start snapping for their windows +// wparam: hwnd of window +// lparam: 0 +// return: 0 on success, 1 on error +#define MS_MW_ADDWINDOW "Utils/MagneticWindows/Add" + +// For other Plugins to stop snapping for their windows +// wparam: hwnd of window +// lparam: 0 +// return: 0 on success, 1 on error +#define MS_MW_REMWINDOW "Utils/MagneticWindows/Rem" + +//decide where to align on the list: +#define MS_MW_STL_List_Left 0x00000001 //Snaps the window to the left border of the list +#define MS_MW_STL_List_Top 0x00000002 //Snaps the window to the top border of the list +#define MS_MW_STL_List_Right 0x00000004 //Snaps the window to the right border of the list +#define MS_MW_STL_List_Bottom 0x00000008 //Snaps the window to the bottom border of the list +//decide with what side (of the window you want to snap) to snap to the list +#define MS_MW_STL_Wnd_Left 0x00000010 //Snaps the window with the left border to the left/right side of the list +#define MS_MW_STL_Wnd_Top 0x00000020 //Snaps the window with the top border to the top/bottom side of the list +#define MS_MW_STL_Wnd_Right 0x00000040 //Snaps the window with the right border to the left/right side of the list +#define MS_MW_STL_Wnd_Bottom 0x00000080 //Snaps the window with the bottom border to the top/bottom side of the list + +#define MS_MW_STL_Wnd_FullWidth (MS_MW_STL_Wnd_Left | MS_MW_STL_Wnd_Right) + //Snaps to the top/bottom of the list and spans over the full width + +#define MS_MW_STL_Wnd_FullHeight (MS_MW_STL_Wnd_Top | MS_MW_STL_Wnd_Bottom) + //Snaps to the left/right of the list and spans over the full height + +// to place the window in the list combine f.e. MS_MW_STL_List_Left | MS_MW_STL_Wnd_Right | *vetical alignment* + +//For other Plugins to snap a window to the list for other Plugins +// wparam: hwnd of window +// lparam: combination of the above constants MS_MW_STL_* +// return: 0 on success, 1 on error +#define MS_MW_SNAPTOLIST "Utils/MagneticWindows/SnapToList" + +// Helper functions +#ifndef _MW_NO_HELPPER_FUNCTIONS + + +static inline int MagneticWindows_AddWindow(HWND hWnd) +{ + if (ServiceExists(MS_MW_ADDWINDOW)) + { + return CallService(MS_MW_ADDWINDOW, (WPARAM) hWnd, 0); + } + else + { + return -1; + } +} + +static inline int MagneticWindows_RemoveWindow(HWND hWnd) +{ + if (ServiceExists(MS_MW_REMWINDOW)) + { + return CallService(MS_MW_REMWINDOW, (WPARAM) hWnd, 0); + } + else + { + return -1; + } +} + +static inline int MagneticWindows_SnapWindowToList(HWND hWnd, int MS_MW_STL_Options) +{ + if (ServiceExists(MS_MW_SNAPTOLIST)) + { + return CallService(MS_MW_SNAPTOLIST, (WPARAM) hWnd, (LPARAM) MS_MW_STL_Options); + } + else + { + return -1; + } +} + +#endif + + +#endif // __M_MAGNETICWINDOWS_H__ diff --git a/plugins/!NotAdopted/MagneticWindows/resource.h b/plugins/!NotAdopted/MagneticWindows/resource.h new file mode 100644 index 0000000000..a651a69a50 --- /dev/null +++ b/plugins/!NotAdopted/MagneticWindows/resource.h @@ -0,0 +1,25 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Options.rc +// + +#define IDD_OPT_MAGNETICWINDOWS 101 + + +#define IDC_MAINFRAME 1001 +#define IDC_SLIDER_SNAPWIDTH 1002 +#define IDC_CHK_SNAP 1003 +#define IDC_TXT_SNAPWIDTH 1004 +#define IDC_CHK_SCRIVERWORKAROUND 1005 + + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1006 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/!NotAdopted/MessagePopup/AggressiveOptimize.h b/plugins/!NotAdopted/MessagePopup/AggressiveOptimize.h new file mode 100644 index 0000000000..c373fa70ad --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/AggressiveOptimize.h @@ -0,0 +1,165 @@ +////////////////////////////// +// Version 1.40 +// October 22nd, 2002 - .NET (VC7, _MSC_VER=1300) support! +// Version 1.30 +// Nov 24th, 2000 +// Version 1.20 +// Jun 9th, 2000 +// Version 1.10 +// Jan 23rd, 2000 +// Version 1.00 +// May 20th, 1999 +// Todd C. Wilson, Fresh Ground Software +// (todd@nopcode.com) +// This header file will kick in settings for Visual C++ 5 and 6 that will (usually) +// result in smaller exe's. +// The "trick" is to tell the compiler to not pad out the function calls; this is done +// by not using the /O1 or /O2 option - if you do, you implicitly use /Gy, which pads +// out each and every function call. In one single 500k dll, I managed to cut out 120k +// by this alone! +// The other two "tricks" are telling the Linker to merge all data-type segments together +// in the exe file. The relocation, read-only (constants) data, and code section (.text) +// sections can almost always be merged. Each section merged can save 4k in exe space, +// since each section is padded out to 4k chunks. This is very noticeable with smaller +// exes, since you could have only 700 bytes of data, 300 bytes of code, 94 bytes of +// strings - padded out, this could be 12k of runtime, for 1094 bytes of stuff! For larger +// programs, this is less overall, but can save at least 4k. +// Note that if you're using MFC static or some other 3rd party libs, you may get poor +// results with merging the readonly (.rdata) section - the exe may grow larger. +// To use this feature, define _MERGE_RDATA_ in your project or before this header is used. +// With Visual C++ 5, the program uses a file alignment of 512 bytes, which results +// in a small exe. Under VC6, the program instead uses 4k, which is the same as the +// section size. The reason (from what I understand) is that 4k is the chunk size of +// the virtual memory manager, and that WinAlign (an end-user tuning tool for Win98) +// will re-align the programs on this boundary. The problem with this is that all of +// Microsoft's system exes and dlls are *NOT* tuned like this, and using 4k causes serious +// exe bloat. This is very noticeable for smaller programs. +// The "trick" for this is to use the undocumented FILEALIGN linker parm to change the +// padding from 4k to 1/2k, which results in a much smaller exe - anywhere from 20%-75% +// depending on the size. Note that this is the same as using /OPT:NOWIN98, which *is* +// a previously documented switch, but was left out of the docs for some reason in VC6 and +// all of the current MSDN's - see KB:Q235956 for more information. +// Microsoft does say that using the 4k alignment will "speed up process loading", +// but I've been unable to notice a difference, even on my P180, with a very large (4meg) exe. +// Please note, however, that this will probably not change the size of the COMPRESSED +// file (either in a .zip file or in an install archive), since this 4k is all zeroes and +// gets compressed away. +// Also, the /ALIGN:4096 switch will "magically" do the same thing, even though this is the +// default setting for this switch. Apparently this sets the same values as the above two +// switches do. We do not use this in this header, since it smacks of a bug and not a feature. +// Thanks to Michael Geary for some additional tips! +// +// Notes about using this header in .NET +// First off, VC7 does not allow a lot of the linker command options in pragma's. There is no +// honest or good reason why Microsoft decided to make this change, it just doesn't. +// So that is why there are a lot of <1300 #if's in the header. +// If you want to take full advantage of the VC7 linker options, you will need to do it on a +// PER PROJECT BASIS; you can no longer use a global header file like this to make it better. +// Items I strongly suggest putting in all your VC7 project linker options command line settings: +// /ignore:4078 /RELEASE +// Compiler options: +// /GL (Whole Program Optimization) +// If you're making an .EXE and not a .DLL, consider adding in: +// /GA (Optimize for Windows Application) +// Some items to consider using in your VC7 projects (not VC6): +// Link-time Code Generation - whole code optimization. Put this in your exe/dll project link settings. +// /LTCG:NOSTATUS +// The classic no-padding and no-bloat compiler C/C++ switch: +// /opt:nowin98 +// +// (C++ command line options: /GL /opt:nowin98 and /GA for .exe files) +// (Link command line options: /ignore:4078 /RELEASE /LTCG:NOSTATUS) +// +// Now, notes on using these options in VC7 vs VC6. +// VC6 consistently, for me, produces smaller code from C++ the exact same sources, +// with or without this header. On average, VC6 produces 5% smaller binaries compared +// to VC7 compiling the exact same project, *without* this header. With this header, VC6 +// will make a 13k file, while VC7 will make a 64k one. VC7 is just bloaty, pure and +// simple - all that managed/unmanaged C++ runtimes, and the CLR stuff must be getting +// in the way of code generation. However, template support is better, so there. +// Both VC6 and VC7 show the same end kind of end result savings - larger binary output +// will shave about 2% off, where as smaller projects (support DLL's, cpl's, +// activex controls, ATL libs, etc) get the best result, since the padding is usually +// more than the actual usable code. But again, VC7 does not compile down as small as VC6. +// +// The argument can be made that doing this is a waste of time, since the "zero bytes" +// will be compressed out in a zip file or install archive. Not really - it doesn't matter +// if the data is a string of zeroes or ones or 85858585 - it will still take room (20 bytes +// in a zip file, 29 bytes if only *4* of them 4k bytes are not the same) and time to +// compress that data and decompress it. Also, 20k of zeros is NOT 20k on disk - it's the +// size of the cluster slop- for Fat32 systems, 20k can be 32k, NTFS could make it 24k if you're +// just 1 byte over (round up). Most end users do not have the dual P4 Xeon systems with +// two gigs of RDram and a Raid 0+1 of Western Digital 120meg Special Editions that all +// worthy developers have (all six of us), so they will need any space and LOADING TIME +// savings they will need; taking an extra 32k or more out of your end user's 64megs of +// ram on Windows 98 is Not a Good Thing. +// +// Now, as a ADDED BONUS at NO EXTRA COST TO YOU! Under VC6, using the /merge:.text=.data +// pragma will cause the output file to be un-disassembleable! (is that a word?) At least, +// with the normal tools - WinDisam, DumpBin, and the like will not work. Try it - use the +// header, compile release, and then use DUMPBIN /DISASM filename.exe - no code! +// Thanks to Gлzim Pani for discovering this gem - for a full writeup on +// this issue and the ramifactions of it, visit www.nopcode.com for the Aggressive Optimize +// article. + +#ifndef _AGGRESSIVEOPTIMIZE_H_ +#define _AGGRESSIVEOPTIMIZE_H_ + +#pragma warning(disable:4711) + +#ifdef NDEBUG +// /Og (global optimizations), /Os (favor small code), /Oy (no frame pointers) +#pragma optimize("gsy",on) + +#if (_MSC_VER<1300) + #pragma comment(linker,"/RELEASE") +#endif + +// Note that merging the .rdata section will result in LARGER exe's if you using +// MFC (esp. static link). If this is desirable, define _MERGE_RDATA_ in your project. +#ifdef _MERGE_RDATA_ +#pragma comment(linker,"/merge:.rdata=.data") +#endif // _MERGE_RDATA_ + +#pragma comment(linker,"/merge:.text=.data") +#if (_MSC_VER<1300) + // In VC7, this causes problems with the relocation and data tables, so best to not merge them + #pragma comment(linker,"/merge:.reloc=.data") +#endif + +// Merging sections with different attributes causes a linker warning, so +// turn off the warning. From Michael Geary. Undocumented, as usual! +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/ignore:4078") +#endif + +// With Visual C++ 5, you already get the 512-byte alignment, so you will only need +// it for VC6, and maybe later. +#if _MSC_VER >= 1000 + +// Option #1: use /filealign +// Totally undocumented! And if you set it lower than 512 bytes, the program crashes. +// Either leave at 0x200 or 0x1000 +//#pragma comment(linker,"/FILEALIGN:0x200") + +// Option #2: use /opt:nowin98 +// See KB:Q235956 or the READMEVC.htm in your VC directory for info on this one. +// This is our currently preferred option, since it is fully documented and unlikely +// to break in service packs and updates. +#if (_MSC_VER<1300) + // In VC7, you will need to put this in your project settings + #pragma comment(linker,"/opt:nowin98") +#else + +// Option #3: use /align:4096 +// A side effect of using the default align value is that it turns on the above switch. +// Does nothing under Vc7 that /opt:nowin98 doesn't already give you +// #pragma comment(linker,"/ALIGN:512") +#endif + +#endif // _MSC_VER >= 1000 + +#endif // NDEBUG + +#endif // _AGGRESSIVEOPTIMIZE_H_ diff --git a/plugins/!NotAdopted/MessagePopup/MsgPopup.dsp b/plugins/!NotAdopted/MessagePopup/MsgPopup.dsp new file mode 100644 index 0000000000..9171ba6982 --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/MsgPopup.dsp @@ -0,0 +1,124 @@ +# Microsoft Developer Studio Project File - Name="MsgPopup" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=MsgPopup - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "MsgPopup.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "MsgPopup.mak" CFG="MsgPopup - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "MsgPopup - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "MsgPopup - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "MsgPopup - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MsgPopup_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W4 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MsgPopup_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "NDEBUG" +# ADD RSC /l 0x809 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# SUBTRACT LINK32 /map + +!ELSEIF "$(CFG)" == "MsgPopup - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MsgPopup_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MsgPopup_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\PROGRA~1\MIRAND~2\PLUGINS\MsgPopup.DLL" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "MsgPopup - Win32 Release" +# Name "MsgPopup - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\main.cpp +# End Source File +# Begin Source File + +SOURCE=.\options.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\options.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\MsgPopup.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/plugins/!NotAdopted/MessagePopup/MsgPopup.dsw b/plugins/!NotAdopted/MessagePopup/MsgPopup.dsw new file mode 100644 index 0000000000..e18e716489 --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/MsgPopup.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "MsgPopup"=".\MsgPopup.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/plugins/!NotAdopted/MessagePopup/MsgPopup.rc b/plugins/!NotAdopted/MessagePopup/MsgPopup.rc new file mode 100644 index 0000000000..e9e1ca93bd --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/MsgPopup.rc @@ -0,0 +1,134 @@ +//Microsoft Developer Studio generated resource script. +// +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "resource.h" +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Russian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +#ifdef _WIN32 +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPTIONS DIALOGEX 0, 0, 295, 181 +STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg" +BEGIN + CONTROL "",IDC_ASTERISK_FG,"ColourPicker",WS_GROUP | WS_TABSTOP, + 56,16,39,12,WS_EX_NOPARENTNOTIFY + GROUPBOX "ASTERISK style",IDC_STATIC,0,1,295,37 + LTEXT "Background",IDC_STATIC,113,18,40,8 + LTEXT "Foreground",IDC_STATIC,8,18,37,8 + CONTROL "",IDC_ASTERISK_BG,"ColourPicker",WS_GROUP | WS_TABSTOP, + 161,16,39,12,WS_EX_NOPARENTNOTIFY + CONTROL "",IDC_ERROR_FG,"ColourPicker",WS_GROUP | WS_TABSTOP,56, + 56,39,12,WS_EX_NOPARENTNOTIFY + GROUPBOX "ERROR style",IDC_STATIC,0,41,295,37 + LTEXT "Background",IDC_STATIC,113,58,40,8 + LTEXT "Foreground",IDC_STATIC,8,58,37,8 + CONTROL "",IDC_ERROR_BG,"ColourPicker",WS_GROUP | WS_TABSTOP,161, + 56,39,12,WS_EX_NOPARENTNOTIFY + CONTROL "",IDC_EXCLAMATION_FG,"ColourPicker",WS_GROUP | + WS_TABSTOP,56,96,39,12,WS_EX_NOPARENTNOTIFY + GROUPBOX "EXCLAMATION style",IDC_STATIC,0,81,295,37 + LTEXT "Background",IDC_STATIC,113,98,40,8 + LTEXT "Foreground",IDC_STATIC,8,98,37,8 + CONTROL "",IDC_EXCLAMATION_BG,"ColourPicker",WS_GROUP | + WS_TABSTOP,161,96,39,12,WS_EX_NOPARENTNOTIFY + CONTROL "",IDC_QUESTION_FG,"ColourPicker",WS_GROUP | WS_TABSTOP, + 56,136,39,12,WS_EX_NOPARENTNOTIFY + GROUPBOX "QUESTION style",IDC_STATIC,0,121,295,37 + LTEXT "Background",IDC_STATIC,113,138,40,8 + LTEXT "Foreground",IDC_STATIC,8,138,37,8 + CONTROL "",IDC_QUESTION_BG,"ColourPicker",WS_GROUP | WS_TABSTOP, + 161,136,39,12,WS_EX_NOPARENTNOTIFY + PUSHBUTTON "Preview",IDC_PREVIEW,234,162,50,14 + LTEXT "Timeout",IDC_STATIC,213,18,26,8 + EDITTEXT IDC_TIMEOUT1,245,15,40,14,ES_AUTOHSCROLL + LTEXT "Special values of the ""Timeout"":\n -1 - infinity, 0 - use default timeout value", + IDC_STATIC,17,160,137,18 + LTEXT "Timeout",IDC_STATIC,213,58,26,8 + EDITTEXT IDC_TIMEOUT2,245,55,40,14,ES_AUTOHSCROLL + LTEXT "Timeout",IDC_STATIC,213,98,26,8 + EDITTEXT IDC_TIMEOUT3,245,95,40,14,ES_AUTOHSCROLL + LTEXT "Timeout",IDC_STATIC,213,138,26,8 + EDITTEXT IDC_TIMEOUT4,245,135,40,14,ES_AUTOHSCROLL + CONTROL "Emit a sound",IDC_MESSAGEBEEP,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,167,164,57,10 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resrc1.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""resource.h""\r\n" + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_OPTIONS, DIALOG + BEGIN + RIGHTMARGIN, 222 + BOTTOMMARGIN, 179 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Russian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/!NotAdopted/MessagePopup/MsgPopup.txt b/plugins/!NotAdopted/MessagePopup/MsgPopup.txt new file mode 100644 index 0000000000..5b99aed133 --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/MsgPopup.txt @@ -0,0 +1,63 @@ +"MessageBox -> Popup" plugin +========================== + +MsgBox.dll +version 0.0.0.1 +by StDenis, ICQ#337380210 + +Miranda 0.3.3+ recommended + +License info +------------ +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. + +Description +----------- + +I dunno how MessageBoxes act on you, but I'm tired of them. +So I make a plugin which replace MessageBoxes with single OK button +into popups. + +*** CAUTION! *** +This plugin use non-ordinary technique - intercepting of API functions. +Author made all his best to provide compatibility and stability, but as usual: + +THIS STUFF PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +Known bugs & limitations & ToDo's: +---------------------------------- + - There's no chance to test this plugin under consumer's version of Windows + (Win9x, WinME) carefully. It was tested on only one PC, which may didn't + reflect all specificity of these versions of OS. + +Thanx to: +--------- + I'm glad to say thanks to HeikoH. Who helps me to test this plugin and + provide compatibility with consumer's Windoze. + +Changelog +--------- ++ - Added, +- - Fixed, +* - Changed. + +Version 0.0.0.1 +--------------- + + Initial release. diff --git a/plugins/!NotAdopted/MessagePopup/common.h b/plugins/!NotAdopted/MessagePopup/common.h new file mode 100644 index 0000000000..2af3d9d964 --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/common.h @@ -0,0 +1,63 @@ +/* + +MessagePopup - replacer of MessageBox'es + +Copyright 2004 Denis Stanishevskiy + +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"AggressiveOptimize.h" +#include + +#include "../../SDK/headers_c/newpluginapi.h" + +#include "../../SDK/headers_c/m_system.h" +#include "../../SDK/headers_c/m_database.h" +#include "../../SDK/headers_c/m_langpack.h" +#include "../../SDK/headers_c/m_clist.h" +#include "../../SDK/headers_c/m_options.h" +#include "../../SDK/headers_c/m_utils.h" +#include "../../SDK/headers_c/m_popup.h" + +#include "options.h" +#include "resource.h" + +#define SERVICENAME "MessagePopup" + +struct MSGBOXOPTIONS +{ + COLORREF FG[4]; + COLORREF BG[4]; + int Timeout[4]; + BOOL Sound; +}; + +extern MSGBOXOPTIONS options; +extern MSGBOXOPTIONS optionsDefault; + +void LoadConfig(); + +#ifdef __cplusplus +extern "C" { +#endif + +int __declspec(dllexport) Load( PLUGINLINK *link ); +int __declspec(dllexport) Unload( void ); +__declspec(dllexport) PLUGININFO *MirandaPluginInfo( DWORD dwVersion ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/plugins/!NotAdopted/MessagePopup/main.cpp b/plugins/!NotAdopted/MessagePopup/main.cpp new file mode 100644 index 0000000000..aab581b57b --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/main.cpp @@ -0,0 +1,272 @@ +/* + +MessagePopup - replacer of MessageBox'es + +Copyright 2004 Denis Stanishevskiy + +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 "common.h" +#include +#include +#pragma comment(lib, "dbghelp.lib") + +HINSTANCE hInst; +PLUGINLINK *pluginLink; + +HANDLE hHookedOpt; +HANDLE hHookedInit; + +MSGBOXOPTIONS optionsDefault = +{ + {0, 0xFFFFFF, 0, 0}, + {0xBFFFFF, 0x0000FF, 0xB0B0FF, 0xECFF93}, + {-1,-1,-1,-1}, + TRUE +}; +MSGBOXOPTIONS options; + +PLUGININFO pluginInfo={ + sizeof( PLUGININFO ), + SERVICENAME, + PLUGIN_MAKE_VERSION( 0,0,0,1 ), + "This stuff will replace MessageBox'es [whose have only OK button] into Popups", + "Denis Stanishevskiy // StDenis", + "stdenformiranda(at)fromru(dot)com", + "Copyright (c) 2004, Denis Stanishevskiy", + "", + 0, 0 +}; + +typedef int (WINAPI *MSGBOXPROC)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); + +MSGBOXPROC prevMessageBoxA; + +#define OIC_HAND 32513 +#define OIC_QUES 32514 +#define OIC_BANG 32515 +#define OIC_NOTE 32516 + +void popupMessage(LPCSTR lpText, LPCSTR lpCaption, UINT uType) +{ + POPUPDATAEX ppd; + int iIcon; + int indx; + + ZeroMemory(&ppd, sizeof(ppd)); + + switch(uType & 0xF0) + { + case MB_ICONHAND: + indx = 1; + iIcon = OIC_HAND; + break; + case MB_ICONEXCLAMATION: + indx = 2; + iIcon = OIC_BANG; + break; + case MB_ICONQUESTION: + indx = 3; + iIcon = OIC_QUES; + break; + default: + indx = 0; + iIcon = OIC_NOTE; + break; + + } + ppd.colorBack = options.BG[indx]; + ppd.colorText = options.FG[indx]; + ppd.iSeconds = options.Timeout[indx]; + + ppd.lchIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(iIcon), IMAGE_ICON, SM_CXSMICON, SM_CYSMICON, LR_SHARED); + lstrcpy(ppd.lpzContactName, lpCaption); + lstrcpy(ppd.lpzText, lpText); + CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0); + if(options.Sound) + MessageBeep(uType); +} + +int WINAPI newMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) +{ + if(CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0) == CALLSERVICE_NOTFOUND || (uType & 0x0F)) + return prevMessageBoxA(hWnd, lpText, lpCaption, uType); + + popupMessage(lpText, lpCaption,uType); + return IDOK; +} + +BOOL g_HookError = FALSE; +BOOL g_HookError2 = FALSE; +int g_mod = 0; +void HookOnImport(HMODULE hModule, char *lpszImpModName, DWORD lpOrigFunc, DWORD lpNewFunc) +{ + ULONG ulSize; + PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData( + hModule, + TRUE, + IMAGE_DIRECTORY_ENTRY_IMPORT, + &ulSize); + if(pImportDesc == NULL) return; + + for(; pImportDesc->Name; pImportDesc++) + { + char *pszModName = (char *)((PBYTE)hModule + pImportDesc->Name); + + if (lstrcmpiA(lpszImpModName, pszModName) == 0) + { + PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hModule + pImportDesc->FirstThunk); + + for (; pThunk->u1.Function; pThunk++) + { + DWORD* ppfn = (DWORD*) &pThunk->u1.Function; + + if(*ppfn == lpOrigFunc) + { + DWORD oldProtect; + + g_mod++; + + if(!VirtualProtect((LPVOID)ppfn, 4, PAGE_EXECUTE_READWRITE, &oldProtect)) + { + if(!g_HookError) + { + char buf[200]; + + g_HookError = TRUE; + wsprintf(buf, "VirtualProtect failed. Code %d\n" + "Try to call the author", GetLastError()); + prevMessageBoxA(0, buf, "MsgBox", MB_OK); + } + } + *(DWORD*)ppfn = lpNewFunc; + if(*(DWORD*)ppfn != lpNewFunc) + { + if(!g_HookError2) + { + g_HookError2 = TRUE; + prevMessageBoxA(0, "Hmm. Something goes wrong. I can't write into the memory.\n" + "And as u can c, there are no any exception raised..\n" + "Try to call the author", "MsgBox", MB_OK); + } + } + } + } + } + } +} + +void HookAPI() +{ + DWORD lpMessageBox = (DWORD)GetProcAddress(GetModuleHandle("USER32.DLL"), "MessageBoxA"); + DWORD lpPopupMsgBox = (DWORD)newMessageBoxA; + + prevMessageBoxA = (MSGBOXPROC)lpMessageBox; + + BOOL bFound = FALSE; + HANDLE hModuleSnap = NULL; + MODULEENTRY32 me32 = {0}; + + hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId()); + if(hModuleSnap == INVALID_HANDLE_VALUE) + return; + + me32.dwSize = sizeof(MODULEENTRY32); + if(Module32First(hModuleSnap, &me32)) + { + do + { + HookOnImport(me32.hModule, "USER32.DLL", lpMessageBox, lpPopupMsgBox); + } + while (!bFound && Module32Next(hModuleSnap, &me32)); + } + CloseHandle (hModuleSnap); + + return; +} + +int HookedInit(WPARAM wParam, LPARAM lParam) +{ + HookAPI(); + + return 0; +} + +int HookedOptions(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCE(IDD_OPTIONS); + odp.pszTitle = Translate("MessagePopup"); + odp.pszGroup = Translate("Popups"); + odp.flags = ODPF_BOLDGROUPS; + odp.pfnDlgProc = OptionsDlgProc; + CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp); + + return 0; +} + +void LoadConfig() +{ + char *szNameFG = "FGx"; + char *szNameBG = "BGx"; + char *szNameTO = "TOx"; + int indx; + + for(indx = 0; indx < 4; indx++) + { + szNameFG[2] = szNameBG[2] = szNameTO[2] = (char)(indx + '0'); + options.FG[indx] = DBGetContactSettingDword(NULL, SERVICENAME, szNameFG, optionsDefault.FG[indx]); + options.BG[indx] = DBGetContactSettingDword(NULL, SERVICENAME, szNameBG, optionsDefault.BG[indx]); + options.Timeout[indx] = DBGetContactSettingDword(NULL, SERVICENAME, szNameTO, (DWORD)optionsDefault.Timeout[indx]); + } + options.Sound = DBGetContactSettingByte(NULL, SERVICENAME, "Sound", (DWORD)optionsDefault.Sound); + +} +int __declspec(dllexport) Load(PLUGINLINK *link) +{ + pluginLink=link; + + hHookedInit = HookEvent(ME_SYSTEM_MODULESLOADED, HookedInit); + hHookedOpt = HookEvent(ME_OPT_INITIALISE, HookedOptions); + + LoadConfig(); + + return 0; +} + +int __declspec(dllexport) Unload(void) +{ + UnhookEvent(hHookedOpt); + UnhookEvent(hHookedInit); + + return 0; +} + +__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} diff --git a/plugins/!NotAdopted/MessagePopup/options.cpp b/plugins/!NotAdopted/MessagePopup/options.cpp new file mode 100644 index 0000000000..28a7e8fd44 --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/options.cpp @@ -0,0 +1,131 @@ +/* + +MessagePopup - replacer of MessageBox'es + +Copyright 2004 Denis Stanishevskiy + +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 "common.h" + +int idOptionControls[4][3] = { + IDC_ASTERISK_FG,IDC_ASTERISK_BG,IDC_TIMEOUT1, + IDC_ERROR_FG,IDC_ERROR_BG,IDC_TIMEOUT2, + IDC_EXCLAMATION_FG,IDC_EXCLAMATION_BG,IDC_TIMEOUT3, + IDC_QUESTION_FG,IDC_QUESTION_BG,IDC_TIMEOUT4 +}; + +static int __inline DBWriteContactSettingDwordDef(HANDLE hContact,const char *szModule,const char *szSetting,DWORD val, DWORD defValue) +{ + if(val == DBGetContactSettingDword(hContact, szModule, szSetting, defValue)) + return 0; + else + return DBWriteContactSettingDword(hContact, szModule, szSetting, val); +} + +BOOL CALLBACK OptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + int indx; + + TranslateDialogDefault(hWnd); + for(indx = 0; indx < 4; indx++) + { + SendDlgItemMessage(hWnd, idOptionControls[indx][0], CPM_SETCOLOUR, 0, options.FG[indx]); + SendDlgItemMessage(hWnd, idOptionControls[indx][1], CPM_SETCOLOUR, 0, options.BG[indx]); + SetDlgItemInt(hWnd, idOptionControls[indx][2], options.Timeout[indx], TRUE); + } + CheckDlgButton(hWnd, IDC_MESSAGEBEEP, options.Sound?BST_CHECKED:BST_UNCHECKED); + return TRUE; + } + case WM_COMMAND: + { + int indx, value; + BOOL Translated; + if(LOWORD(wParam) == IDC_PREVIEW) + { + MessageBoxA(0, Translate("Message with question"), Translate(SERVICENAME " - demo"), MB_ICONQUESTION); + MessageBoxA(0, Translate("Message with exclamation"), Translate(SERVICENAME " - demo"), MB_ICONEXCLAMATION); + MessageBoxA(0, Translate("Message with error"), Translate(SERVICENAME " - demo"), MB_ICONSTOP); + MessageBoxA(0, Translate("Message with asterisk"), Translate(SERVICENAME " - demo"), MB_ICONASTERISK); + + return FALSE; + } + if(LOWORD(wParam) == IDC_MESSAGEBEEP) + { + options.Sound = IsDlgButtonChecked(hWnd, IDC_MESSAGEBEEP) == BST_CHECKED; + } + else + for(indx = 0; indx < 4; indx++) + { + if(LOWORD(wParam) == idOptionControls[indx][0]) + { + if(HIWORD(wParam) != CPN_COLOURCHANGED) return FALSE; + options.FG[indx] = SendDlgItemMessage(hWnd, LOWORD(wParam), CPM_GETCOLOUR, 0, 0); + } + else + if(LOWORD(wParam) == idOptionControls[indx][1]) + { + if(HIWORD(wParam) != CPN_COLOURCHANGED) return FALSE; + options.BG[indx] = SendDlgItemMessage(hWnd, LOWORD(wParam), CPM_GETCOLOUR, 0, 0); + } + else + if(LOWORD(wParam) == idOptionControls[indx][2]) + { + if(HIWORD(wParam) != EN_CHANGE) return FALSE; + if((HWND)lParam != GetFocus()) return FALSE; + + value = (DWORD)GetDlgItemInt(hWnd, LOWORD(wParam), &Translated, TRUE); + if(Translated) options.Timeout[indx] = value; + } + } + SendMessage(GetParent(hWnd), PSM_CHANGED, 0,0); + break; + } + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) + { + case PSN_RESET: + LoadConfig(); + return FALSE; + + case PSN_APPLY: + { + char *szNameFG = "FGx"; + char *szNameBG = "BGx"; + char *szNameTO = "TOx"; + int indx; + + for(indx = 0; indx < 4; indx++) + { + szNameFG[2] = szNameBG[2] = szNameTO[2] = (char)(indx + '0'); + + DBWriteContactSettingDwordDef(NULL, SERVICENAME, szNameFG, options.FG[indx], optionsDefault.FG[indx]); + DBWriteContactSettingDwordDef(NULL, SERVICENAME, szNameBG, options.BG[indx], optionsDefault.BG[indx]); + DBWriteContactSettingDwordDef(NULL, SERVICENAME, szNameTO, options.Timeout[indx], (DWORD)optionsDefault.Timeout[indx]); + } + DBWriteContactSettingDwordDef(NULL,SERVICENAME,"Sound",options.Sound,optionsDefault.Sound); + + break; + } + } + break; + } + return FALSE; +} diff --git a/plugins/!NotAdopted/MessagePopup/options.h b/plugins/!NotAdopted/MessagePopup/options.h new file mode 100644 index 0000000000..4d139d814f --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/options.h @@ -0,0 +1,22 @@ +/* + +MessagePopup - replacer of MessageBox'es + +Copyright 2004 Denis Stanishevskiy + +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. + +*/ +BOOL CALLBACK OptionsDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); diff --git a/plugins/!NotAdopted/MessagePopup/resource.h b/plugins/!NotAdopted/MessagePopup/resource.h new file mode 100644 index 0000000000..27e128723b --- /dev/null +++ b/plugins/!NotAdopted/MessagePopup/resource.h @@ -0,0 +1,34 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by MsgBox.rc +// +#define IDD_OPTIONS 101 + +#define IDC_ASTERISK_BG 101 +#define IDC_ERROR_FG 102 +#define IDC_ERROR_BG 103 +#define IDC_EXCLAMATION_FG 104 +#define IDC_EXCLAMATION_BG 105 +#define IDC_QUESTION_FG 106 +#define IDC_QUESTION_BG 107 +#define IDC_ASTERISK_FG 108 +#define IDC_PREVIEW 109 + +#define IDC_TIMEOUT1 1000 +#define IDC_TIMEOUT2 1001 +#define IDC_TIMEOUT3 1002 +#define IDC_TIMEOUT4 1003 + +#define IDC_MESSAGEBEEP 1004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 135 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/!NotAdopted/WinPopup/add_dialog.cpp b/plugins/!NotAdopted/WinPopup/add_dialog.cpp new file mode 100644 index 0000000000..3312c73385 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/add_dialog.cpp @@ -0,0 +1,74 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "add_dialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static INT_PTR CALLBACK DlgProcAddContact(HWND hwndDlg, UINT Msg, + WPARAM wParam, LPARAM /*lParam*/) +{ + switch ( Msg ) + { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + return TRUE; + + case WM_COMMAND: + switch ( LOWORD( wParam ) ) + { + case IDOK: + { + bool bGroup = IsDlgButtonChecked( hwndDlg, IDC_GROUP ) == BST_CHECKED; + CString sName; + GetDlgItemText( hwndDlg, IDC_NAME, sName.GetBuffer( 128 ), 127 ); + sName.ReleaseBuffer(); + sName.Trim(); + if ( ! sName.IsEmpty() ) + { + HCURSOR hCurrent = SetCursor( LoadCursor( NULL, IDC_WAIT ) ); + HANDLE hContact = AddToListByName( sName, 0, NULL, true, bGroup ); + SetCursor( hCurrent ); + if ( hContact ) + EndDialog( hwndDlg, IDOK ); + } + } + return TRUE; + + case IDCANCEL: + EndDialog( hwndDlg, IDCANCEL ); + return TRUE; + } + break; + } + return FALSE; +} + +void AddDialog(HWND hParentWnd) +{ + DialogBox( pluginModule, MAKEINTRESOURCE( IDD_ADD ), hParentWnd, DlgProcAddContact ); +} diff --git a/plugins/!NotAdopted/WinPopup/add_dialog.h b/plugins/!NotAdopted/WinPopup/add_dialog.h new file mode 100644 index 0000000000..16f0245eb8 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/add_dialog.h @@ -0,0 +1,25 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2009 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +// Показывает диалог для ручного добавления контакта по имени/адресу +void AddDialog(HWND hParentWnd); diff --git a/plugins/!NotAdopted/WinPopup/chat.cpp b/plugins/!NotAdopted/WinPopup/chat.cpp new file mode 100644 index 0000000000..4572bb10ac --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/chat.cpp @@ -0,0 +1,337 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2008-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "chat.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#ifdef CHAT_ENABLED + +HANDLE plugin_CHAT_EVENT = NULL; + +static int __cdecl CHAT_EVENT(WPARAM /* wParam */, LPARAM lParam) +{ + GCHOOK* pgch = (GCHOOK*)lParam; + switch ( pgch->pDest->iType ) + { + case GC_USER_MESSAGE: + { + // Дублирование в чат + ChatMessage( pgch->pDest->ptszID, pgch->ptszText ); + + // Отправка сообщения + DWORD dwLastError = 0; + SendMessage( pgch->pDest->ptszID, pgch->ptszText, dwLastError ); + } + break; + } + + return 0; +} + +bool ChatRegister() +{ + GCREGISTER gcr = + { + sizeof( GCREGISTER ), + 0, + modname, + modname, + 0, + 0, + NULL + }; + int result = CallServiceSync( MS_GC_REGISTER, 0, (LPARAM)&gcr ); + if ( result != 0 ) + return false; + + _ASSERT (plugin_CHAT_EVENT == NULL); + plugin_CHAT_EVENT = HookEvent (ME_GC_EVENT, CHAT_EVENT); + _ASSERT (plugin_CHAT_EVENT != NULL); + + return true; +} + +void ChatUnregister() +{ + if (plugin_CHAT_EVENT) + { + UnhookEvent (plugin_CHAT_EVENT); + plugin_CHAT_EVENT = NULL; + } +} + +bool ChatNewSession(LPCTSTR szSession) +{ + GCSESSION gcr = + { + sizeof( GCSESSION ), + GCW_CHATROOM, + modname, + (LPCSTR)szSession, + (LPCSTR)szSession, + NULL, + 0, + 0 + }; + return ( CallServiceSync( MS_GC_NEWSESSION, 0, (LPARAM)&gcr ) == 0 ); +} + +bool ChatAddGroup(LPCTSTR szSession, LPCTSTR szGroup) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_ADDGROUP + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + (LPCSTR)szGroup, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatJoinMe(LPCTSTR szSession, LPCTSTR szGroup) +{ + CString sMe; + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + sMe = sMyNick; + else + sMe = pluginMachineName; + + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_JOIN + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)szGroup, + NULL, + TRUE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatJoinUser(LPCTSTR szSession, LPCTSTR szUser, LPCTSTR szGroup) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_JOIN + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + (LPCSTR)szUser, + (LPCSTR)szUser, + (LPCSTR)szGroup, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatInitDone(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce ) == 0 ); +} + +bool ChatOnline(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce ) == 0 ); +} + +bool ChatOffline(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce ) == 0 ); +} + +bool ChatMessage(LPCTSTR szSession, LPCTSTR szFrom, LPCTSTR szMessage) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_MESSAGE + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + (LPCSTR)szMessage, + (LPCSTR)szFrom, + (LPCSTR)szFrom, + NULL, + NULL, + FALSE, + 0, + 0, + time() + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatMessage(LPCTSTR szSession, LPCTSTR szMessage) +{ + CString sMe; + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + sMe = sMyNick; + else + sMe = pluginMachineName; + + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_MESSAGE + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + (LPCSTR)szMessage, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)(LPCTSTR)sMe, + NULL, + NULL, + TRUE, + 0, + 0, + time() + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +CString GetChatSession(HANDLE hContact) +{ + CString sContact; + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( hContact, modname, "ChatRoomID", &dbv ) ) + { + sContact = dbv.pszVal; + DBFreeVariant( &dbv ); + } + return sContact; +} + +bool IsChatRoom(HANDLE hContact) +{ + return ( DBGetContactSettingByte( hContact, modname, "ChatRoom", 0 ) != 0 ); +} + +#endif // CHAT_ENABLED diff --git a/plugins/!NotAdopted/WinPopup/chat.h b/plugins/!NotAdopted/WinPopup/chat.h new file mode 100644 index 0000000000..6351ea3042 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/chat.h @@ -0,0 +1,44 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2008-2009 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +#ifdef CHAT_ENABLED + +bool ChatRegister(); +void ChatUnregister(); +bool ChatNewSession(LPCTSTR szSession); +bool ChatAddGroup(LPCTSTR szSession, LPCTSTR szGroup); +bool ChatJoinMe(LPCTSTR szSession, LPCTSTR szGroup); +bool ChatJoinUser(LPCTSTR szSession, LPCTSTR szUser, LPCTSTR szGroup); +bool ChatInitDone(LPCTSTR szSession); +bool ChatOnline(LPCTSTR szSession); +bool ChatOffline(LPCTSTR szSession); +bool ChatMessage(LPCTSTR szSession, LPCTSTR szFrom, LPCTSTR szMessage); +bool ChatMessage(LPCTSTR szSession, LPCTSTR szMessage); + +// Получение идентификатора чата (обычно имя рабочей группы) +CString GetChatSession(HANDLE hContact); + +// Проверка что контакт - это чат +bool IsChatRoom(HANDLE hContact); + +#endif // CHAT_ENABLED diff --git a/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h b/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h new file mode 100644 index 0000000000..218a5a114c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h @@ -0,0 +1,338 @@ +/* + * This software is the original work of DKLT. + * Copyright (c) 2002 DKLT. All rights reserved. + * email: dtung@eng.monash.edu.au + * + */ +/* + * Permission to make digital or hard copies of all or part of this work for personal + * or classroom use is granted without fee provided that copies are not distributed + * for profit or commercial advantage. + */ + +#ifndef LOADDLL_H +#define LOADDLL_H + +/// proof of concept code follows +/////// +/////// class DllLoader and class DllFunctor<...> +/////// +/////// Two classes are designed to provide the functionality to load a function, +/////// using the "function name" as an identifier, from a Win32 .dll file. +/////// Sample code are attached at the end of this file. +/////// +/////// -04Oct2003 11.52pm +/////// reworked article and sample code to be posted on codeproject.com +/////// better defined behaviours with refined logics idealistic goals yet to be completed +/////// +/////// -29Mar2003 1.47pm +/////// Polishing code for public release. minimizing code size, removing redundent +/////// comments, eliminating deprecated funcs. +/////// +/////// -29Mar2003 12.47am +/////// Revising the src tree. Using redundent code to achieve src level compatibility +/////// (ie: same set of calls for both funcs attached with apps or reside in dlls) +/////// +/////// -12Nov2002 1.35am +/////// My first attempt to tidy the code for another public release. +/////// +/////// -14Oct2002 1.40am +/////// created and tested briefly inside \DKLT TestApp\ +/////// +/////// +/////// + +//template + +/// +/// No error message for you +/// +#ifndef ERRORMSG +#define DEBUGMSG(aMesg) ; +#define ERRORMSG(aMesg) ; +#endif + +/// +/// protos +/// +class DllLoader; +template class DllFunctor; + + +/* +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For Current release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// + /// u can load a dll function in two differnt ways + /// + DllLoader dll("testDll.dll", false); + DllFunctor fAdd("Add"); + fAdd.SetDll(dll); + + int b; + b = fSub()(b,1); // with delay load, but not src level compatible + + OR + + + DllLoader dll("testDll.dll"); + FuncPtrType( int(*)(int,int) ) Add; + dll.LoadFunc(Add,"Add"); + int a=90; + a = Add(a,1); // src level compatible, but no delay load + + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For previous release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // + // sample code for demonstrating class DllLoader {...}; and DllFunctor<...> {...}; + // + FuncPtrType( int(*)(int) ) a; // define a new variable "a" of type "int(*)(int)" + + DllLoader Dlldshow("dlls.dll"); // expect a dll name "dlls.dll" + Dllshow.LoadFunc( a, "test"); // load func named "test" from dll file + int i =a(10); + +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For initial release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + This version enables a delay-load behaviour. Note the double ()() call on last line. + + // + // sample code for demonstrating class DllLoader {...}; and DllFunctor<...> {...}; + // + + DllLoader Dlldshow("dlls.dll"); + DllFunctor update("UpdatePoint"); + + Dlldshow.find(update); + + update() (&pt); + + +*/ + +/* + A little comment here + + My previous attempts to use operator()(...) and operator FuncPtrType () with MSVC + failed, where FuncPtrType is a function pointer typedef. That technique, enables + more control over a functor object. ie: can implement delay load among many exciting + features. That technique, however, works with g++ line of compilers. + + This current implementation is design for use with MSVC line of compilers only. + + It seems, from the MSVC compiler error message, that "operator FuncPtrType ()" is + never a candidate function, not to mention viability. I guess this is how they + design and implemented MSVC6. ".net" version doesnt "evaluate" + "operator FuncPtrType()" properly as well. + + - DKLT March 2003 +*/ + + +////// +//////++++++++++++++++++++++++++++++++++++++++++++++++++ +////// This marco is for performing the following task... GoodJob! creative man!! +//////++++++++++++++++++++++++++++++++++++++++++++++++++ +////// normally, u define a function pointer variable this way +////// +////// int (*c) (int) = test; // c pointing to "int test(int) {...}" +////// +////// This marco enables u define a function pointer this way +////// +////// FuncPtrType( int(*)(int) ) c =test; +////// +////// +////// took me a while to come up with this one. +////// +////// - DKLT 2003 March + +template +struct TypeOnlyStruct { +typedef FuncTypeTTT FuncType; +}; + +#define FuncPtrType(funcType) \ + TypeOnlyStruct::FuncType + +////// +////// potential problems +////// - an instantiation for every differnt type on the template class +////// thus bloated executable? need to fully test it out. not sure about +////// behaviour at this stage. +////// - DKLT March 2003 + + +////// +////// class DllLoader {...} +////// -init a dll file with LoadLibrary() so that its mapped into dll memory +////// space. this class is designed to use with class DllFunctor<...>. +////// +////// +///////////////////////////////////////////////////////// +class DllLoader +{ +///////////////////////////////////////////////////////// + +private: + TCHAR dllName[ MAX_PATH ]; + +public: + HINSTANCE dll; + + DllLoader (LPCTSTR n, bool loadNow = true) : + dll(0) + { + lstrcpy( dllName, n ); + if (loadNow) + LoadLibrary(); + } + ~DllLoader () + { + FreeLibrary(); + } + + // test to see if dll is loaded already + operator bool () const + { + return (dll != 0); + } + +// FuncTypePtr(int(*)(int)) a; +// Dllshow.LoadFunc( a, "test") ; +// int i =a(10); + + /// This is my latest implementation + ///---------------------------------------------------------- + /// public: + /// template + /// DllLoader::LoadFunc(FuncTTT& c, string fNameStr) + ///---------------------------------------------------------- + /// This function loads a function named "fNameStr" from a DllLoader object + /// and put the address of that function into c. + /// + /// - template type is derived(deduced) from 1st param. + /// + ///note: bloated executable is possible + template + //-------------------------- + FuncTTT LoadFunc(FuncTTT& c, LPCSTR fNameStr) { + //-------------------------- + FuncTTT fPtr; + + // existing lib loaded? + if (!dll) + if (!this->LoadLibrary()) + return (FuncTTT) NULL; + + // load func from dll + fPtr =(FuncTTT)GetProcAddress ( + dll, // handle to DLL module + fNameStr // name of function + ); + if (!fPtr) { + /// return a pointer to a base generic function would be good. ie: ERROR prompt + return (FuncTTT) NULL; + } + c = fPtr; + return fPtr; + } + +public: + /// + /// decrement dll ref count via win32 ::FreeLibrary(...) + /// + //-------------------------- + void FreeLibrary() { + //-------------------------- + if (dll) { + ::FreeLibrary(dll); + dll=0; + } + } + +public: + /// + /// find the dll file and attempt to load it + /// + //------------------------ + bool LoadLibrary (HINSTANCE hInstance = NULL) { + //------------------------ + + // existing lib loaded? + if (dll !=0 ) + this->FreeLibrary(); + + // load from: + // 1. The directory from which the application loaded. + // 2. The current directory. + // 3. The Windows system directory. + // 4. The Windows directory. + // 5. The directories that are listed in the PATH environment variable. + dll = ::LoadLibrary( dllName ); + if ( ! dll ) + { + // 6. The module directory (if dll). + if ( hInstance ) + { + TCHAR self[ MAX_PATH ]; + GetModuleFileName( hInstance, self, MAX_PATH ); + lstrcpy( lstrnrchr( self, _T('\\'), lstrlen( self )) + 1, dllName ); + dll = ::LoadLibrary( self ); + } + if ( ! dll ) + { + return false; + } + } + return true; + } + + ////// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ////// All class functions below are for backward compatibility.... + ////// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ////// U may delete all of them if u dont need them + ////// + /// + /// find() is deprecated. Do not use it anymore. + /// locate the functor inside a dll. let a DllFunctor object to do the job + /// instead... double dispatch?? + /// +public:template + bool find(DllFunctor& functor) { + return functor.LoadFromDll(this); + } + +}; + +/// +/// DllFunctor<> is templated on the function type +/// +template +class DllFunctor { + FuncPtrType fp; // pointer to dll function + DllLoader* dll; // which dllLoader to load from + CString fname; // name of function as char array + +public: + DllFunctor(FuncPtrType f, DllLoader* d=0): fp(f), dll(d) {;} + DllFunctor(LPCTSTR n): fname(n),fp(0), dll(0) {;} + FuncPtrType operator()() { + if (!*dll) { + if (!dll->LoadLibrary()) + return (FuncPtrType) NULL; + } + if (fp == 0) { + dll->LoadFunc (fp, fname.c_str()); + } + return fp; + } + void SetDll(DllLoader& d) { dll=&d; } +}; + +#endif diff --git a/plugins/!NotAdopted/WinPopup/icons/add.ico b/plugins/!NotAdopted/WinPopup/icons/add.ico new file mode 100644 index 0000000000..2b407bd899 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/add.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/away.ico b/plugins/!NotAdopted/WinPopup/icons/away.ico new file mode 100644 index 0000000000..fd4fc06d27 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/bad_name.ico b/plugins/!NotAdopted/WinPopup/icons/bad_name.ico new file mode 100644 index 0000000000..d90e82cf30 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/bad_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/bad_names.ico b/plugins/!NotAdopted/WinPopup/icons/bad_names.ico new file mode 100644 index 0000000000..939dcffcb1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/bad_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/computer.ico b/plugins/!NotAdopted/WinPopup/icons/computer.ico new file mode 100644 index 0000000000..70e0c09112 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/computer.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/computer_error.ico b/plugins/!NotAdopted/WinPopup/icons/computer_error.ico new file mode 100644 index 0000000000..380ed3d9f1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/computer_error.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/dnd.ico b/plugins/!NotAdopted/WinPopup/icons/dnd.ico new file mode 100644 index 0000000000..3cc44e4a98 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/explore.ico b/plugins/!NotAdopted/WinPopup/icons/explore.ico new file mode 100644 index 0000000000..0e26c97f10 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/explore.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/freechat.ico b/plugins/!NotAdopted/WinPopup/icons/freechat.ico new file mode 100644 index 0000000000..730bbe436a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/good_name.ico b/plugins/!NotAdopted/WinPopup/icons/good_name.ico new file mode 100644 index 0000000000..86aaef9d46 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/good_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/good_names.ico b/plugins/!NotAdopted/WinPopup/icons/good_names.ico new file mode 100644 index 0000000000..37fc97841f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/good_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/invisible.ico b/plugins/!NotAdopted/WinPopup/icons/invisible.ico new file mode 100644 index 0000000000..2c5378e70c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/lana.ico b/plugins/!NotAdopted/WinPopup/icons/lana.ico new file mode 100644 index 0000000000..d753509117 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/lana.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/na.ico b/plugins/!NotAdopted/WinPopup/icons/na.ico new file mode 100644 index 0000000000..e9cffaf26f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/occupied.ico b/plugins/!NotAdopted/WinPopup/icons/occupied.ico new file mode 100644 index 0000000000..2abca3db31 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/offline.ico b/plugins/!NotAdopted/WinPopup/icons/offline.ico new file mode 100644 index 0000000000..a94a20319a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/offline.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/online.ico b/plugins/!NotAdopted/WinPopup/icons/online.ico new file mode 100644 index 0000000000..8bd53fe6f7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/online.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/onthephone.ico b/plugins/!NotAdopted/WinPopup/icons/onthephone.ico new file mode 100644 index 0000000000..5f88fdbc48 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/onthephone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/other_name.ico b/plugins/!NotAdopted/WinPopup/icons/other_name.ico new file mode 100644 index 0000000000..b46b632318 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/other_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/other_names.ico b/plugins/!NotAdopted/WinPopup/icons/other_names.ico new file mode 100644 index 0000000000..c5eb01ad5c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/other_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico b/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico new file mode 100644 index 0000000000..9b144d1eea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico new file mode 100644 index 0000000000..4c6928082d Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico new file mode 100644 index 0000000000..778689c234 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico new file mode 100644 index 0000000000..58a04c226e Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico new file mode 100644 index 0000000000..9775d6deea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico new file mode 100644 index 0000000000..8ffa02a346 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico new file mode 100644 index 0000000000..290f2b4ef7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico new file mode 100644 index 0000000000..9dda2ec2ae Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico new file mode 100644 index 0000000000..d357c23da1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico b/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico new file mode 100644 index 0000000000..6ee65927cf Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico differ diff --git a/plugins/!NotAdopted/WinPopup/m_uninstaller.h b/plugins/!NotAdopted/WinPopup/m_uninstaller.h new file mode 100644 index 0000000000..695330c4c5 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/m_uninstaller.h @@ -0,0 +1,703 @@ +/* + + PluginUninstaller 1.1.2.1 for Miranda IM 0.3.3a and + + ------------------------------------------------------------------------ + Developers - C/C++ Header File + + Plugin Info: ---------------------------- + | Version: 1.1.2.1 + | Filename: uninstaller.dll + | Author: H. Herkenrath (hrathh@users.sourceforge.net) + | Description: Extends the plugin options and offers the possibility + | to directly remove plugins and delete all associated + | settings and files. + + Contents: ------------------------------- + | > General Info: + | - Uninstall Example/Template + | - Changing displayed icon + | - Changing displayed docs + | - Message boxes on uninstall + | - Service Accesibility + | - Including this file + | + | > Structs: + | - Uninstall Params (PLUGINUNINSTALLPARAMS) + | + | > Helpers: + | - Macro: Run service while uninstalling (PUICallService) + | - Function: Remove some files in directory (PUIRemoveFilesInDirectory) + | + | > Events: + | - Allow to uninstall a plugin (ME_PLUGINUNINSTALLER_OKTOUNINSTALL) + | - Plugin gets uninstalled (ME_PLUGINUNINSTALLER_UNINSTALL) + | + | > Services: + | - Remove database module (MS_PLUGINUNINSTALLER_REMOVEDBMODULE) + | - Remove a setting globally (MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY) + | - Remove skinned sound (MS_PLUGINUNINSTALLER_REMOVESKINSOUND) + | - Uninstall a plugin (MS_PLUGINUNISTALLER_UNISTALLPLUGIN) + | - Getting handles (MS_PLUGINUNINSTALLER_GETHANDLE) + | + + + This file is only thought for plugin developers. + If you only want to use "PluginUninstaller" and don't want to develop a plugin + or something with it you don't need this file. + + If there are any problems or bugs with or in this file or something else + please mail me. My e-mail address is: hrathh@users.sourceforge.net + For more documentation you can use this address, too. :-) + + If you have any whishes on some plugin uninstalling for your + plugin you can mail me, too. :-) + +*/ +#ifndef M_UNINSTALLER_H +#define M_UNINSTALLER_H + +#ifndef CallService + #pragma message("Mistake Alert!: "m_uninstaller.h" needs to be included after "newpluginapi.h"!\n The following errors are resulting of this mistake.\n") +#endif + + +// | General Info +// ----------------------------- + +// Uninstall Example/Template +// --------------------------- +// Making your plugin uninstallable is very easy. +// Just add the following "Uninstall" function near the "Unload" function +// in your plugin. +// A template plugin is available in the source code package. + +// Old: +// int __declspec(dllexport) Uninstall(BOOL bIsMirandaRunning, BOOL bDoDeleteSettings, char* pszPluginPath); + +// New: +//int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup) +//{ + // Available Variables: + // ----------------------------- + // ppup->bIsMirandaRunning: + // Contains if Miranda is running + // (Currently this is always TRUE). + + // ppup->bDoDeleteSettings: + // Contains if the users selected + // that he wants all settings be deleted. + + // ppup->pszPluginsPath: + // Contains the plugins directory name. + + + // Notes: + // ----------------------------- + + // Run before "Unload" function: + // -> IMPORTANT: Be careful not to write to the database or to files in "Unload" again!!! + // -> Perhaps create a global BOOL variable which is set to TRUE when your plugin gets uninstalled + // or check of a database setting "IsInstalled" in Unload() or sth. like that + + // All Miranda is still loaded + + // Here you can do: + // - Delete settings group in database + // - Delete registry items + // - Delete ini-files and other settings files + // - Delete other files + + // Your plugin dll gets automatically deleted + + // Services to remove are offered: + // MS_PLUGINUNINSTALLER_REMOVEDBMODULE + // MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + // MS_PLUGINUNINSTALLER_REMOVESKINSOUND + + + // Getting other useful paths: + // ----------------------------- + + // System directory: + + //char szSysPath[MAX_PATH]; + //GetSystemDirectory(szSysPath, MAX_PATH); + + + // Windows directory: + + //char szWinPath[MAX_PATH]; + //GetWindowsDirectory(szWinPath, MAX_PATH); + + + // Other directories: + + // char szPath[MAX_PATH]; + // SHGetSpecialFolderPath(NULL, szPath, CSIDL_* , FALSE); + + // Some available dirs: + // CSIDL_APPDATA CSIDL_SENDTO CSIDL_FAVORITES + // CSIDL_STARTUP CSIDL_PROFILE CSIDL_DESKTOPDIRECTORY + + + // Delete Files + //const char* apszFiles[] = {"MyPlugin_Readme.txt", "MyPlugin_License.txt", "MyPlugin_Developer.txt", "MyPlugin_Translation.txt"}; + //PUIRemoveFilesInPath(ppup->pszPluginsPath, apszFiles); + + // Delete Settings + //if(ppup->bDoDeleteSettings == TRUE) + //{ + //if (ppup->bIsMirandaRunning == TRUE) // Check if it is possible to access services + //{ + // Remove plugin's module + //PUIRemoveDbModule("MyPlugin"); + + // Remove plugin's sounds + //PUIRemoveSkinSound("MySoundSetting1"); + //PUIRemoveSkinSound("MySoundSetting2"); + //} + //} + + // Remember: + // Do not forget to remove your (eventually) created registry items here, too. + + + // The plugin's dll file gets deleted after returning. + + // Remember: + // If your DLL file is additionally in use by another application (eg. Windows) + // you need to free the DLL *here* completely. Otherwise it can't be deleted. + +// return 0; +//} + + + +// Changing displayed icon +// --------------------------- +// The icon that gets displayed on the options page is always the "first" +// icon in your DLL file. +// An icon in your DLL file is the first icon when it has the lowest recource ID. +// If you would like to have an other icon shown in the options please change your +// icon resource IDs so that the icon you would like to have has the lowest one. +// For example if you use MS Visual C++, open "resource.h" and change the resource define +// of your prefered icon to the lowest icon number. + + +// Changing displayed docs +// --------------------------- +// The items "License" and "More Information" on the plugin details page +// are created when the a license and/or a readme file for the plugin exists. +// The files get detected automatically and need a special name +// so that they get detected. +// The text files need to be either placed in the "Plugins" directory or +// in the "Docs" directory. Whereof the last one is the better one :-) +// +// For the license file the following file name formatings are possible: +// PluginName-License.txt (I personally think that this is the best naming solution... :-) ) +// PluginName_License.txt, +// +// For the readme file the following ones are possible: +// PluginName-Readme.txt (Again...I like this one :-D ), +// PluginName_Readme.txt, + +// Message boxes on uninstall +// --------------------------- +// If you would like to ask the user for something to remove/uninstall +// please hook the event ME_PLUGINUNINSTALLER_UNINSTALL and show your +// message box there. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + + +// Service Accessibility +// --------------------------- +// Remember that you only can use these functions after the event ME_SYSTEM_MODULESLOADED +// or later because "PluginUninstaller" needs to be loaded first. +// Normally you only use them in your "UninstallEx" function. +// +// IMPORTANT!: +// Please make sure that you always use the macro PUICallService +// in the "UninstallEx" function instead of the CallService function. + + +// Including this file +// --------------------------- +// To use some of the uninstalling functionality you have to include this file +// into your project. +// +// IMPORTANT!: +// Please make sure that you include the file "newpluginapi.h" before this one. +// If this isn't the case there may some compile errors come up. + + // -> Example: + // If your plugin is in the directory "Plugins/MyPlugin/" and + // this include file is in the directory "Plugins/PluginUninstaller" + // you can use the following: + + //#include "../PluginUninstaller/m_uninstaller.h" + + // If your plugin is in an directory that is different to that one just + // change the include path to the one you want. + + + + + +// | Structs +// ----------------------------- + +// --------------------------------------------- +// -- Struct: Uninstall Params ----------------- +// --------------------------------------------- + +// Struct: PLUGINUNINSTALLPARAMS +// (Gets passed to "UninstallEx" function) + +typedef int (*HELPERPROC)(const char*, WPARAM, LPARAM); // Used internally (for pHelperProcAddress) + +typedef struct { + BOOL bIsMirandaRunning; // Is TRUE when Miranda is loaded and services are available (Please use PUICallService instead of CallService) + BOOL bDoDeleteSettings; // Is TRUE when user wants to delete settings (If this is FALSE, please only delete your files) + char* pszPluginsPath; // Contains the plugin directory path + char* pszDocsPath; // Contains the document directory for plugins documentation (Added in version 1.1.1.0) + char* pszIconsPath; // Contains the icon directory for icon dlls (Added in version 1.1.2.0) + HELPERPROC pHelperProcAddress; // Used internally (Contains proc address for PUICallService) +} PLUGINUNINSTALLPARAMS; + + + + + +// | Helper +// ----------------------------- + + +// --------------------------------------------- +// -- Macro: Run service while uninstalling ---- +// --------------------------------------------- + +// Macro: PUICallService + +#define PUICallService(service, wParam, lParam) (ppup->pHelperProcAddress) (service, wParam, lParam); + +// Description: +// ------------- +// This service provides the possibility to call a Miranda +// service in the "UninstallEx" function. +// Important!: Use this macro always instead of "CallService", +// because else a crash occurs when the plugin was decativated +// and gets uninstalled + +// Parameters: +// ------------- +// Same parameters as CallService of Miranda Core. + +// Return Values: +// -------------- +// Return values are the same as the CallService function of Miranda Core. +// Additionaly returns CALLSERVICE_NOTFOUND if Miranda is not loaded +// which means the services are not accessable. + + + // Example: + // ---------------------------------- + + //if ( (bIsMirandaRunning == TRUE) && (bDoDeleteSettings == TRUE) ) + //{ + // Remove plugin's module + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)"MyPlugin", 0); + //} + + + + +// --------------------------------------------- +// -- Function: Remove some files in directory - +// --------------------------------------------- + +// Function: PUIRemoveFilesInDirectory + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]); + +// Description: +// ------------- +// This helper provides the possibility to easily +// remove specified files in a specified directory. + +// Note: The last version of this helper (PUIRemoveFilesInPath) +// did not work correctly. +// Please do now always append a NULL slot to the end of your array. + +// Parameters: +// ------------- +// char* pszPath = Path to the files in array +// const LPCSTR apszFiles[] = NULL-terminated array of files to be deleted. + +// Return Values: +// -------------- +// Returns TRUE if the files could be deleted. +// FALSE if the files could not be deleted or did not exist. + + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]) +{ + char szFile[MAX_PATH]; + BOOL bReturn = FALSE; + unsigned iFile = 0; + unsigned cbPath = (unsigned)lstrlenA(pszPath); + + for (; apszFiles[iFile] != NULL; ++iFile) + { + if(cbPath + lstrlenA(apszFiles[iFile]) < sizeof(szFile) / sizeof(szFile[0])) + { + lstrcpyA(szFile, pszPath); + lstrcatA(szFile, apszFiles[iFile]); + + if (DeleteFileA(szFile)) bReturn = TRUE; + } + } + + return bReturn; +} + + // Example: + // ---------------------------------- + + //const char* apszFiles[] = {"File1.txt", "File2.txt", "File3.txt", NULL}; + //PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles); + + + + +// | Events +// ----------------------------- + + +// --------------------------------------------- +// -- Event: Allow to uninstall a plugin ------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_OKTOUNINSTALL + +#define ME_PLUGINUNINSTALLER_OKTOUNINSTALL "PluginUninstaller/OkToUninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the "Remove Plugin" button to be disabled. + + + +// --------------------------------------------- +// -- Event: Plugin gets uninstalled ----------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_UNINSTALL + +#define ME_PLUGINUNINSTALLER_UNINSTALL "PluginUninstaller/Uninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the uninstall process to be canceled. + +// Notice: +// Hook this event if you would like to ask the user for something to remove/uninstall +// and show your message box on this event. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + +// Other plugins can use this event to be noticed that another plugin isn't installed anylonger. + + + + +// | Services +// ----------------------------- + + +// --------------------------------------------- +// -- Service: Remove database module ---------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBMODULE + +#define MS_PLUGINUNINSTALLER_REMOVEDBMODULE "PluginUninstaller/RemoveDbModule" + +// Description: +// ------------- +// This service provides the possibility to delete all database modules +// associated to your plugin. +// The specified database module will be removed in all contacts +// including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule // Pointer to a string containd module name. Can't be NULL +// lParam = (const char*)apszIgnoreSettings // NULL terminated array of strings. Can be 0 if no settings should be ignored. + // See example 3 for more details + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the module was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbModule(pszModule) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)pszModule, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbModule("MyPlugin"); + + + // Example 2: + // ---------------------------------- + + //char szModule[] = "MyModule"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, 0); + + + // Example 3: + // ---------------------------------- + + // This deletes all settings in the specified module exept + // the specified settings: "Setting1",..."Setting4" + + // char szModule[] = "MyModule"; + // const char* apszIgnoreSettings[] = {"Setting1", "Setting2", "Setting3", "Setting4", NULL}; + // PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, (LPARAM)&apszIgnoreSettings); + + + +// --------------------------------------------- +// -- Service: Remove a setting globally ------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + +#define MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY "PluginUninstaller/RemoveDbSettingGlobally" + +// Description: +// ------------- +// This service provides the possibility to delete a specific +// setting in database in all contacts including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule +// lParam = (char*)pszSetting + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the setting was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbSettingGlobally(pszModule, pszSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)pszModule, (LPARAM)pszSetting); + + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbSettingGlobally("MyPlugin", "MySetting"); + + + // Example 2: + // ---------------------------------- + + //szModule[] = "MyPlugin"; + //szSetting[] = "MySetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)szModule, (LPARAM)szSetting); + + + + + + +// --------------------------------------------- +// -- Service: Remove skinned sound ------------ +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVESKINSOUND + +#define MS_PLUGINUNINSTALLER_REMOVESKINSOUND "PluginUninstaller/RemoveSkinSound" + +// Description: +// ------------- +// This service provides the possibility to delete all your sound settings +// associated to your plugin. +// The specified sound will be be removed. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszSoundSetting +// lParam = 0 + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the sound was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveSkinSound(pszSoundSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVESKINSOUND, (WPARAM)pszSoundSetting, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveSkinSound("MySoundSetting"); + + + // Example 2: + // ---------------------------------- + + //szSoundModule[] = "MySoundSetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szSoundSetting, 0); + + + + + +// --------------------------------------------- +// -- Service: Uninstall a plugin -------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN + +#define MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN "PluginUninstaller/UninstallPlugin" + +// Description: +// ------------- +// This service marks a plugin to be uninstalled at next restart of Miranda IM. +// It uses the default value for "Delete all settings". +// You can use this service for example when you want that your sub-plugin gets +// also removed when your main-plugin is uninstalled. +// Note: This service is not needed for the normal uninstalling functionality. + +// Parameters: +// ------------- +// wParam = (char*)pszPluginName // do not translate this! +// lParam = (char*)pszPluginFile // without path, only file name! + +// Return Values: +// -------------- +// Returns always 0. + + +#ifndef UNINSTALLER_NOHELPERS + +int __inline PUIUninstallPlugin(char* pszPluginName, char* pszPluginFile) +{ + return CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)pszPluginName, (LPARAM)pszPluginFile); +} + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIUninstallPlugin("PluginName", "plugin.dll"); + + + // Example 2: + // ---------------------------------- + + // hInst => Handle of a specific (your?) plugin + // char szPluginName[] = "YourPluginName"; + + //char* pFileName; + //char szPath[MAX_PATH]; + + //GetModuleFileName(hInst, szPath, sizeof(szPath)); + //pFileName = strrchr(szPath, '\\'); + //pFileName = pFileName+1; // Pointer arithmetic + + //CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)szPluginName, (LPARAM)pFileName); + + + + +// --------------------------------------------- +// -- Service: Getting handles ----------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_GETHANDLE + +#define MS_PLUGINUNINSTALLER_GETHANDLE "PluginUninstaller/GetHandle" + +// Description: +// ------------- +// This service gets a specified window/instance handle. + +// Note: This service must not be used in "UninstallEx" function. +// It is mainly thought for being used in ME_PLUGINUNINSTALLER_UNINSTALL event +// to give out a MessageBox or something like that. + +// Parameters: +// ------------- +// wParam = UINT uHandleType; +// lParam = 0 + +// Possible values for wParam: +#define PUIHT_HINST_PLUGIN_INSTANCE 0 // HINSTANCE of the PluginUninstaller plugin +#define PUIHT_HWND_PLUGIN_OPTIONS 1 // HWND of the plugin options dialog (if it is loaded; else NULL) + +// Return Values: +// -------------- +// Returns the specified handle value. +// If no handle type is specified it returns NULL. +// The handle doesn't need to be destroyed. + + +#ifndef UNINSTALLER_NOHELPERS + +HANDLE __inline PUIGetHandle(UINT uHandleType) +{ + return (HANDLE)CallService(MS_PLUGINUNINSTALLER_GETHANDLE, uHandleType, 0); +} + +#endif + + + // Example + // ---------------------------------- + + //HWND hwndDlg; + //hwndDlg = (HWND)PUIGetHandle(PUIHT_HWND_PLUGIN_OPTIONS); + + + + + +#endif // M_UNINSTALLER_H diff --git a/plugins/!NotAdopted/WinPopup/m_updater.h b/plugins/!NotAdopted/WinPopup/m_updater.h new file mode 100644 index 0000000000..c83b8a4600 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/m_updater.h @@ -0,0 +1,117 @@ +#ifndef _M_UPDATER_H +#define _M_UPDATER_H + +// if you set Update::szUpdateURL to the following value when registering, as well as setting your beta site and version data, +// updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data. +// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case) +#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER" + +typedef struct Update_tag { + int cbSize; + char *szComponentName; // component name as it will appear in the UI (will be translated before displaying) + + char *szVersionURL; // URL where the current version can be found (NULL to disable) + BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + // (not that this URL could point at a binary file - dunno why, but it could :) + int cpbVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szUpdateURL; // URL where dll/zip is located + // set to UPDATER_AUTOREGISTER if you want updater to find the file listing URLs (ensure plugin shortName matches file listing!) + + char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas) + BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + int cpbBetaVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szBetaUpdateURL; // URL where dll/zip is located + + BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL + int cpbVersion; // number of bytes pionted to by pbVersion + + char *szBetaChangelogURL; // url for displaying changelog for beta versions +} Update; + +// register a comonent with the updater +// +// wparam = 0 +// lparam = (LPARAM)&Update +#define MS_UPDATE_REGISTER "Update/Register" + +// utility functions to create a version string from a DWORD or from pluginInfo +// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter +// +__inline static char *CreateVersionString(DWORD version, char *buf) { + mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); + return buf; +} + +__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) { + return CreateVersionString(pluginInfo->version, buf); +} + + +// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing +// NOTE: the plugin 'short name' in pluginInfo must match the name of the plugin on the file listing, exactly (not including case) +// AND the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1, +// so no letters, brackets, etc.) +// +// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link) +// lParam = (PLUGININFO*)&pluginInfo +#define MS_UPDATE_REGISTERFL "Update/RegisterFL" + +// this event is fired when the startup process is complete, but NOT if a restart is imminent +// it is designed for status managment plugins to use as a trigger for beggining their own startup process +// wParam = lParam = 0 (unused) +// (added in version 0.1.6.0) +#define ME_UPDATE_STARTUPDONE "Update/StartupDone" + +// this service can be used to enable/disable Updater's global status control +// it can be called from the StartupDone event handler +// wParam = (BOOL)enable +// lParam = 0 +// (added in version 0.1.6.0) +#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl" + +// An description of usage of the above service and event: +// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler. +// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function, +// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service. +// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may +// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature. + +#endif + + +/////////////// Usage Example /////////////// + +#ifdef EXAMPLE_CODE + +// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function... + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + + Update update = {0}; // for c you'd use memset or ZeroMemory... + char szVersion[16]; + + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) + update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip"; + update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html"; + update.pbVersionPrefix = (BYTE *)"Updater version "; + + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + + // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing... + // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo); + + return 0; +} + +#endif diff --git a/plugins/!NotAdopted/WinPopup/mailslot.cpp b/plugins/!NotAdopted/WinPopup/mailslot.cpp new file mode 100644 index 0000000000..5774cfa2a9 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/mailslot.cpp @@ -0,0 +1,313 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "mailslot.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define MAX_MESSAGE_SIZE 424 // Размер пакета данных (байт) посылаемых/принимаемых + // через мейлслот + +mailslot pluginMailslot; // Мейлслот для приема сообщений + +/*const struct { // Список конфликтующих процессов + LPCTSTR name; +} blacklist [] = { + _T("winpopup"), + _T("vikpopup"), + _T("netter"), + _T("realpopup"), + NULL +};*/ + +//////////////////////////////////////////////////////////////////////// +// Class mailslot + +mailslot::mailslot () : + m_hMailslot (INVALID_HANDLE_VALUE), + m_MonitorTerm (NULL), + m_Monitor (NULL) +{ +} + +mailslot::~mailslot () +{ + Destroy (); +} + +bool mailslot::Create (LPCTSTR Name) +{ + CLock oLock( m_cs ); + + m_sName = Name; + + bool ret = true; + if ( ! IsValid() ) + { + // Открытие мейлслота + CString sAddr; + sAddr.Format( _T("\\\\.\\mailslot\\%s"), (LPCTSTR)m_sName ); + + m_hMailslot = CreateMailslot( sAddr, 0, 2000, NULL ); + if ( ! IsValid() ) + { + ret = false; + DWORD err = GetLastError (); + if (err == ERROR_ALREADY_EXISTS) + WarningBox (NULL, 0, _T("%s\r\n%s"), T_CREATE_ERROR, + TranslateT ("Please shutdown any other IM applications and/or Messenger service")); + else + WarningBox (NULL, err, T_CREATE_ERROR); + } + } + if (ret) + { + if (m_MonitorTerm) + ResetEvent (m_MonitorTerm); + else + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + m_Monitor = (HANDLE)mir_forkthread( MonitorThread, this ); + } + + return ret; +} + +void mailslot::AskForDestroy() +{ + if (m_MonitorTerm) + SetEvent (m_MonitorTerm); +} + +void mailslot::Destroy () +{ + CLock oLock( m_cs ); + + // Запрос останова мониторинга мейлслота + AskForDestroy(); + + // Закрытие мейлслота + if ( IsValid() ) + { + CloseHandle (m_hMailslot); + m_hMailslot = INVALID_HANDLE_VALUE; + } + + // Ожидание останова мониторинга + if (m_Monitor) + { + if (WaitForSingleObject (m_Monitor, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate mailslot monitor!"); + TerminateThread (m_Monitor, 0); + } + m_Monitor = NULL; + } + if (m_MonitorTerm) + { + CloseHandle (m_MonitorTerm); + m_MonitorTerm = NULL; + } +} + +bool mailslot::IsValid() const +{ + return ( m_hMailslot != INVALID_HANDLE_VALUE ); +} + +bool mailslot::SendMailslotMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = ERROR_BAD_NETPATH; + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = ERROR_BAD_NETPATH; + return false; + } + + // Нет разницы группа это или компьютер + // bool bGroup = IsGroup( hContact ); + + // Сборка пакета сообщения: FROM<00>TO<00>MESSAGE<00> + COemString sOemMessage = msg; + COemString sOemTo = (LPCTSTR)sTo; + COemString sOemFrom = (LPCTSTR)sFrom; + + // Размер заголовка пакета + int fixed_size = sOemFrom.GetLength() + 1 + sOemTo.GetLength() + 1 + 1; + if ( fixed_size >= MAX_MESSAGE_SIZE ) + { + err = ERROR_BAD_LENGTH; + return false; + } + + // Создание мейлслота для отправки сообщения + CString sAddr; + sAddr.Format( _T("\\\\%s\\mailslot\\%s"), sTo, (LPCTSTR)m_sName ); + HANDLE hFile = CreateFile( sAddr, GENERIC_WRITE, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) + { + err = GetLastError(); + return false; + } + + int max_message_size = MAX_MESSAGE_SIZE - fixed_size; + char buf[ MAX_MESSAGE_SIZE ] = {}; + lstrcpynA( buf, sOemFrom, sOemFrom.GetLength() + 1 ); + lstrcpynA( buf + sOemFrom.GetLength() + 1, sOemTo, sOemTo.GetLength() + 1 ); + do + { + int message_size = ( sOemMessage.GetLength() < max_message_size ) ? + sOemMessage.GetLength() : max_message_size; + lstrcpynA( buf + fixed_size - 1, sOemMessage, message_size + 1 ); + + // Отсылка пакета + DWORD written = 0; + if ( ! WriteFile( hFile, buf, (DWORD)fixed_size + message_size, &written, NULL ) || + ( written < (DWORD)fixed_size ) ) + { + err = GetLastError(); + CloseHandle( hFile ); + return false; + } + Sleep( 100 ); + + // Укорачивание на отосланный пакет + sOemMessage.CutFromStart( message_size ); + } + while ( sOemMessage.GetLength() ); + + err = ERROR_SUCCESS; + CloseHandle( hFile ); + return true; +} + +bool mailslot::Receive(unsigned char* buf /* OEM */, DWORD size) +{ + // Разборка сообщения <00><00><00> (последний <00> необязателен) + if (size) + { + char* from = (char*) buf; + char* to = lstrnchr (from, 0, (int)size); + if (to) + { + DWORD from_len = (DWORD)( to - from + 1 ); + if ( from_len < size ) + { + to++; + size -= from_len; + char* msg = lstrnchr (to, 0, (int)size); + if (msg) + { + DWORD to_len = (DWORD)( msg - to + 1 ); + if (to_len < size) + { + msg++; + size -= to_len; + char* eof = lstrnchr (msg, 0, (int)size); + DWORD msg_len = eof ? (DWORD)( eof - msg + 1 ) : size; + if (msg_len == size) + { + CAnsiString sFrom (from); + CAnsiString sTo (to); + CAnsiString sMessage (msg); + ReceiveContactMessage(sFrom, sTo, sMessage, sMessage.GetLength ()); + return true; + } + } + } + } + } + } + return false; +} + +void mailslot::MonitorThread(void* param) +{ + if ( mailslot* pMailslot = (mailslot*)param ) + { + pMailslot->Monitor(); + pMailslot->m_Monitor = NULL; + } +} + +void mailslot::Monitor () +{ + // Ожидание прерывания 500 мс при закрытом майлслоте, иначе 50 мс + while ( WaitForSingleObject( m_MonitorTerm, IsValid() ? 50u : 500u ) == WAIT_TIMEOUT ) + { + // Проверка входящих сообщений + LPSTR buf = NULL; + for ( DWORD buf_size = MAX_MESSAGE_SIZE; IsValid(); buf_size += 1024 ) + { + if ( WaitForSingleObject( m_MonitorTerm, 0 ) != WAIT_TIMEOUT ) + break; + + if ( buf ) mir_free( buf ); + buf = (LPSTR)mir_alloc( buf_size ); + + DWORD readed = 0; + DWORD err = ReadFile (m_hMailslot, buf, buf_size, + &readed, NULL) ? ERROR_SUCCESS : GetLastError (); + if (err == ERROR_ACCESS_DENIED || err == ERROR_SEM_TIMEOUT) + { + // Тайм-аут мейлслота + break; + } + else if (err == ERROR_SUCCESS) + { + // Данные приняты + if (readed) + if (!Receive((LPBYTE)buf, readed)) + LOG("Receive error (bad format?)"); + break; + } + else if (err == ERROR_INSUFFICIENT_BUFFER) + { + // Нехватка размера буфера + continue; + } + else + { + // Другие ошибки + // ERROR_HANDLE_EOF - хендл мейлслота закрыт + LOG("ReadFile form mailslot error: %d", err); + break; + } + } + if ( buf ) mir_free( buf ); + } +} diff --git a/plugins/!NotAdopted/WinPopup/mailslot.h b/plugins/!NotAdopted/WinPopup/mailslot.h new file mode 100644 index 0000000000..921127ae6e --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/mailslot.h @@ -0,0 +1,48 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +class mailslot +{ +public: + mailslot(); + ~mailslot(); + + bool Create(LPCTSTR Name); + void AskForDestroy(); // Для ускорения + void Destroy(); + bool IsValid() const; + bool SendMailslotMessage(HANDLE hContact, LPCTSTR msg, DWORD& err); + +protected: + CString m_sName; // Имя мейлслота + HANDLE m_hMailslot; // Хэндлер мейлслота + CComAutoCriticalSection m_cs; // Защита данных + HANDLE m_MonitorTerm; // Событие для остановки Monitor + HANDLE m_Monitor; // Прием/отправка сообщений через мейлслот + + bool Receive(unsigned char* buf /* OEM */, DWORD size); + static void MonitorThread(void* param); + void Monitor(); +}; + +extern mailslot pluginMailslot; // Мейлслот для приема сообщений diff --git a/plugins/!NotAdopted/WinPopup/md5.h b/plugins/!NotAdopted/WinPopup/md5.h new file mode 100644 index 0000000000..dc5284ed35 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/md5.h @@ -0,0 +1,222 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +typedef unsigned long uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +// initialization constants. +inline void md5init (struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +// The four core functions - F1 is optimized somewhat +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +// This is the central step in the MD5 algorithm. +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +// The core of the MD5 algorithm, this alters an existing MD5 hash to +// reflect the addition of 16 longwords of new data. MD5Update blocks +// the data and converts bytes into longwords for this routine. +inline void md5transform (uint32 buf[4], uint32 in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +// Update context to reflect the concatenation of another buffer full of bytes. +inline void md5update (struct MD5Context *ctx, const unsigned char *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + CopyMemory (p, buf, len); + return; + } + CopyMemory (p, buf, t); + md5transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + CopyMemory (ctx->in, buf, 64); + md5transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + CopyMemory (ctx->in, buf, len); +} + +// Final wrapup - pad to 64-byte boundary with the bit pattern +// 1 0* (64-bit count of bits processed, MSB-first) +inline void md5final (unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + ZeroMemory (p, count); + md5transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + ZeroMemory (ctx->in, 56); + } else { + /* Pad block to 56 bytes */ + ZeroMemory (p, count - 8); + } + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + md5transform(ctx->buf, (uint32 *) ctx->in); + CopyMemory (digest, ctx->buf, 16); + ZeroMemory (ctx, sizeof(ctx)); /* In case it's sensitive */ +} diff --git a/plugins/!NotAdopted/WinPopup/messagebox.cpp b/plugins/!NotAdopted/WinPopup/messagebox.cpp new file mode 100644 index 0000000000..008110c269 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messagebox.cpp @@ -0,0 +1,232 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "messagebox.h" +#include "netbios.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +class messagebox +{ +public: + messagebox () : + m_hwndOwner (NULL), + m_hwndMessageBox (NULL), + m_Timeout (0), + m_MonitorTerm (NULL) + { + } + + int WINAPI DoModal (const LPMSGBOXPARAMS lpMsgBoxParams, DWORD dwTimeout) + { + int ret = 0; + m_hwndOwner = lpMsgBoxParams->hwndOwner; + m_Timeout = dwTimeout; + m_hwndMessageBox = NULL; + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + if (m_MonitorTerm) { + HANDLE hThread = (HANDLE)mir_forkthread( MsgBox, this ); + if (hThread) { + + ret = MessageBoxIndirect (lpMsgBoxParams); + + // Ожидание завершения + SetEvent (m_MonitorTerm); + WaitForSingleObject (hThread, INFINITE); + } + CloseHandle (m_MonitorTerm); + } + return ret; + } + +protected: + static BOOL CALLBACK EnumWindowsProc (HWND hWnd, LPARAM lParam) + { + messagebox* self = reinterpret_cast (lParam); + + DWORD dwProcessId; + GetWindowThreadProcessId (hWnd, &dwProcessId); + const LONG req_style = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU; + HWND hButton; + TCHAR ClassName[ 8 ]; + if ( GetCurrentProcessId () != dwProcessId || + ( GetWindowLongPtr(hWnd, GWL_STYLE) & req_style ) != req_style || + GetParent( hWnd ) != NULL || + GetWindow( hWnd, GW_OWNER ) != self->m_hwndOwner || + ( hButton = GetWindow( hWnd, GW_CHILD ) ) == NULL || + GetClassName( hButton, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi( _T("button"), ClassName ) != 0 ) + return TRUE; + + self->m_hwndMessageBox = hWnd; + + return FALSE; + } + + static void MsgBox (LPVOID param) + { + messagebox* self = reinterpret_cast (param); + + // Ловим диалог 10 секунд + DWORD i = 0; + while (WaitForSingleObject (self->m_MonitorTerm, 250) == WAIT_TIMEOUT && + EnumWindows (messagebox::EnumWindowsProc, reinterpret_cast (self)) && + i++ < 10 * 4); + if (!self->m_hwndMessageBox) + // Так и не поймали + return; + + HWND hButton = GetWindow (self->m_hwndMessageBox, GW_CHILD); + + // Отсчёт времени + while (self->m_Timeout-- && + WaitForSingleObject (self->m_MonitorTerm, 1000) == WAIT_TIMEOUT && + IsWindow (self->m_hwndMessageBox) && IsWindow (hButton)) { + CString buf, msg; + int buf_size = GetWindowTextLength (hButton); + if (buf_size) { + GetWindowText (hButton, buf.GetBuffer (buf_size + 1), buf_size + 1); + buf.ReleaseBuffer (); + } + int n = buf.ReverseFind (_T('=')); + msg.Format (_T(" = %u"), self->m_Timeout); + SetWindowText (hButton, ((n < 1) ? buf : buf.Left (n - 1)) + msg); + } + + // Закрытие окна + if (IsWindow (self->m_hwndMessageBox) && IsWindow (hButton)) { + DWORD_PTR res; + SendMessageTimeout (self->m_hwndMessageBox, WM_COMMAND, + (WPARAM) GetDlgCtrlID (hButton), + (LPARAM) hButton, SMTO_ABORTIFHUNG | SMTO_NORMAL, 10000, &res); + } + + return; + } + + volatile HWND m_hwndOwner; + volatile HWND m_hwndMessageBox; + volatile DWORD m_Timeout; + HANDLE m_MonitorTerm; +}; + +static int WINAPI MessageBoxIndirectTimeout (const LPMSGBOXPARAMS lpMsgBoxParams, DWORD dwTimeout) +{ + messagebox mb; + return mb.DoModal (lpMsgBoxParams, dwTimeout); +} + +LPCTSTR const szModules [] = { + _T("netapi32.dll"), + _T("netmsg.dll"), + _T("wininet.dll"), + _T("ntdll.dll"), + _T("ntdsbmsg.dll"), + NULL +}; + +void GetErrorMessage (DWORD dwLastError, CString &msg) +{ + CString buf; + if ( HRESULT_FACILITY( dwLastError ) == FACILITY_NETBIOS ) + { + CString sMessage = (LPCTSTR)CA2T( GetNetbiosError( HRESULT_CODE ( dwLastError ) ) ); + if ( ! sMessage.IsEmpty() ) + msg.Format( _T("%s\r\nNetBIOS %s: %u"), sMessage, T_ERROR, HRESULT_CODE( dwLastError ) ); + else + msg.Format( _T("NetBIOS %s: %u"), T_ERROR, HRESULT_CODE( dwLastError ) ); + } + else + { + HMODULE hModule = NULL; + for (int i = 0; szModules [i]; i++) + { + hModule = LoadLibraryEx (szModules [i], NULL, LOAD_LIBRARY_AS_DATAFILE); + LPTSTR MessageBuffer = NULL; + if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM | + (hModule ? FORMAT_MESSAGE_FROM_HMODULE : 0u), + hModule, dwLastError, 0u, (LPTSTR) &MessageBuffer, 0u, NULL)) + { + buf = MessageBuffer; + buf.Trim (_T(" \t\r\n")); + LocalFree (MessageBuffer); + if (hModule) + FreeLibrary (hModule); + break; + } + if (hModule) + FreeLibrary (hModule); + } + if ( ! buf.IsEmpty() ) + msg.Format( _T("%s\r\n%s: %u"), (LPCTSTR)buf, T_ERROR, dwLastError ); + else + msg.Format( _T("%s: %u"), T_ERROR, dwLastError ); + } +} + +static void PopupOrMessageBox (LPPOPUPDATAT ppdp) +{ + if (CALLSERVICE_NOTFOUND == PUAddPopUpT (ppdp)) + { + MSGBOXPARAMS mbp = { 0 }; + mbp.cbSize = sizeof (MSGBOXPARAMS); + mbp.lpszText = ppdp->lptzText; + mbp.lpszCaption = ppdp->lptzContactName; + mbp.dwStyle = MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL; + MessageBoxIndirectTimeout (&mbp, (DWORD)ppdp->iSeconds); + } +} + +void WarningBox (HANDLE hContact /* = NULL */, DWORD dwLastError /* = 0 */, LPCTSTR format, ...) +{ + if (!pluginInstalled) + return; + + POPUPDATAT pdp = { 0 }; + pdp.lchContact = hContact; + pdp.lchIcon = (HICON) LoadImage( pluginModule, MAKEINTRESOURCE (IDI_WINPOPUP), + IMAGE_ICON, 16, 16, LR_SHARED ); + lstrcpy (pdp.lptzContactName, modtitle_t); + va_list marker; + va_start (marker, format); + wvsprintf( pdp.lptzText, format, marker ); + va_end (marker); + pdp.iSeconds = 10; + + if (dwLastError) { + CString msg; + GetErrorMessage (dwLastError, msg); + int len = lstrlen (pdp.lptzText); + pdp.lptzText [len] = _T('\r'); + pdp.lptzText [len + 1] = _T('\n'); + lstrcpy (pdp.lptzText + len + 2, msg); + } + + PopupOrMessageBox (&pdp); +} diff --git a/plugins/!NotAdopted/WinPopup/messagebox.h b/plugins/!NotAdopted/WinPopup/messagebox.h new file mode 100644 index 0000000000..bde25887f4 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messagebox.h @@ -0,0 +1,29 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +// Отображение пояснительного текста ошибки в виде высплывающей подсказки если +// установлен Popup Plugin, иначе в виде диалога с автозакрытием +void WarningBox (HANDLE hContact /* = NULL */, DWORD dwLastError /* = 0 */, LPCTSTR format, ...); + +// Получение описания WinAPI или NetBIOS ошибки по её номеру +void GetErrorMessage (DWORD dwLastError, CString &msg); diff --git a/plugins/!NotAdopted/WinPopup/messenger.cpp b/plugins/!NotAdopted/WinPopup/messenger.cpp new file mode 100644 index 0000000000..b73bd4b23a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messenger.cpp @@ -0,0 +1,469 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "services.h" +#include "messenger.h" +#include "processapi.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static bool IsMessengerRunning() +{ + bool found = false; + HANDLE h = CreateMailslot (_T("\\\\.\\mailslot\\") MESSENGER_MAIL, 0, 0, NULL); + if (h == INVALID_HANDLE_VALUE) { + if (GetLastError () == ERROR_ALREADY_EXISTS) + found = true; + else + LOG ("IsMessengerRunning() error 0x%08x", GetLastError ()); + } else + CloseHandle (h); + return found; +} + +messenger pluginMessenger; // Прием/отправка сообщений через Messenger + +messenger::messenger () : + m_MonitorTerm (NULL), + m_Monitor (NULL), + m_ID (0), + m_bMSMessengerStopped (false) +{ +} + +messenger::~messenger () +{ + Destroy (); +} + +bool messenger::Create(BOOL start) +{ + if ( pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT ) + return false; + + // Косвенная проверка, что Messenger запущен + bool messngr = IsMessengerRunning(); + if ( start ) + { + if ( ! messngr ) + Start (); + } + else + { + if ( messngr ) + Stop (); + } + + m_ID = GetProcessId (_T("csrss.exe")); + LOG ( ( m_ID ? "Messenger host process CSRSS.EXE found : PID %u(%08x)" : + "Messenger host process CSRSS.EXE not found" ), m_ID, m_ID ); + + // Запуск сканера контактов + if (m_MonitorTerm) + ResetEvent (m_MonitorTerm); + else + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + + if (!m_Monitor) + m_Monitor = (HANDLE)mir_forkthread( MonitorThread, this ); + + return (m_Monitor != NULL); +} + +void messenger::AskForDestroy() +{ + if (m_MonitorTerm) + SetEvent (m_MonitorTerm); +} + +void messenger::Destroy () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return; + + AskForDestroy(); + + if (m_Monitor) + { + if (WaitForSingleObject (m_Monitor, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate Messenger monitor!"); + TerminateThread (m_Monitor, 0); + } + m_Monitor = NULL; + } + + if (m_MonitorTerm) + { + CloseHandle (m_MonitorTerm); + m_MonitorTerm = NULL; + } + + // Запуск "Службы Сообщений", если ее останавливали + if (m_bMSMessengerStopped) + Start (); +} + +messenger::operator bool () const +{ + return (m_Monitor != NULL); +} + +BOOL CALLBACK messenger::EnumWindowsProc (HWND hWnd, LPARAM lParam) +{ + DWORD dwTargetId = reinterpret_cast (lParam)->m_ID; + DWORD dwProcessId = 0; + GetWindowThreadProcessId (hWnd, &dwProcessId); + if (dwTargetId && dwTargetId != dwProcessId) + return TRUE; + + const LONG req_style = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU; + const LONG req_style_ex = WS_EX_TOPMOST; + HWND hButton, hText; + TCHAR ClassName[ 8 ] = {}; + if ((GetWindowLongPtr(hWnd, GWL_STYLE) & req_style) != req_style || + (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & req_style_ex) != req_style_ex || + GetParent (hWnd) != NULL || + GetWindow (hWnd, GW_OWNER) != NULL || + // child 1 = Button, child 2 = STATIC, child 3 = NULL + (hButton = GetWindow (hWnd, GW_CHILD)) == NULL || + GetClassName( hButton, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi (_T("button"), ClassName) != 0 || + (hText = GetNextWindow (hButton, GW_HWNDNEXT)) == NULL || + GetClassName( hText, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi( _T("static"), ClassName ) != 0 || + GetNextWindow (hText, GW_HWNDNEXT) != NULL) + // Чужое окно + return TRUE; + + CString buf; + int buf_size = GetWindowTextLength (hText); + if (buf_size) { + GetWindowText (hText, buf.GetBuffer (buf_size + 1), buf_size + 1); + buf.ReleaseBuffer (); + } + + if (!buf.IsEmpty ()) { + CString tok, from, to, msg; + int curPos = 0; + for (int i = 0; (tok = buf.Tokenize( _T(" "), curPos)), !tok.IsEmpty (); i++) { + switch (i) { + case 2: + from = tok; + break; + case 4: + to = tok; + break; + } + } + int n = buf.Find ( _T("\n") ); + msg = buf.Mid (n + 3); + if (!from.IsEmpty () && !to.IsEmpty () && !msg.IsEmpty ()) { + // Закрытие окна + DWORD_PTR res = 0; + SendMessageTimeout (hWnd, WM_COMMAND, (WPARAM) GetDlgCtrlID (hButton), + (LPARAM) hButton, SMTO_ABORTIFHUNG | SMTO_NORMAL, 10000, &res); + + // Ок + ReceiveContactMessage(from, to, msg, msg.GetLength ()); + } + } + + return FALSE; +} + +void messenger::Monitor () +{ + while (WaitForSingleObject (m_MonitorTerm, 250) == WAIT_TIMEOUT) + { + EnumWindows (EnumWindowsProc, reinterpret_cast (this)); + } + m_Monitor = NULL; +} + +void messenger::MonitorThread(LPVOID lpParameter) +{ + reinterpret_cast< messenger* >( lpParameter )->Monitor(); +} + +// Запуск "Службы Сообщений" +bool messenger::Start () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return false; + + bool ret = m_bMSMessengerStopped = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SC_MANAGER_CONNECT); + if (manager) { + // Открытие сервиса + SC_HANDLE service = fnOpenService (manager, MESSENGER, + SERVICE_START | SERVICE_QUERY_STATUS); + if (service) { + for(;;) + { + // Проверка состояния сервиса + SERVICE_STATUS ss = { 0 }; + if (fnQueryServiceStatus (service, &ss)) { + if (ss.dwCurrentState == SERVICE_RUNNING) { + // Уже работает + LOG ("Messenger service already running"); + ret = true; + } else { + // Запуск сервиса + if (fnStartService (service, 0, NULL)) + // Ожидание запуска сервиса + ret = WaitForService (T_START_ERROR, service, SERVICE_START_PENDING, SERVICE_RUNNING); + else { + DWORD err = GetLastError (); + if ( err == ERROR_SERVICE_DISABLED ) + { + // Попытка разрешения сервиса + if ( Enable() ) + // Повтор + continue; + } else + WarningBox (NULL, err, T_START_ERROR); + } + } + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + break; + } + fnCloseServiceHandle (service); + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + fnCloseServiceHandle (manager); + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + return ret; +} + +// Останов "Службы Сообщений" +bool messenger::Stop () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return false; + + bool ret = m_bMSMessengerStopped = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SC_MANAGER_CONNECT); + if (manager) + { + // Открытие сервиса + SC_HANDLE service = fnOpenService (manager, MESSENGER, + SERVICE_STOP | SERVICE_QUERY_STATUS); + if (service) + { + // Проверка состояния сервиса + SERVICE_STATUS ss = {}; + if (fnQueryServiceStatus (service, &ss)) + { + if (ss.dwCurrentState == SERVICE_STOPPED) + { + // Уже остановлен + LOG ("Messenger service already stopped"); + ret = true; // m_bMSMessengerStopped = false + } + else + { + // Останов сервиса + ZeroMemory (&ss, sizeof (SERVICE_STATUS)); + if (fnControlService (service, SERVICE_CONTROL_STOP, &ss)) + { + // Ожидание останова + ret = m_bMSMessengerStopped = WaitForService ( + T_STOP_ERROR, service, + SERVICE_STOP_PENDING, SERVICE_STOPPED); + } + else + { + if (GetLastError () == ERROR_SERVICE_NOT_ACTIVE) + // Уже остановлен + ret = true; // m_bMSMessengerStopped = false + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + } + } + } + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + fnCloseServiceHandle (service); + } + else + { + if (GetLastError () == ERROR_SERVICE_DOES_NOT_EXIST) + // Такого сервиса нет - ок + ret = true; // m_bMSMessengerStopped = false + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + } + fnCloseServiceHandle (manager); + } + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + + return ret; +} + +// Разрешение запуска "Службы Сообщений" +bool messenger::Enable () +{ + bool ret = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | + SC_MANAGER_CONNECT | SC_MANAGER_LOCK); + if (manager) + { + // Блокировка менеджера + SC_LOCK lock = fnLockServiceDatabase( manager ); + if (lock) + { + // Открытие сервиса + SC_HANDLE service = fnOpenService ( manager, MESSENGER, + SERVICE_CHANGE_CONFIG ); + if (service) + { + // Установка автозапуска сервиса + if ( fnChangeServiceConfig( service, SERVICE_NO_CHANGE, + SERVICE_AUTO_START, SERVICE_NO_CHANGE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ) + ret = true; + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnCloseServiceHandle (service); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnUnlockServiceDatabase( lock ); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnCloseServiceHandle ( manager ); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + return ret; +} + +bool messenger::WaitForService (LPCTSTR reason, SC_HANDLE service, DWORD process, DWORD end) +{ + SERVICE_STATUS ss = { 0 }; + if (fnQueryServiceStatus (service, &ss)) + { + DWORD dwStartTickCount = GetTickCount(); + DWORD dwOldCheckPoint = ss.dwCheckPoint; + while (ss.dwCurrentState == process) { + // Do not wait longer than the wait hint. A good interval is + // one tenth the wait hint, but no less than 1 second and no + // more than 10 seconds. + DWORD dwWaitTime = ss.dwWaitHint / 10; + if (dwWaitTime < 1000) + dwWaitTime = 1000; + else + if (dwWaitTime > 10000) + dwWaitTime = 10000; + Sleep (dwWaitTime); + // Check the status again. + if (!fnQueryServiceStatus (service, &ss)) + { + WarningBox (NULL, GetLastError (), reason); + return false; + } + if (ss.dwCurrentState == end) + break; + if (ss.dwCheckPoint > dwOldCheckPoint) + { + // The service is making progress. + dwStartTickCount = GetTickCount(); + dwOldCheckPoint = ss.dwCheckPoint; + } else + { + if (GetTickCount() - dwStartTickCount > ss.dwWaitHint) + { + WarningBox (NULL, 0, _T("%s\r\n%s"), TranslateT ("No progress"), reason); + return false; + } + } + } + if (ss.dwCurrentState == end) + return true; + WarningBox (NULL, 0, _T("%s\r\n%s"), TranslateT ("Unexpected service status change"), reason); + } + else + WarningBox (NULL, GetLastError (), reason); + return false; +} + +bool messenger::SendMessengerMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + if ( pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT || ! fnNetMessageBufferSend ) + { + err = ERROR_NOT_SUPPORTED; + return false; + } + + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = NERR_NameNotFound; + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = NERR_NameNotFound; + return false; + } + + // Нет разницы группа это или компьютер + // bool bGroup = IsGroup( hContact ); + + LPWSTR wto = mir_t2u( sTo ); + LPWSTR wfrom = mir_t2u( sFrom ); + LPWSTR wmsg = mir_t2u( msg ); + err = fnNetMessageBufferSend( NULL, wto, wfrom, (LPBYTE)wmsg, + lstrlen( msg ) * sizeof( WCHAR ) ); + mir_free( wto ); + mir_free( wfrom ); + mir_free( wmsg ); + + return ( err == NERR_Success ); +} diff --git a/plugins/!NotAdopted/WinPopup/messenger.h b/plugins/!NotAdopted/WinPopup/messenger.h new file mode 100644 index 0000000000..582b4d554c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messenger.h @@ -0,0 +1,54 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +class messenger +{ +public: + messenger (); + ~messenger (); + + bool Create (BOOL start); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool () const; + + bool Start (); // Запуск "Службы Сообщений" + bool Stop (); // Останов "Службы Сообщений" + bool Enable (); // Разрешение запуска "Службы Сообщений" + + bool SendMessengerMessage(HANDLE hContact, LPCTSTR msg, DWORD& err); + +protected: + HANDLE m_MonitorTerm; // Событие для остановки + HANDLE m_Monitor; // Периодическая проверка + DWORD m_ID; // ID процесса CSRSS.EXE + bool m_bMSMessengerStopped; // Флаг показывающий был ли остановлен + // MS Messenger с помощью функции Stop() + + void Monitor (); + static BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lParam); + static void MonitorThread (LPVOID lpParameter); + static bool WaitForService (LPCTSTR reason, SC_HANDLE service, DWORD process, DWORD end); +}; + +extern messenger pluginMessenger; // Прием/отправка сообщений через Messenger diff --git a/plugins/!NotAdopted/WinPopup/netbios.cpp b/plugins/!NotAdopted/WinPopup/netbios.cpp new file mode 100644 index 0000000000..21a0cfd3c4 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios.cpp @@ -0,0 +1,1065 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "netbios.h" +#include "smbconst.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +netbios pluginNetBIOS; // Прием/отправка сообщений через NetBIOS + +// Макрос печати NetBIOS-имени +#define NETBIOS_NAME_TRACE(bb,mm,nn) mir_snprintf((bb),(mm),"%s #%d %02x %c %s", \ + (nn.GetANSIFullName()), (nn.name_num), (nn.name_flags), \ + (((nn.name_flags & GROUP_NAME) == GROUP_NAME) ? 'G' : 'U'), \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == REGISTERING) ? "REGISTERING" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == REGISTERED) ? "REGISTERED" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DEREGISTERED) ? "DEREGISTERED" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DUPLICATE) ? "DUPLICATE" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DUPLICATE_DEREG) ? "DUPLICATE_DEREG" : \ + "UNKNOWN")))))); + +// NetBIOS commands +static const struct +{ + UCHAR code; // NetBIOS command code + LPCSTR name; // NetBIOS command description +} +NCBCommands[] = +{ + { NCBCALL, "CALL" }, + { NCBLISTEN, "LISTEN" }, + { NCBHANGUP, "HANG UP" }, + { NCBSEND, "SEND" }, + { NCBRECV, "RECEIVE" }, + { NCBRECVANY, "RECEIVE ANY" }, + { NCBCHAINSEND, "CHAIN SEND" }, + { NCBDGSEND, "SEND DATAGRAM" }, + { NCBDGRECV, "RECEIVE DATAGRAM" }, + { NCBDGSENDBC, "SEND BROADCAST DATAGRAM" }, + { NCBDGRECVBC, "RECEIVE BROADCAST DATAGRAM" }, + { NCBADDNAME, "ADD NAME" }, + { NCBDELNAME, "DELETE NAME" }, + { NCBRESET, "RESET" }, + { NCBASTAT, "ADAPTER STATUS" }, + { NCBSSTAT, "SESSION STATUS" }, + { NCBCANCEL, "CANCEL" }, + { NCBADDGRNAME, "ADD GROUP NAME" }, + { NCBENUM, "ENUMERATE LANA NUMBERS" }, + { NCBUNLINK, "UNLINK" }, + { NCBSENDNA, "SEND NO ACK" }, + { NCBCHAINSENDNA, "CHAIN SEND NO ACK" }, + { NCBLANSTALERT, "LAN STATUS ALERT" }, + { NCBACTION, "ACTION" }, + { NCBFINDNAME, "FIND NAME" }, + { NCBTRACE, "TRACE" }, + { 0, NULL } +}; + +// NetBIOS errors +static const struct +{ + UCHAR error; // NetBIOS error code + LPCSTR message; // NetBIOS error message +} +NRCErrors [] = +{ + { NRC_GOODRET, "The operation succeeded." }, + { NRC_BUFLEN, "An illegal buffer length was supplied." }, + { NRC_ILLCMD, "An illegal command was supplied." }, + { NRC_CMDTMO, "The command was timed out." }, + { NRC_INCOMP, "The message was incomplete. The application is to issue another command." }, + { NRC_BADDR, "The buffer address was illegal." }, + { NRC_SNUMOUT, "The session number was out of range." }, + { NRC_NORES, "No resource was available." }, + { NRC_SCLOSED, "The session was closed." }, + { NRC_CMDCAN, "The command was canceled." }, + { NRC_DUPNAME, "A duplicate name existed in the local name table." }, + { NRC_NAMTFUL, "The name table was full." }, + { NRC_ACTSES, "The command finished; the name has active sessions and is no longer registered." }, + { NRC_LOCTFUL, "The local session table was full." }, + { NRC_REMTFUL, "The remote session table was full. The request to open a session was rejected." }, + { NRC_ILLNN, "An illegal name number was specified." }, + { NRC_NOCALL, "The system did not find the name that was called." }, + { NRC_NOWILD, "Wildcards are not permitted in the ncb_name member." }, + { NRC_INUSE, "The name was already in use on the remote adapter." }, + { NRC_NAMERR, "The name was deleted." }, + { NRC_SABORT, "The session ended abnormally." }, + { NRC_NAMCONF, "A name conflict was detected." }, + { NRC_IFBUSY, "The interface was busy." }, + { NRC_TOOMANY, "Too many commands were outstanding; the application can retry the command later." }, + { NRC_BRIDGE, "The ncb_lana_num member did not specify a valid network number." }, + { NRC_CANOCCR, "The command finished while a cancel operation was occurring." }, + { NRC_CANCEL, "The NCBCANCEL command was not valid; the command was not canceled." }, + { NRC_DUPENV, "The name was defined by another local process." }, + { NRC_ENVNOTDEF, "The environment was not defined." }, + { NRC_OSRESNOTAV, "Operating system resources were exhausted. The application can retry the command later." }, + { NRC_MAXAPPS, "The maximum number of applications was exceeded." }, + { NRC_NOSAPS, "No service access points (SAPs) were available for NetBIOS." }, + { NRC_NORESOURCES, "The requested resources were not available." }, + { NRC_INVADDRESS, "The NCB address was not valid." }, + { NRC_INVDDID, "The NCB DDID was invalid." }, + { NRC_LOCKFAIL, "The attempt to lock the user area failed." }, + { NRC_OPENERR, "An error occurred during an open operation being performed by the device driver." }, + { NRC_SYSTEM, "A system error occurred." }, + { NRC_PENDING, "An asynchronous operation is not yet finished." }, + { 0, NULL } +}; + +LPCSTR GetNetbiosCommand(UCHAR command) +{ + command &= 0x7f; // strip ASYNCH bit + for ( int i = 0; NCBCommands[ i ].name; ++i ) + if ( NCBCommands[ i ].code == command ) + return NCBCommands[ i ].name; + return "UNKNOWN"; +} + +LPCSTR GetNetbiosError(UCHAR err) +{ + for ( int i = 0; NRCErrors [ i ].message; ++i ) + if ( NRCErrors [ i ].error == err ) + return NRCErrors [ i ].message; + return "Unknown error."; +} + +UCHAR NetbiosEx(NCB* pNCB) +{ + UCHAR command = pNCB->ncb_command; + UCHAR ret = Netbios( pNCB ); + //if ( ret != NRC_GOODRET ) + if ( ret == pNCB->ncb_retcode ) + { + LOG( "NetBIOS call 0x%02x \"%s\" result: 0x%02x \"%s\"", + command, GetNetbiosCommand( command ), + ret, GetNetbiosError( ret ) ); + } + else + { + LOG( "NetBIOS call 0x%02x \"%s\" result: 0x%02x \"%s\", return: 0x%02x \"%s\"", + command, GetNetbiosCommand( command ), + ret, GetNetbiosError( ret ), + pNCB->ncb_retcode, GetNetbiosError( pNCB->ncb_retcode ) ); + } + return ret; +} + +// Определение NCB не на стеке +// KB317437: "NetBIOS Listen May Return a Damaged NCB Structure" +// The _NCB structure that is returned when a NetBIOS Listen call completes may have a changed server name offset. +class CNCB +{ +public: + CNCB() : + m_buf( VirtualAlloc( NULL, 4096, MEM_COMMIT, PAGE_READWRITE ) ) + { + } + + ~CNCB() + { + if ( m_buf ) + { + VirtualFree( m_buf, 0, MEM_RELEASE ); + } + } + + inline operator bool() const + { + return ( m_buf != NULL ); + } + + inline operator NCB*() const + { + return (NCB*)m_buf; + } + + inline NCB* operator->() const + { + return (NCB*)m_buf; + } + +protected: + void* m_buf; +}; + +//////////////////////////////////////////////////////////////////////// +// Class netbios + +netbios::netbios () : + m_initialized( false ) +{ + ZeroMemory (&m_le, sizeof (m_le)); +} + +netbios::~netbios () +{ + Destroy (); +} + +bool netbios::Create (BOOL registration) +{ + CLock oLock( m_csData ); + + if ( ! m_initialized ) + { + // Перечисление адаптеров + if ( EnumLanas( m_le ) == NRC_GOODRET ) + { + // Сброс адаптеров + for ( UCHAR i = 0; i < m_le.length; i++ ) + { + ResetLana( m_le.lana [i] ); + } + + // Регистрация имён, если нужна + if ( registration ) + { + Register (); + } + } + + m_initialized = true; + } + + return m_initialized; +} + +void netbios::AskForDestroy() +{ + CLock oLock( m_csData ); + + // Запрос на дерегистрацию имён + for ( size_t i = 0; i < m_names.GetCount (); ++i ) + m_names [i]->AskForDestroy(); +} + +void netbios::Destroy () +{ + CLock oLock( m_csData ); + + if ( m_initialized ) + { + Deregister(); + m_initialized = false; + } +} + +unsigned char* netbios::SetSMBHeaderCommand (unsigned char* szHeader, BYTE iCommandCode, size_t iBufferLen) +{ + ZeroMemory (szHeader, iBufferLen); + *(DWORD*)szHeader = SMB_MAGIC; + szHeader [4] = iCommandCode; + return (szHeader + SMB_HEADER_SIZE); +} + +netbios::operator bool() const +{ + return m_initialized; +} + +bool netbios::SendNetBIOSMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + // Created by Ilja Razinkov (also known as IPv6), 2002, IPv6Intendo@yandex.ru + // Keep this comment if you redistribute this file + + //Схема отправки большого NB-сообщения: + //1) Шлется D5. Текст сообщения: + //- 00, длина остатка A (1 байт), 00 (3 байта) + //- остаток A. 04, строка КТО, 00, 04, строка КОМУ, 00 + //в ответ приходит КОД СООБЩЕНИЯ (2 байта) и 00,00,00 (всего 5 байт), с D5 в заголовке + // + //2) Шлется D7. Текст сообщения: + //- КОД СООБЩЕНИЯ (2 байта), 00, длина остатка (A+B) (1 байт), 00 (всего 5 байт) + //- остаток A. 01, длина остатка B, 00 (3 байта) + //- остаток B. очередной кусок посланного СООБЩЕНИЯ + //в ответ приходит пустое сообщение (с 3мя 0-лями), с D7 в заголовке + // + //3) Пункт 2 повторяется пока не будет отослано все СООБЩЕНИЕ + // + //4) Шлется D6.Текст сообщения: + //- КОД СООБЩЕНИЯ (2 байта), 00, 00, 00 (всего 5 байт) + //в ответ приходит пустое сообщение (с 3мя 0-лями), с D6 в заголовке + + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + bool bGroup = IsGroup( hContact ); + + // Подготовка данных + CStringA sMessage( msg ); + sMessage.AnsiToOem(); + sMessage.Replace( "\r\n", "\x14" ); // -> <14> + sMessage.Replace( "\r", "\x14" ); // -> <14> + sMessage.Replace( "\n", "\x14" ); // -> <14> + netbios_name nname_To( sTo, 3, bGroup ); + netbios_name nname_From( sFrom, 3 ); + + // Поиск адаптера + UCHAR lana = 0; + if ( ! FindNameLana( nname_To, lana ) ) + { + LOG ("SendNetBIOSMessage : Unknown name"); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + // Коннект к клиенту + UCHAR lsn = 0; + err = Call (lana, nname_From, nname_To, lsn); + if (err != NRC_GOODRET) + { + LOG ("SendNetBIOSMessage : Cannot connect" ); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + UCHAR SMBBlock [168] = { 0 }; + UCHAR* szSMBData = NULL; + UCHAR iFromLen = (UCHAR)nname_From.GetLength (); + UCHAR iToLen = (UCHAR)nname_To.GetLength (); + UCHAR iHiMsgCode = 0, iLoMsgCode = 0; + + // 1. Шлем заголовок + LOG ( "SendNetBIOSMessage : Send start of multi-block message" ); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendstrt, sizeof (SMBBlock)); + UCHAR dwD5ALength = (UCHAR)( 1 + iFromLen + 2 + iToLen + 1 ); + szSMBData[1] = dwD5ALength; + szSMBData[3] = 4; + szSMBData[4+iFromLen+1] = 4; + CopyMemory ( szSMBData + 4, nname_From.netbiosed.name, iFromLen ); + CopyMemory ( szSMBData + 4 + iFromLen + 2, nname_To.netbiosed.name, iToLen ); + UCHAR dwD5Length = (UCHAR)( 3 + dwD5ALength ); + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + dwD5Length)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t start session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Ждем подтверждения + WORD length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (start session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + iHiMsgCode=SMBBlock[SMB_HEADER_SIZE]; + iLoMsgCode=SMBBlock[SMB_HEADER_SIZE+1]; + + // 2. Шлем сообщение (кусочками) + UCHAR dwD7BLength = 0; + for (int iSendedBytes = 0; iSendedBytes < sMessage.GetLength (); iSendedBytes += dwD7BLength) + { + dwD7BLength = sizeof (SMBBlock) - (5 + 3 + SMB_HEADER_SIZE); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendtxt, sizeof (SMBBlock)); + if (iSendedBytes + dwD7BLength > sMessage.GetLength ()) + dwD7BLength = (UCHAR)( sMessage.GetLength () - iSendedBytes ); + szSMBData[0]=iHiMsgCode; + szSMBData[1]=iLoMsgCode; + szSMBData[3]=(UCHAR)( dwD7BLength + 3 ); + szSMBData[5]=1; + szSMBData[6]=dwD7BLength; + CopyMemory (szSMBData + 5 + 3, (LPCSTR) sMessage + iSendedBytes, dwD7BLength); + LOG( "SendNetBIOSMessage : Send text (%u-%u bytes) of multi-block message" , iSendedBytes, iSendedBytes + dwD7BLength - 1); + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + 5 + 3 + dwD7BLength)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t use session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + // Ждем подтверждения + length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (use session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + } + + // 3. Шлем извещение что все отослано + LOG ( "SendNetBIOSMessage : Send and of multi-block message" ); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendend, sizeof (SMBBlock)); + DWORD dwD6Length=5; + szSMBData[0]=iHiMsgCode; + szSMBData[1]=iLoMsgCode; + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + dwD6Length)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t close session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Ждем подтверждения + length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (close session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Закрываем сессию + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 1, FACILITY_NETBIOS, NRC_GOODRET ); + return true; +} + +ip netbios::FindNameIP (LPCTSTR szName, UCHAR type) +{ + // Поиск имени + netbios_name nname( szName, type ); + ip addr = INADDR_NONE; + FIND_NAME_BLOCK fn = { 0 }; + for (UCHAR i = 0; i < m_le.length; i++) { + UINT uReturn = FindName (nname, m_le.lana [i], fn); + if (uReturn == NRC_GOODRET) { + LOG( "Found %s at %u boxes. LAN #%u IP: %u.%u.%u.%u", nname.GetANSIFullName(), + fn.fnb_header.node_count, m_le.lana [i], + fn.fnb_Names [0].source_addr[2], + fn.fnb_Names [0].source_addr[3], + fn.fnb_Names [0].source_addr[4], + fn.fnb_Names [0].source_addr[5]); + addr = ((ip)fn.fnb_Names [0].source_addr[5]) | + ((ip)fn.fnb_Names [0].source_addr[4] << 8) | + ((ip)fn.fnb_Names [0].source_addr[3] << 16) | + ((ip)fn.fnb_Names [0].source_addr[2] << 24); + break; + } + } + return addr; +} + +void netbios::GetRegisteredNames (netbios_name_list& names) +{ + CLock oLock( m_csData ); + + for (size_t i = 0; i < m_names.GetCount (); ++i) + names.AddTail (*m_names [i]); +} + +bool netbios::GetNames(netbios_name_list& names, LPCTSTR name, bool bGroup) +{ + // Получение имен + ADAPTER_STATUS_BLOCK astat = { 0 }; + netbios_name nname( name, 0, bGroup ); + UINT uReturn = NRC_GOODRET; + for (UCHAR i = 0; i < m_le.length; i++) + { + uReturn = GetAdapterStatus (nname, m_le.lana [i], astat); + if (uReturn == NRC_GOODRET) + { + for (int j = 0; j < astat.asb_header.name_count; ++j) + { + names.AddTail (netbios_name (astat.asb_Names [j], m_le.lana [i])); + } + } + } + return (uReturn == NRC_GOODRET); +} + +netbios_name* netbios::GetName (const netbios_name& nname) +{ + CLock oLock( m_csData ); + + netbios_name* ret = NULL; + for (size_t i = 0; i < m_names.GetCount (); ++i) + { + if ( nname == *(m_names [i]) ) + { + // Похожее имя обнаружено + ret = m_names [i]; + break; + } + } + + return ret; +} + +bool netbios::FindNameLana(const netbios_name& nname, UCHAR& lana) +{ + // Получение имен + ADAPTER_STATUS_BLOCK astat = {}; + for (UCHAR i = 0; i < m_le.length; i++) + { + UINT uReturn = GetAdapterStatus (nname, m_le.lana [i], astat); + if ( uReturn == NRC_GOODRET ) + { + for ( int j = 0; j < astat.asb_header.name_count; ++j ) + { + if (nname == astat.asb_Names [j]) + { + // Имя обнаружено + LOG ( "FindNameLana : Name \"%s\" found at #%d", nname.GetANSIFullName(), m_le.lana [i]); + lana = m_le.lana [i]; + return true; + } + } + } + LOG( "FindNameLana : Name \"%s\" not found", nname.GetANSIFullName()); + } + + return false; +} + +bool netbios::GetMAC (UCHAR lana, CString& mac) +{ + ADAPTER_STATUS_BLOCK astat = { 0 }; + netbios_name nname; + UINT uReturn = GetAdapterStatus (nname, lana, astat); + if (uReturn == NRC_GOODRET) { + mac.Format (_T("%02x:%02x:%02x:%02x:%02x:%02x"), + astat.asb_header.adapter_address[0], + astat.asb_header.adapter_address[1], + astat.asb_header.adapter_address[2], + astat.asb_header.adapter_address[3], + astat.asb_header.adapter_address[4], + astat.asb_header.adapter_address[5]); + } else + mac.Empty (); + return true; +} + +UCHAR netbios::FindName (const netbios_name& nname, UCHAR lana, FIND_NAME_BLOCK& fn) +{ + ZeroMemory (&fn, sizeof (FIND_NAME_BLOCK)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBFINDNAME; + ncb->ncb_lana_num = lana; + CopyMemory( ncb->ncb_callname, nname.netbiosed.name, NCBNAMSZ ); + ncb->ncb_buffer = reinterpret_cast (&fn); + ncb->ncb_length = sizeof (FIND_NAME_BLOCK); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::GetAdapterStatus (const netbios_name& nname, UCHAR lana, ADAPTER_STATUS_BLOCK& astat) +{ + ZeroMemory (&astat, sizeof (ADAPTER_STATUS_BLOCK)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBASTAT; + ncb->ncb_lana_num = lana; + CopyMemory( ncb->ncb_callname, nname.netbiosed.name, NCBNAMSZ ); + ncb->ncb_buffer = reinterpret_cast (&astat); + ncb->ncb_length = sizeof (ADAPTER_STATUS_BLOCK); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::EnumLanas (LANA_ENUM& le) +{ + // Перечисление адаптеров + ZeroMemory (&le, sizeof (LANA_ENUM)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBENUM; + ncb->ncb_buffer = (PUCHAR) ≤ + ncb->ncb_length = sizeof (LANA_ENUM); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::ResetLana (UCHAR lana) +{ + // Сброс адаптера + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBRESET; + ncb->ncb_lana_num = lana; + ncb->ncb_callname [0] = 20; // maximum sessions + ncb->ncb_callname [2] = 30; // maximum names + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Hangup (UCHAR lana, UCHAR lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBHANGUP; + ncb->ncb_lana_num = lana; + ncb->ncb_lsn = lsn; + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Send (UCHAR lana, UCHAR lsn, unsigned char* data, WORD length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_lana_num = lana; + ncb->ncb_command = NCBSEND; + ncb->ncb_lsn = lsn; + ncb->ncb_length = length; + ncb->ncb_buffer = data; + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 10; // 10 * 500 ms = 5 s + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Recv (UCHAR lana, UCHAR lsn, unsigned char* data, WORD& length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBRECV; + ncb->ncb_lana_num = lana; + ncb->ncb_lsn = lsn; + ncb->ncb_length = length; + ncb->ncb_buffer = data; + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 10; // 10 * 500 ms = 5 s + NetbiosEx (ncb); + length = ncb->ncb_length; + return ncb->ncb_retcode; +} + +UCHAR netbios::Stat (const netbios_name& nname, SESSION_INFO_BLOCK* psibSession) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBSSTAT; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_buffer = (unsigned char*)psibSession; + ncb->ncb_length = sizeof (SESSION_INFO_BLOCK); + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Listen (const netbios_name& nname, UCHAR& lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + CopyMemory (ncb->ncb_callname, SMB_ANY_NAME, NCBNAMSZ); + ncb->ncb_command = NCBLISTEN; + ncb->ncb_num = nname.netbiosed.name_num; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 2; // 2 * 500 ms = 1 s + NetbiosEx (ncb); + lsn = ncb->ncb_lsn; + return ncb->ncb_retcode; +} + +UCHAR netbios::AddName (netbios_name& nname) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = (UCHAR)( nname.IsGroupName() ? NCBADDGRNAME : NCBADDNAME ); + ncb->ncb_lana_num = nname.GetLana(); + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + nname.netbiosed.name_num = ncb->ncb_num; + return ncb->ncb_retcode; +} + +UCHAR netbios::DeleteName (const netbios_name& nname) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBDELNAME; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_num = nname.netbiosed.name_num; + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::SendDatagram (const netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory( ncb->ncb_name, nname_from.netbiosed.name, NCBNAMSZ ); + CopyMemory( ncb->ncb_callname, nname_to.netbiosed.name, NCBNAMSZ ); + ncb->ncb_command = NCBDGSEND; + ncb->ncb_num = nname_from.netbiosed.name_num; + ncb->ncb_lana_num = nname_from.GetLana(); + ncb->ncb_buffer = data; + ncb->ncb_length = length; + + CLock oLock( m_csNetBIOS ); + Sleep( 100 ); + + NetbiosEx (ncb); + + return ncb->ncb_retcode; +} + +UCHAR netbios::RecvDatagram (netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD& length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory (ncb->ncb_name, nname_to.netbiosed.name, NCBNAMSZ); + ncb->ncb_command = NCBDGRECV; + ncb->ncb_num = nname_to.netbiosed.name_num; + ncb->ncb_lana_num = nname_to.GetLana(); + ncb->ncb_buffer = data; + ncb->ncb_length = length; + NetbiosEx (ncb); + nname_from = ncb->ncb_callname; + length = ncb->ncb_length; + return ncb->ncb_retcode; +} + +UCHAR netbios::Call (UCHAR lana, const netbios_name& nname_from, const netbios_name& nname_to, UCHAR& lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory( ncb->ncb_name, nname_from.netbiosed.name, NCBNAMSZ ); + CopyMemory( ncb->ncb_callname, nname_to.netbiosed.name, NCBNAMSZ ); + ncb->ncb_lana_num = lana; + ncb->ncb_rto = ncb->ncb_sto = 10; // 5 секунд + ncb->ncb_command = NCBCALL; + NetbiosEx (ncb); + lsn = ncb->ncb_lsn; + return ncb->ncb_retcode; +} + +bool netbios::AskAway(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = sizeof( WORD ) + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETAWAYMESSAGE; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Away\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendAway(netbios_name& nname_from, const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + CString sAwayT; + pluginStatusMessage.Lookup( pluginCurrentStatus, sAwayT ); + CT2A sAwayA( sAwayT ); + WORD len = (WORD)min( lstrlenA( sAwayA ), 250 ); + + // Сборка пакета + WORD packet_size = (WORD)( 2 + 1 + 4 + len ); + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet [ 2 ] = SM_SENDAWAYMESSAGE; + *(__int32*)( packet + 2 + 1 ) = 0; + CopyMemory( packet + 2 + 1 + 4, sAwayA, len ); + + LOG( "Send \"Away\" answer from \"%s\" to \"%s\" : \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName(), (LPCSTR)sAwayA ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::AskStatus(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETSTATUS; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Status\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendStatus(netbios_name& nname_from, const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1 + 4; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet [ 2 ] = SM_SENDSTATUS; + *(__int32*)( packet + 2 + 1 ) = (__int32)pluginCurrentStatus; + + LOG( "Send \"Status\" answer from \"%s\" to \"%s\" : \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName(), STATUS2TEXT(pluginCurrentStatus) ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::BroadcastStatus() +{ + bool ret = false; + if ( m_initialized ) + { + for (UCHAR i = 0; i < m_le.length; i++) + { + netbios_name nname_to( MNS_STATUS, 0xab, true, m_le.lana [i] ); + netbios_name* nname = GetName( + netbios_name ( pluginMachineName, 0x03, false, m_le.lana [i] ) ); + if ( nname ) + ret = SendStatus( *nname, nname_to ) || ret; + } + } + return ret; +} + +bool netbios::AskAvatar(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETAVATAR; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Avatar\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendAvatar(netbios_name& nname_from, const netbios_name& nname_to) +{ + if ( ! m_initialized ) + return false; + + if ( ! ServiceExists( MS_AV_GETMYAVATAR ) ) + // Нет аватарского плагина + return false; + + // Запрос аватара протокола + AVATARCACHEENTRY* pAvatar = (AVATARCACHEENTRY*)CallService( + MS_AV_GETMYAVATAR, 0, (LPARAM)modname ); + if ( ! pAvatar ) + // Запрос общего аватара + pAvatar = (AVATARCACHEENTRY*)CallService( MS_AV_GETMYAVATAR, 0, (LPARAM)"" ); + if ( ! pAvatar || pAvatar->cbSize < sizeof( AVATARCACHEENTRY ) ) + // Нет аватара + return false; + + CString sFilename = (LPCTSTR)CA2T( pAvatar->szFilename ); + + CAtlFile oAvatarFile; + if ( FAILED( oAvatarFile.Create( sFilename, GENERIC_READ, + FILE_SHARE_READ, OPEN_EXISTING ) ) ) + // Файл не найден + return false; + + ULONGLONG avatar_size = 0; + if ( FAILED( oAvatarFile.GetSize( avatar_size ) ) || + avatar_size < 16 || avatar_size > MAX_AVATAR_SIZE ) + // Слишком маленький или слишком большой файл + return false; + + bool ret = false; + + // Сборка статусного пакета + WORD packet_size = (WORD)( 2 + 1 + avatar_size ); + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_SENDAVATAR; + + // Чтение аватара из файла + if ( SUCCEEDED( oAvatarFile.Read( packet + 2 + 1, avatar_size ) ) ) + { + LOG( "Send \"Avatar\" answer from \"%s\" to \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName() ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + } + + mir_free( packet ); + } + + return ret; +} + +bool netbios::Register () +{ + CLock oLock( m_csData ); + + bool ret = false; + + // Удаление имён, если они есть + for (size_t i = 0; i < m_names.GetCount (); ++i) + delete m_names [i]; + m_names.RemoveAll (); + + // Добавление имен на каждом адаптере + for (UCHAR i = 0; i < m_le.length; i++) + { + // COMPUTER <01> U + netbios_name *pnn1 = + DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE) ? + new netbios_name ( pluginMachineName, 0x01, false, m_le.lana [i]) : NULL; + if (pnn1) + m_names.Add (pnn1); + + // COMPUTER <03> U + netbios_name *pnn2 = + DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE) ? + new netbios_name ( pluginMachineName, 0x03, false, m_le.lana [i]) : NULL; + if (pnn2) + m_names.Add (pnn2); + + // USER <03> U + netbios_name *pnn3 = + DBGetContactSettingByte (NULL, modname, "RegisterUser", TRUE) ? + new netbios_name ( pluginUserName, 0x03, false, m_le.lana [i]) : NULL; + if (pnn3) { + // Проверка на совпадение имени пользователя и имени компьютера + if (pnn2 && *pnn3 == *pnn2) + // Имена совпадают + delete pnn3; + else + m_names.Add (pnn3); + } + + // MNS_STATUS G + netbios_name *pnn4 = + DBGetContactSettingByte (NULL, modname, "RegisterStatus", TRUE) ? + new netbios_name (MNS_STATUS, 0xab, true, m_le.lana [i]) : NULL; + if ( pnn4 ) + m_names.Add( pnn4 ); + } + + // Регистрация имен + for ( size_t i = 0; i < m_names.GetCount (); ++i ) + { + if ( m_names [i]->Register() ) + { + ret = true; + } + } + + return ret; +} + +// Дерегистрация NetBIOS-имен +void netbios::Deregister () +{ + CLock oLock( m_csData ); + + // Дерегистрация имён + for (size_t i = 0; i < m_names.GetCount (); ++i) + m_names [i]->Destroy(); + + // Удаление имён + for (size_t i = 0; i < m_names.GetCount (); ++i) + delete m_names [i]; + m_names.RemoveAll (); +} diff --git a/plugins/!NotAdopted/WinPopup/netbios.h b/plugins/!NotAdopted/WinPopup/netbios.h new file mode 100644 index 0000000000..a56294cb14 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios.h @@ -0,0 +1,134 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +#include "netbios_name.h" + +const DWORD SMB_MAGIC = 0x424d53ff; // 0xff 'S' 'M' 'B' +const WORD SM_MAGIC = 0x4d53; // 'S' 'M' + +// NetBIOS datagrams: +// (obsolete) +const UCHAR SM_CHANGESTATUS = 0x01; +// Status request: 'S' 'M' 0x02 +const UCHAR SM_GETSTATUS = 0x02; +// Status answer: 'S' 'M' 0x03 status(i32) +const UCHAR SM_SENDSTATUS = 0x03; +// Away message request: 'S' 'M' 0x04 +const UCHAR SM_GETAWAYMESSAGE = 0x04; +// Away message answer: 'S' 'M' 0x05 0x00(i32) message(ASCII) +const UCHAR SM_SENDAWAYMESSAGE = 0x05; +// Avatar request: 'S' 'M' 0x06 +const UCHAR SM_GETAVATAR = 0x06; +// Avatar answer: 'S' 'M' 0x07 avatar +const UCHAR SM_SENDAVATAR = 0x07; + +const LPCTSTR MNS_STATUS = _T("MNS_STATUS"); + +#define MAX_AVATAR_SIZE 65000 // Максимальный размер файла аватара (байт) + +#pragma pack (push, 1) + +typedef struct _FIND_NAME_BLOCK +{ + FIND_NAME_HEADER fnb_header; + FIND_NAME_BUFFER fnb_Names [256]; +} FIND_NAME_BLOCK, *PFIND_NAME_BLOCK; + +typedef struct _ADAPTER_STATUS_BLOCK +{ + ADAPTER_STATUS asb_header; + NAME_BUFFER asb_Names [NCBNAMSZ]; +} ADAPTER_STATUS_BLOCK, *PADAPTER_STATUS_BLOCK; + +#pragma pack (pop) + +class netbios +{ +public: + netbios(); + ~netbios(); + + bool Create (BOOL registration); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool() const; + + bool SendNetBIOSMessage (HANDLE hContact, LPCTSTR msg /* ANSI */, DWORD& err); + ip FindNameIP (LPCTSTR szName /* ANSI */, UCHAR type = 3); + void GetRegisteredNames (netbios_name_list& names); + bool GetNames (netbios_name_list& names, LPCTSTR name /* ANSI */, bool bGroup); + + // Получение имени из списка по указанному имени + netbios_name* GetName (const netbios_name& nname); + + // Поиск номера адаптера через который можно достучаться до указанного имени + bool FindNameLana (const netbios_name& nname, UCHAR& lana); + + bool GetMAC (UCHAR lana, CString& mac); + UCHAR FindName (const netbios_name& nname, UCHAR lana, FIND_NAME_BLOCK& fn); + UCHAR GetAdapterStatus (const netbios_name& nname, UCHAR lana, ADAPTER_STATUS_BLOCK& astat); + UCHAR EnumLanas (LANA_ENUM& le); + UCHAR ResetLana (UCHAR lana); + UCHAR Hangup (UCHAR lana, UCHAR lsn); + UCHAR Send (UCHAR lana, UCHAR lsn, unsigned char* data, WORD length); + UCHAR Recv (UCHAR lana, UCHAR lsn, unsigned char* data, WORD& length); + UCHAR Stat (const netbios_name& nname, SESSION_INFO_BLOCK* psibSession); + UCHAR Listen (const netbios_name& nname, UCHAR& lsn); + UCHAR AddName (netbios_name& nname); + UCHAR DeleteName (const netbios_name& nname); + UCHAR SendDatagram (const netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD length); + UCHAR RecvDatagram (netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD& length); + UCHAR Call (UCHAR lana, const netbios_name& nname_from, const netbios_name& nname_to, UCHAR& lsn); + unsigned char* SetSMBHeaderCommand (unsigned char* szHeader, BYTE iCommandCode, size_t iBufferLen); + + // Запрос эвей-сообщения + bool AskAway(const netbios_name& nname_to); + // Отправка эвей-сообщения + bool SendAway(netbios_name& nname_from, const netbios_name& nname_to); + // Запрос статуса + bool AskStatus(const netbios_name& nname_to); + // Отправка статуса + bool SendStatus(netbios_name& nname_from, const netbios_name& nname_to); + // Отправка статуса на всех адаптерах (от COMPUTER<03> U на MNS_STATUS G) + bool BroadcastStatus(); + // Запрос аватара + bool AskAvatar(const netbios_name& nname_to); + // Отправка аватара + bool SendAvatar(netbios_name& nname_from, const netbios_name& nname_to); + +protected: + bool m_initialized; // Флаг инициализации подсистемы NetBIOS + netbios_name_array m_names; // Все регистрируемые NetBIOS-имена для слушателя + LANA_ENUM m_le; // Список адаптеров + CComAutoCriticalSection m_csData; // Защита данных + CComAutoCriticalSection m_csNetBIOS; // Синхронизация NetBIOS + + bool Register (); // Регистрация всех NetBIOS-имен + void Deregister (); // Дерегистрация всех NetBIOS-имен +}; + +extern netbios pluginNetBIOS; // Прием/отправка сообщений через NetBIOS + +LPCSTR GetNetbiosCommand(UCHAR command); +LPCSTR GetNetbiosError(UCHAR err); +UCHAR NetbiosEx(NCB* pNCB); diff --git a/plugins/!NotAdopted/WinPopup/netbios_name.cpp b/plugins/!NotAdopted/WinPopup/netbios_name.cpp new file mode 100644 index 0000000000..ce3ad86ce7 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios_name.cpp @@ -0,0 +1,640 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "netbios.h" +#include "smbconst.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//////////////////////////////////////////////////////////////////////// +// Class netbios_name + +netbios_name::netbios_name(LPCTSTR n, UCHAR type, bool group, UCHAR lana) : + m_managed (false), + m_registered (false), + m_duplicated (false), + m_error (false), + m_lana (lana), + m_listener (NULL), + m_dgreceiver (NULL), + m_term (NULL) +{ + // Преобразование имени в NetBIOS-имя + int len = NCBNAMSZ - 1; + CT2A nA( n ); + LPCSTR src = (LPCSTR)nA; + LPSTR dst = (LPSTR)netbiosed.name; + for ( ; len && *src; --len, ++dst, ++src ) + *dst = *src; + for ( ; len; --len ) + *dst++ = ' '; + *dst = (CHAR)type; + CharUpperBuffA( (LPSTR)netbiosed.name, NCBNAMSZ - 1 ); + CharToOemBuffA( (LPSTR)netbiosed.name, (LPSTR)netbiosed.name, NCBNAMSZ - 1 ); + netbiosed.name_num = 0; + netbiosed.name_flags = (UCHAR)( group ? GROUP_NAME : UNIQUE_NAME ); + + original = GetANSIName(); +} + +netbios_name::netbios_name(const NAME_BUFFER& n, UCHAR lana) : + m_managed (false), + m_registered (false), + m_duplicated (false), + m_error (false), + m_lana (lana), + m_listener (NULL), + m_dgreceiver (NULL), + m_term (NULL) +{ + CopyMemory (&netbiosed, &n, sizeof (NAME_BUFFER)); + original = GetANSIName(); +} + +netbios_name& netbios_name::operator=(const netbios_name& n) +{ + _ASSERTE (m_managed == false); + m_managed = n.m_managed; + _ASSERTE (m_registered == false); + m_registered = n.m_registered; + _ASSERTE (m_duplicated == false); + m_duplicated = n.m_duplicated; + _ASSERTE (m_error == false); + m_error = n.m_error; + m_lana = n.m_lana; + _ASSERTE( m_listener == NULL ); + m_listener = NULL; + _ASSERTE( m_dgreceiver == NULL ); + m_dgreceiver = NULL; + _ASSERTE( m_term == NULL ); + m_term = NULL; + CopyMemory (&netbiosed, &n.netbiosed, sizeof( NAME_BUFFER )); + original = n.original; + return *this; +} + +netbios_name& netbios_name::operator= (const UCHAR* n) +{ + _ASSERTE (m_managed == false); + m_managed = false; + _ASSERTE (m_registered == false); + m_registered = false; + _ASSERTE (m_duplicated == false); + m_duplicated = false; + _ASSERTE (m_error == false); + m_error = false; + m_lana = 0; + _ASSERTE( m_listener == NULL ); + m_listener = NULL; + _ASSERTE( m_dgreceiver == NULL ); + m_dgreceiver = NULL; + _ASSERTE( m_term == NULL ); + m_term = NULL; + CopyMemory (netbiosed.name, n, NCBNAMSZ); + netbiosed.name_num = 0; + netbiosed.name_flags = UNIQUE_NAME; + original = GetANSIName(); + + return *this; +} + +bool netbios_name::operator== (const NAME_BUFFER& n) const +{ + return ( netbiosed.name [NCBNAMSZ - 1] == n.name [NCBNAMSZ - 1] ) && + ( ( netbiosed.name_flags & GROUP_NAME ) == ( n.name_flags & GROUP_NAME ) ) && + ( memcmp( netbiosed.name, n.name, NCBNAMSZ - 1 ) == 0 ); +} + +bool netbios_name::operator!= (const NAME_BUFFER& n) const +{ + return ! operator==( n ); +} + +bool netbios_name::operator== (const netbios_name& n) const +{ + return ( m_lana == n.m_lana ) && operator==( n.netbiosed ); +} + +bool netbios_name::operator!= (const netbios_name& n) const +{ + return ( m_lana != n.m_lana ) || operator!=( n.netbiosed ); +} + +bool netbios_name::Register() +{ + m_managed = true; + + UCHAR ret = AddName (); + LOG("Register NetBIOS name \"%s\" on lana %d num=%d : 0x%02x \"%s\"", GetANSIFullName(), m_lana, netbiosed.name_num, ret, GetNetbiosError( ret ) ); + m_registered = (ret == NRC_GOODRET); + m_duplicated = (ret == NRC_DUPNAME); + if ( ret != NRC_GOODRET && ret != NRC_DUPNAME ) + { + WarningBox (NULL, (DWORD)MAKE_HRESULT (0, FACILITY_NETBIOS, ret), + _T("%s: %s"), TranslateT ("Cannot register NetBIOS name"), (LPCTSTR)CA2T( GetANSIFullName() ) ); + } + + if (!m_term) + m_term = CreateEvent (NULL, TRUE, FALSE, NULL); + else + ResetEvent (m_term); + + if ( m_term && !m_listener ) + m_listener = (HANDLE)mir_forkthread( ListenerThread, this ); + + if ( m_term && !m_dgreceiver && + // NOTE: Под Win9x нельзя запускать ожидание датаграмм для имён-дубликатов + // т.к. потом невозможно выбить управление из функции Netbios() даже если + // разрегистрировать имя + !m_duplicated ) + { + m_dgreceiver = (HANDLE)mir_forkthread( DatagramReceiverThread, this ); + } + + return m_registered; +} + +void netbios_name::AskForDestroy() +{ + if (m_term) + SetEvent (m_term); +} + +void netbios_name::Destroy() +{ + // Запрос останова рабочего потока-слушателя + if ( m_term ) SetEvent( m_term ); + + // Удаление имени (если не удалить, то слушатель не завершиться) + UCHAR ret = DeleteName (); + LOG("Unregister NetBIOS name \"%s\" on lana %d num=%d : 0x%02x \"%s\"", GetANSIFullName(), m_lana, netbiosed.name_num, ret, GetNetbiosError( ret ) ); + m_registered = !(ret == NRC_GOODRET); + if ( m_duplicated ) + { + // Восстановление имени + m_duplicated = false; + + // NOTE: Восстанавливать не надо - проблем больше + // uReturn = AddName (); + // LOG("Restore NetBIOS name \"%s\" on lana %d : 0x%02x", GetANSIFullName(), m_lana, uReturn); + } + + // Ожидание, а затем принудительный останов + if ( m_listener ) + { + if ( m_term ) SetEvent( m_term ); + if (WaitForSingleObject (m_listener, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate NetBIOS listener!"); + TerminateThread (m_listener, 0); + } + m_listener = NULL; + } + + if ( m_dgreceiver ) + { + if ( m_term ) SetEvent( m_term ); + if (WaitForSingleObject (m_dgreceiver, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate NetBIOS datagram receiver!"); + TerminateThread (m_dgreceiver, 0); + } + m_dgreceiver = NULL; + } + + if ( m_term ) + { + CloseHandle (m_term); + m_term = NULL; + } +} + +CStringA netbios_name::GetANSIName() const +{ + CStringA sName; + LPSTR szName = sName.GetBuffer( NCBNAMSZ ); + CopyMemory( szName, (LPCSTR)netbiosed.name, NCBNAMSZ - 1 ); + szName[ NCBNAMSZ - 1 ] = 0; + sName.ReleaseBuffer(); + sName.Trim(); + sName.OemToAnsi(); + return sName; +} + +CStringA netbios_name::GetANSIFullName() const +{ + CStringA sType; + sType.Format( " <%02X>", GetType() ); + return original + sType; +} + +UCHAR netbios_name::GetType () const +{ + return netbiosed.name [NCBNAMSZ - 1]; +} + +bool netbios_name::IsGroupName () const +{ + return ((netbiosed.name_flags & GROUP_NAME) == GROUP_NAME); +} + +bool netbios_name::IsRegistered () const +{ + return m_registered; +} + +bool netbios_name::IsDuplicated () const +{ + return m_duplicated; +} + +bool netbios_name::IsError () const +{ + return m_error; +} + +bool netbios_name::IsOwnName () const +{ + return m_managed; +} + +UCHAR netbios_name::GetLana () const +{ + return m_lana; +} + +bool netbios_name::GetRealSender (UCHAR lsn, CStringA& sRealFrom) const +{ + sRealFrom.Empty (); + + SESSION_INFO_BLOCK sibSession = {}; + UCHAR dwInfoRes = pluginNetBIOS.Stat( *this, &sibSession ); + if ( dwInfoRes == NRC_GOODRET ) + { + for ( int i = 0; i < sibSession.sib_header.num_sess; i++ ) + { + if ( sibSession.sib_Names [i].lsn == lsn ) + { + // Наша сессия + const char* n = (const char*)sibSession.sib_Names [i].remote_name; + BYTE j = NCBNAMSZ - 2; + for ( ; j && ( n [ j ] == ' ' ); --j ); + sRealFrom.Append( n, j + 1 ); + sRealFrom.OemToAnsi(); + return true; + } + } + } + return false; +} + +size_t netbios_name::GetLength() const +{ + return (size_t)original.GetLength(); +} + +UCHAR netbios_name::AddName() +{ + return pluginNetBIOS.AddName( *this ); +} + +UCHAR netbios_name::DeleteName() +{ + return pluginNetBIOS.DeleteName( *this ); +} + +typedef struct _ReceiverData +{ + netbios_name* self; + UCHAR lsn; +} ReceiverData; + +void netbios_name::Listener() +{ + m_error = false; + while ( WaitForSingleObject( m_term, 50 ) == WAIT_TIMEOUT ) + { + UCHAR lsn = 0; + UCHAR ret = pluginNetBIOS.Listen( *this, lsn ); + if ( ret != NRC_GOODRET ) + { + LOG( "Listener : Closing \"%s\"", GetANSIFullName() ); + m_error = true; + break; + } + + LOG( "Listener : Got packet for \"%s\"", GetANSIFullName() ); + if ( ReceiverData* data = (ReceiverData*)mir_alloc( sizeof( ReceiverData ) ) ) + { + data->self = this; + data->lsn = lsn; + mir_forkthread( ReceiverThread, data ); + } + } +} + +void netbios_name::ListenerThread(LPVOID param) +{ + if ( netbios_name* pName = (netbios_name*)param ) + { + pName->Listener(); + pName->m_listener = NULL; + } +} + +void netbios_name::DatagramReceiver() +{ + UCHAR* SMBBlock = (UCHAR*)mir_alloc( 65536 ); + if ( ! SMBBlock ) + { + m_error = true; + return; + } + + m_error = false; + while ( WaitForSingleObject ( m_term, 50 ) == WAIT_TIMEOUT ) + { + ZeroMemory( SMBBlock, 65536 ); + + WORD iReadedBytes = 65535; + netbios_name nname_from; + UCHAR ret = pluginNetBIOS.RecvDatagram( nname_from, *this, SMBBlock, iReadedBytes ); + if ( ret != NRC_GOODRET ) + { + // Ошибка - выход + m_error = true; + break; + } + + nname_from.m_lana = m_lana; + + LOG( "Got datagram from \"%s\" to \"%s\"", nname_from.GetANSIFullName(), GetANSIFullName() ); + + // Свое собственное сообщение? + if ( IsItMe ( CA2T( nname_from.original ) ) ) + { + LOG( "DatagramReceiver : Ignoring my datagram" ); + continue; + } + + // Обработка датаграмм + if ( iReadedBytes > 2 && *(WORD*)SMBBlock == SM_MAGIC ) + { + UCHAR iMsgType = SMBBlock[ 2 ]; + switch ( iMsgType ) + { + case SM_GETSTATUS: + // Отвечаем своим статусом + LOG( "DatagramReceiver : It's status request" ); + pluginNetBIOS.SendStatus( *this, nname_from ); + break; + + case SM_SENDSTATUS: + // Находим контакт и ставим его статус + if ( iReadedBytes == 2 + 1 + 4 ) + { + HANDLE hContact = GetContact( CA2T( nname_from.original ) ); + if ( hContact ) + { + LOG( "DatagramReceiver : It's status answer" ); + SetContactStatus( hContact, *(__int32*)(SMBBlock + 2 + 1), false ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format" ); + break; + + case SM_GETAWAYMESSAGE: + // Отвечаем своим эвей-сообщением + LOG( "DatagramReceiver : It's away request" ); + pluginNetBIOS.SendAway( *this, nname_from ); + break; + + case SM_SENDAWAYMESSAGE: + // Находим контакт и ставим его эвей-сообщение + if ( iReadedBytes >= 2 + 1 + 4 ) + { + if ( HANDLE hContact = GetContact( CA2T( nname_from.original ) ) ) + { + LPCSTR szAway = (LPCSTR)( SMBBlock + 2 + 1 + 4 ); + SMBBlock[ iReadedBytes ] = 0; // ASCII -> ASCIIZ + + LOG( "DatagramReceiver : It's away answer \"%s\"", szAway ); + SetContactAway( hContact, szAway ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format" ); + break; + + case SM_GETAVATAR: + // Отвечаем своим аватаром + LOG( "DatagramReceiver : It's avatar request." ); + pluginNetBIOS.SendAvatar( *this, nname_from ); + break; + + case SM_SENDAVATAR: + // Находим контакт и ставим его аватар + if ( iReadedBytes >= 2 + 1 && iReadedBytes < MAX_AVATAR_SIZE + 3 ) + { + if ( HANDLE hContact = GetContact( CA2T( nname_from.original ) ) ) + { + LOG( "DatagramReceiver : It's avatar answer" ); + SetContactAvatar( hContact, SMBBlock + 2 + 1, (DWORD)iReadedBytes - 3 ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format or too big avatar" ); + break; + + default: + LOG( "DatagramReceiver : Unsupported message type 0x%02x", iMsgType ); + } + } + else + LOG( "DatagramReceiver : Unsupported data 0x%04x", *(WORD*)SMBBlock ); + } + + mir_free( SMBBlock ); +} + +void netbios_name::DatagramReceiverThread(LPVOID param) +{ + if ( netbios_name* pName = (netbios_name*)param ) + { + pName->DatagramReceiver(); + pName->m_dgreceiver = NULL; + } +} + +void netbios_name::Receiver(UCHAR lsn) +{ + // Created by Ilja Razinkov (also known as IPv6), 2002, IPv6Intendo@yandex.ru + // Keep this comment if you redistribute this file + + UCHAR* SMBBlock = (UCHAR*)mir_alloc( 65536 ); + if ( ! SMBBlock ) + return; + + CStringA sTo, sFrom, sMessage; + UCHAR nRes; + for (;;) + { + ZeroMemory( SMBBlock, 65536 ); + + // Получение очередного блока данных + WORD iReadedBytes = 65535; + nRes = pluginNetBIOS.Recv (m_lana, lsn, SMBBlock, iReadedBytes); + if (nRes != NRC_GOODRET) + { + LOG( "Receiver : Error while receiving data block" ); + break; + } + + // Смотрим что к нам пришло - сообщение или что-то неизвестное + if ( iReadedBytes < 4 || *(DWORD*)SMBBlock != SMB_MAGIC ) + { + LOG( "Receiver : Unsupported data 0x%08x", *(DWORD*)SMBBlock ); + break; + } + + UCHAR iMsgType = SMBBlock [4]; + if (iMsgType != SMBsends && + iMsgType != SMBsendstrt && + iMsgType != SMBsendend && + iMsgType != SMBsendtxt) + { + LOG( "Receiver : Unsupported message type 0x%02x", iMsgType ); + break; + } + + // Шлём подтверждение + UCHAR szReply [SMB_HEADER_SIZE + 5]; + UCHAR* szReplyData = + pluginNetBIOS.SetSMBHeaderCommand (szReply, iMsgType, sizeof (szReply)); + if (iMsgType == SMBsendstrt) + { + // Код сообщения + static UCHAR rnd = 1; + szReplyData [0] = 1; // Номер сообщения + szReplyData [1] = rnd++; // + if ( rnd > 5 ) + rnd = 1; + } + nRes = pluginNetBIOS.Send (m_lana, lsn, szReply, + (WORD)( (iMsgType == SMBsendstrt) ? (SMB_HEADER_SIZE + 5) : (SMB_HEADER_SIZE + 3) ) ); + if ( nRes != NRC_GOODRET ) + { + // Нефатальная ошибка + LOG( "Receiver : Error while sending ack" ); + } + + // Действия в зависимости от типа сообщения + if (iMsgType == SMBsends) + { + LOG( "Receiver : Got single-block message" ); + // Короткое сообщение, вытаскиваем данные и выходим... + sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4; + int iFromOffset = sFrom.GetLength (); + sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2; + int iToOffset = sTo.GetLength (); + sMessage = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2 + + iToOffset + 4; + break; + } + else if (iMsgType == SMBsendstrt) + { + LOG( "Receiver : Got start of multi-block message" ); + // Кусочковое сообщение, начало, смотрим от кого и кому + sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4; + int iFromOffset = sFrom.GetLength (); + sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + iFromOffset + 4 + 2; + } + else if (iMsgType == SMBsendtxt) + { + // Кусочковое сообщение, блок с данными, конкатенируем... + int iConcatSize = iReadedBytes - SMB_HEADER_SIZE - 8; + LOG( "Receiver : Got text (%d-%d bytes) of multi-block message", sMessage.GetLength(), sMessage.GetLength() + iConcatSize - 1 ); + sMessage.Append ((const char*) (SMBBlock + SMB_HEADER_SIZE + 8), iConcatSize); + } + else if (iMsgType == SMBsendend) + { + LOG( "Receiver : Got end of multi-block message" ); + // Кусочковое сообщение, конец, все получено, выходим + break; + } + } + + sMessage.Replace( "\x14", "\r\n" ); // <14> -> + + sTo.OemToAnsi(); + sFrom.OemToAnsi(); + sMessage.OemToAnsi(); + + // Смотрим информацию о сессии + CStringA sRealFrom; + if (GetRealSender (lsn, sRealFrom)) + { + LOG( "Receiver : Message from \"%s\" (real \"%s\") to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sRealFrom, (LPCSTR)sTo); + sFrom = sRealFrom; + } + else + { + LOG( "Receiver : Message from \"%s\" (real sender unknown) to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sTo); + } + + // Скажем до свиданья... + pluginNetBIOS.Hangup (m_lana, lsn); + + // Открываем сообщение (пустое игнорируем) + if ( ! sMessage.IsEmpty() ) + { + ReceiveContactMessage( CA2T( sFrom ), CA2T( sTo ), CA2T( sMessage ), sMessage.GetLength ()); + } + else + { + LOG( "Receiver : Ignoring empty message" ); + } + + mir_free( SMBBlock ); +} + +void netbios_name::ReceiverThread(LPVOID param) +{ + if ( ReceiverData* data = (ReceiverData*)param ) + { + data->self->Receiver( data->lsn ); + mir_free( data ); + } +} diff --git a/plugins/!NotAdopted/WinPopup/netbios_name.h b/plugins/!NotAdopted/WinPopup/netbios_name.h new file mode 100644 index 0000000000..2d35531b33 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios_name.h @@ -0,0 +1,157 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +#define SMB_ANY_NAME _T("* ") +#define FACILITY_NETBIOS (0x0f0f) +#define SMB_HEADER_SIZE (32) + +#pragma pack (push, 1) + +typedef struct SESSION_INFO_BLOCK +{ + SESSION_HEADER sib_header; + SESSION_BUFFER sib_Names[ NCBNAMSZ ]; +} SESSION_INFO_BLOCK, *PSESSION_INFO_BLOCK; + +#pragma pack (pop) + +class netbios_name +{ +public: + netbios_name(LPCTSTR n = SMB_ANY_NAME /* ANSI */, UCHAR type = 0, bool group = false, UCHAR lana = 0); + netbios_name(const NAME_BUFFER& n, UCHAR lana); + netbios_name& operator=(const netbios_name& n); + netbios_name& operator=(const UCHAR* n); + // Сравнение (производиться только по имени, номеру имени, типу имени) + bool operator==(const NAME_BUFFER& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени) + bool operator!=(const NAME_BUFFER& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени, адаптеру) + bool operator==(const netbios_name& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени, адаптеру) + bool operator!=(const netbios_name& n) const; + // Регистрация имени + bool Register(); + // Для ускорения + void AskForDestroy(); + // Дерегистрация имени + void Destroy(); + // Обратное преобразование NetBIOS-имени из OEM в ANSI в виде: NAME + CStringA GetANSIFullName() const; + + CStringA original; // Полное имя (в ANSI кодировке) + NAME_BUFFER netbiosed; // NetBIOS имя (в OEM кодировке): + // typedef struct _NAME_BUFFER { + // UCHAR name[NCBNAMSZ]; + // UCHAR name_num; + // UCHAR name_flags; + // } NAME_BUFFER, *PNAME_BUFFER; + + // Получение атрибутов имени: + + UCHAR GetType() const; + bool IsGroupName() const; + bool IsRegistered() const; + bool IsDuplicated() const; + bool IsError() const; + bool IsOwnName() const; + UCHAR GetLana() const; + size_t GetLength() const; // Длина имени NetBIOS + +protected: + bool m_managed; // Флаг управляемого имени + bool m_registered; // Флаг успешной регистрации имени + bool m_duplicated; // Флаг существования имени до регистрации + bool m_error; // Флаг ошибки прослушивания имени + UCHAR m_lana; // Номер адаптера + HANDLE m_listener; // Хэндлер рабочего потока-слушателя сессий + HANDLE m_dgreceiver; // Хэндлер рабочего потока-слушателя датаграмм + HANDLE m_term; // Хэндлер события останова рабочего потока-слушателя + + // Обратное преобразование NetBIOS-имени из OEM в ANSI + CStringA GetANSIName() const; + + bool GetRealSender(UCHAR lsn, CStringA& sRealFrom) const; + UCHAR AddName(); + UCHAR DeleteName(); + + // Ожидание начала сессии + void Listener(); + static void ListenerThread(LPVOID param); + + // Ожидание датаграммы + void DatagramReceiver(); + static void DatagramReceiverThread(LPVOID param); + + // Обработка сессии (из Listener) + void Receiver(UCHAR lsn); + static void ReceiverThread(LPVOID param); +}; + +typedef CAtlArray netbios_name_array; +typedef CAtlList netbios_name_list; + +/* +Name Number(h) Type Usage +-------------------------------------------------------------------------- + 00 U Workstation Service + 01 U Messenger Service +<\\--__MSBROWSE__> 01 G Master Browser + 03 U Messenger Service + 06 U RAS Server Service + 1F U NetDDE Service + 20 U File Server Service + 21 U RAS Client Service + 22 U Microsoft Exchange Interchange(MSMail +Connector) + 23 U Microsoft Exchange Store + 24 U Microsoft Exchange Directory + 30 U Modem Sharing Server Service + 31 U Modem Sharing Client Service + 43 U SMS Clients Remote Control + 44 U SMS Administrators Remote Control +Tool + 45 U SMS Clients Remote Chat + 46 U SMS Clients Remote Transfer + 4C U DEC Pathworks TCPIP service on +Windows NT + 42 U mccaffee anti-virus + 52 U DEC Pathworks TCPIP service on +Windows NT + 87 U Microsoft Exchange MTA + 6A U Microsoft Exchange IMC + BE U Network Monitor Agent + BF U Network Monitor Application + 03 U Messenger Service + 00 G Domain Name + 1B U Domain Master Browser + 1C G Domain Controllers + 1D U Master Browser + 1E G Browser Service Elections + 1C G IIS + 00 U IIS + [2B] U Lotus Notes Server Service +IRISMULTICAST [2F] G Lotus Notes +IRISNAMESERVER [33] G Lotus Notes +Forte_$ND800ZA [20] U DCA IrmaLan Gateway Server Service +*/ diff --git a/plugins/!NotAdopted/WinPopup/network.cpp b/plugins/!NotAdopted/WinPopup/network.cpp new file mode 100644 index 0000000000..4f51318e08 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/network.cpp @@ -0,0 +1,88 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "network.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Проверка, что строка похожа на IPv4-адрес в формате xx.xx.xx.xx +bool IsValidIP (LPCTSTR name) +{ + int dots = 0; + bool digit = false; + for ( ; *name; name++ ) + { + if ( *name == _T('.') ) + { + if ( ! digit ) + // Две точки подряд + return false; + + dots++; + digit = false; + } + else if ( *name < _T('0') || *name > _T('9') ) + { + // Это не цифра + return false; + } + else + { + digit = true; + } + } + return dots == 3 && digit; +} + +// Получение IP по имени хоста и получение короткого имени хоста +ip ResolveToIP (CString& name) +{ + // Получение имени из IP-адреса + ip addr = IsValidIP (name) ? ::inet_addr ( CT2A( name ) ) : INADDR_NONE; + if (addr != INADDR_NONE) { + struct hostent *hp = ::gethostbyaddr ((const char*) &addr, sizeof (addr), AF_INET); + if (hp) { + // Укорачиваем имя + name = hp->h_name; + int n = name.Find ('.'); + if (n != -1) + name = name.Left (n); + } + } + // Получение IP-адреса из имени + if (addr == INADDR_NONE) { + struct hostent *hp = ::gethostbyname ( CT2A( name ) ); + if (hp) { + addr = ((struct in_addr*)hp->h_addr)->s_addr; + // Укорачиваем имя + name = hp->h_name; + int n = name.Find ('.'); + if (n != -1) + name = name.Left (n); + } + } + return ntohl (addr); +} diff --git a/plugins/!NotAdopted/WinPopup/network.h b/plugins/!NotAdopted/WinPopup/network.h new file mode 100644 index 0000000000..541c764fbc --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/network.h @@ -0,0 +1,31 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2009 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +// Адрес IPv4 +typedef unsigned long ip; + +// Проверка, что строка похожа на IP-адрес в формате xx.xx.xx.xx +bool IsValidIP (LPCTSTR name); + +// Получение IP по имени хоста и получение короткого имени хоста +ip ResolveToIP (CString& name); diff --git a/plugins/!NotAdopted/WinPopup/options.cpp b/plugins/!NotAdopted/WinPopup/options.cpp new file mode 100644 index 0000000000..bfc227402a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/options.cpp @@ -0,0 +1,392 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "services.h" +#include "options.h" +#include "netbios.h" +#include "add_dialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define WM_FILLTREE (WM_USER+75) + +static netbios_name_list nns; +static HWND hTree = NULL; + +typedef struct _DlgDataOptions +{ + HMODULE hContact; + HIMAGELIST hTreeImages; + bool need_restart; +} DlgDataOptions; + +static void FillTreeThread (LPVOID param) +{ + // Ожидание инициализации NetBIOS (20 секунд) + for ( int i = 0; i < 20 && ! pluginNetBIOS && IsWindow( hTree ); i++ ) + Sleep( 1000 ); + + if ( IsWindow( hTree ) ) + { + // ...вначале своими именами + pluginNetBIOS.GetRegisteredNames( nns ); + // ...потом остальными именами + pluginNetBIOS.GetNames( nns, pluginMachineName, false ); + // ...и уведомление о готовности данных + PostMessage( reinterpret_cast (param), WM_FILLTREE, 0, 0 ); + } +} + +static void Refresh (HWND hwndDlg, HWND hwndTree) +{ + bool bOnline = ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + + nns.RemoveAll (); + + // Заполнение дерева имён... + TreeView_DeleteAllItems (hwndTree); + TVINSERTSTRUCT tvis = { TVI_ROOT, TVI_LAST }; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.iImage = tvis.item.iSelectedImage = bOnline ? 0 : 8; + tvis.item.pszText = bOnline ? TranslateT("Retrieving...") : TranslateT("Offline"); + TreeView_InsertItem (hwndTree, &tvis); + + if ( bOnline ) + { + // Запуск опроса хоста + mir_forkthread( FillTreeThread, hwndDlg ); + } +} + +static INT_PTR CALLBACK DlgProcOptions (HWND hwndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static bool bLastOnline = false; + DlgDataOptions* data = reinterpret_cast (GetWindowLongPtr (hwndDlg, DWLP_USER)); + + switch ( Msg ) + { + case WM_INITDIALOG: + { + TranslateDialogDefault (hwndDlg); + + data = (DlgDataOptions*)mir_alloc( sizeof( DlgDataOptions ) ); + if ( ! data ) + return FALSE; + + SetWindowLongPtr (hwndDlg, DWLP_USER, reinterpret_cast (data)); + data->need_restart = false; + data->hTreeImages = ImageList_Create (16, 16, ILC_COLOR8 | ILC_MASK, 8, 0); + + hTree = GetDlgItem (hwndDlg, IDC_TREE); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 0 + pluginModule, MAKEINTRESOURCE (IDI_COMPUTER), IMAGE_ICON, 16, 16, LR_SHARED ))); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 1 + pluginModule, MAKEINTRESOURCE (IDI_LANA), IMAGE_ICON, 16, 16, LR_SHARED ))); + + HICON hIcon; + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_GOOD_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 2 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_1, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_BAD_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 3 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_2, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_OTHER_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 4 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_3, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_GOOD_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 5 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_4, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_BAD_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 6 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_5, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_OTHER_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 7 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_6, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_COMPUTER_ERROR), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 8 + + TreeView_SetImageList (hTree, data->hTreeImages, TVSIL_NORMAL); + + BOOL b = DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE); + CheckDlgButton (hwndDlg, IDC_CHECK_NICK, (UINT)( b ? BST_CHECKED : BST_UNCHECKED )); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK1), b); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK2), b); + + b = DBGetContactSettingByte (NULL, modname, "RegisterUser", TRUE); + CheckDlgButton (hwndDlg, IDC_CHECK_USER, (UINT)( b ? BST_CHECKED : BST_UNCHECKED )); + EnableWindow (GetDlgItem (hwndDlg, IDC_USER), b); + + CheckDlgButton (hwndDlg, IDC_AUTOANSWER, + (UINT)( DBGetContactSettingByte (NULL, modname, "Auto-answer", FALSE) ? + BST_CHECKED : BST_UNCHECKED ) ); + CheckDlgButton (hwndDlg, IDC_DUPS, + (UINT)( DBGetContactSettingByte (NULL, modname, "Filter-dups", TRUE) ? + BST_CHECKED : BST_UNCHECKED ) ); + CheckDlgButton (hwndDlg, IDC_ALWAYSCHECK00FORONLINE, + (UINT)( IsLegacyOnline( NULL ) ? BST_CHECKED : BST_UNCHECKED ) ); + + BYTE method = (BYTE) DBGetContactSettingByte (NULL, modname, "SendMethod", 0); + CheckRadioButton (hwndDlg, IDC_USE_MAILSLOT, IDC_USE_NETSEND, + IDC_USE_MAILSLOT + method); + EnableWindow (GetDlgItem (hwndDlg, IDC_USE_NETSEND), (fnNetMessageBufferSend != NULL)); + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + { + netbios_name nname (sMyNick, 3); + SetDlgItemText (hwndDlg, IDC_NICK1, CA2T( nname.GetANSIFullName() ) ); + } + + if ( ! sMyNick.IsEmpty() ) + { + netbios_name nname (sMyNick, 1); + SetDlgItemText (hwndDlg, IDC_NICK2, CA2T( nname.GetANSIFullName() ) ); + } + + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( NULL, modname, "User", &dbv ) ) + { + netbios_name nname (dbv.ptszVal, 3); + SetDlgItemText (hwndDlg, IDC_USER, CA2T( nname.GetANSIFullName() ) ); + DBFreeVariant (&dbv); + } + + bLastOnline = ! ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + + SetTimer( hwndDlg, 55, 500, NULL ); + + return TRUE; + } + + case WM_TIMER: + if ( bLastOnline != ( pluginCurrentStatus != ID_STATUS_OFFLINE ) ) + { + bLastOnline = ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + Refresh( hwndDlg, hTree ); + } + return TRUE; + + case WM_DESTROY: + { + nns.RemoveAll(); + SetWindowLongPtr( hwndDlg, DWLP_USER, NULL ); + if ( data ) + { + ImageList_Destroy( data->hTreeImages ); + mir_free( data ); + } + hTree = NULL; + break; + } + + case WM_FILLTREE: + { + // Заполнение дерева имён + TreeView_DeleteAllItems (hTree); + TVINSERTSTRUCT tvis = { TVI_ROOT, TVI_LAST }; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + tvis.item.pszText = (LPTSTR)(LPCTSTR)pluginMachineName; + tvis.item.iImage = tvis.item.iSelectedImage = nns.GetCount() ? 0 : 8; + HTREEITEM hRoot = TreeView_InsertItem (hTree, &tvis); + if ( nns.GetCount() ) + { + TVITEM item = { 0 }; + for (POSITION pos = nns.GetHeadPosition (); pos;) + { + netbios_name nname (nns.GetNext (pos)); + tvis.item.lParam = nname.GetLana(); + + // Поиск ланы в дереве по номеру + item.hItem = TreeView_GetChild (hTree, hRoot); + while (item.hItem) + { + item.mask = TVIF_HANDLE | TVIF_PARAM; + if (TreeView_GetItem (hTree, &item) && + item.lParam == nname.GetLana ()) + // найден + break; + item.hItem = TreeView_GetNextSibling (hTree, item.hItem); + } + if (item.hItem) + // Лана уже есть + tvis.hParent = item.hItem; + else + { + // Ланы ещё нет + tvis.hParent = hRoot; + tvis.item.iImage = tvis.item.iSelectedImage = 1; + CString tmp; + tmp.Format ( _T("%s #%d"), TranslateT ("LAN adapter"), nname.GetLana ()); + tvis.item.pszText = (LPTSTR) (LPCTSTR) tmp; + tvis.hParent = TreeView_InsertItem (hTree, &tvis); + + pluginNetBIOS.GetMAC (nname.GetLana (), tmp); + tmp.Insert (0, _T("MAC: ")); + tvis.item.pszText = (LPTSTR) (LPCTSTR) tmp; + TreeView_InsertItem (hTree, &tvis); + } + + CA2T textT( nname.GetANSIFullName() ); + tvis.item.pszText = (LPTSTR)(LPCTSTR)textT; + tvis.item.iImage = tvis.item.iSelectedImage = + (nname.IsOwnName () ? (nname.IsError () ? 1 : 0) : 2) + + (nname.IsGroupName () ? 5 : 2); + + // Поиск имени в лане по имени + item.hItem = TreeView_GetChild (hTree, tvis.hParent); + while (item.hItem) + { + item.mask = TVIF_HANDLE | TVIF_TEXT; + item.cchTextMax = 64; + CString tmp; + item.pszText = tmp.GetBuffer (item.cchTextMax); + BOOL ret = TreeView_GetItem (hTree, &item); + tmp.ReleaseBuffer (); + if (ret && tmp == textT ) + // найден + break; + item.hItem = TreeView_GetNextSibling (hTree, item.hItem); + } + if (!item.hItem) + // Имени ещё нет + TreeView_InsertItem (hTree, &tvis); + } + } + TreeView_Expand (hTree, hRoot, TVE_EXPAND); + + nns.RemoveAll (); + return TRUE; + } + + case WM_NOTIFY: + { + LPPSHNOTIFY lpHdr = reinterpret_cast (lParam); + if (lpHdr->hdr.idFrom == 0) { + data->hContact = reinterpret_cast (lpHdr->lParam); + switch (lpHdr->hdr.code) { + case PSN_KILLACTIVE: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); + return TRUE; + + case PSN_APPLY: + DBWriteContactSettingByte (NULL, modname, "RegisterNick", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "RegisterUser", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_CHECK_USER) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "Auto-answer", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_AUTOANSWER) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "Filter-dups", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_DUPS) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "SendMethod", + (BYTE)( (((IsDlgButtonChecked (hwndDlg, IDC_USE_MAILSLOT) == BST_CHECKED) ? 0 : + ((IsDlgButtonChecked (hwndDlg, IDC_USE_NETBIOS) == BST_CHECKED) ? 1 : + ((IsDlgButtonChecked (hwndDlg, IDC_USE_NETSEND) == BST_CHECKED) ? 2 : + 0 ) ))))); + SetLegacyOnline( NULL, ( IsDlgButtonChecked( hwndDlg, + IDC_ALWAYSCHECK00FORONLINE ) == BST_CHECKED ) ); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); + if (data->need_restart) { + data->need_restart = false; + GotoOffline (); + Sleep (2000); + Refresh (hwndDlg, hTree); + } + return TRUE; + } + } + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) { + case IDC_CHECK_NICK: + case IDC_CHECK_USER: + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK1), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK2), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED); + EnableWindow (GetDlgItem (hwndDlg, IDC_USER), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_USER) == BST_CHECKED); + + case IDC_USE_MAILSLOT: + case IDC_USE_NETBIOS: + case IDC_USE_NETSEND: + data->need_restart = true; + + case IDC_AUTOANSWER: + case IDC_ALWAYSCHECK00FORONLINE: + case IDC_DUPS: + PropSheet_Changed (GetParent (hwndDlg), hwndDlg); + break; + + case IDC_ADD: + AddDialog( hwndDlg ); + break; + } + break; + } + } + return FALSE; +} + +int __cdecl OPT_INITIALISE (WPARAM wParam, LPARAM /* lParam */) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.cbSize = sizeof ( OPTIONSDIALOGPAGE ); + odp.pszGroup = "Network"; + odp.position = odp.pszGroup [0]; + odp.hInstance = pluginModule; + odp.pszTemplate = MAKEINTRESOURCEA (IDD_OPTIONS); + odp.pszTitle = modtitle; + odp.pfnDlgProc = DlgProcOptions; + odp.flags = ODPF_BOLDGROUPS; + CallService (MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); + + return 0; +} diff --git a/plugins/!NotAdopted/WinPopup/options.h b/plugins/!NotAdopted/WinPopup/options.h new file mode 100644 index 0000000000..8b7d8b8bec --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/options.h @@ -0,0 +1,24 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +int __cdecl OPT_INITIALISE (WPARAM wParam, LPARAM lParam); diff --git a/plugins/!NotAdopted/WinPopup/processapi.cpp b/plugins/!NotAdopted/WinPopup/processapi.cpp new file mode 100644 index 0000000000..d37578aed1 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/processapi.cpp @@ -0,0 +1,578 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "processapi.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +DWORD GetProcessId (LPCTSTR name) +{ + DWORD id = 0; + int name_len = lstrlen (name); + CProcessApi papi; + if (papi.Init (true)) { + DWORD pl = papi.ProcessesGetList(); + if (pl) { + CProcessApi::tProcessInfo pi = {0}; + while (papi.ProcessesWalk (pl, &pi)) { + int len = lstrlen (pi.FileName); + if (len >= name_len && + lstrcmpi (pi.FileName + (len - name_len), name) == 0) { + id = pi.pid; + break; + } + } + } + papi.ProcessesFreeList(pl); + } + return id; +} + +/* ----------------------------------------------------------------------------- + * Copyright (c) 2003 Elias Bachaalany + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ----------------------------------------------------------------------------- + */ + +#ifdef _UNICODE + #define Modifier "W" +#else + #define Modifier "A" +#endif + +// custom macro to allow me to load functions dynamically +#define DynamicGetProcAddress(lib, prefix, mod_name, Mod) \ + { \ + PVOID p = GetProcAddress(lib, #mod_name Mod); \ + if (!p) { \ + FreeLibrary(lib); \ + return (LastError = paeNoEntryPoint, false); \ + } \ + ##prefix##mod_name = (t_##prefix##mod_name)p; \ + } + +//-------------------------------------------------------------------------------------------- +// The constructor only initializes some internal variables +CProcessApi::CProcessApi() : + m_hPsApi (NULL), + m_hTlHlp (NULL), + m_hNtApi (NULL), + m_bPsApi (false), + m_bToolHelp (false), + m_bNtApi (false), + LastError (paeSuccess) +{ +} + +//-------------------------------------------------------------------------------------------- +// This is the destructor. It frees any process helper api that has been used +CProcessApi::~CProcessApi() +{ + if (m_hPsApi) + FreeLibrary(m_hPsApi); + if (m_hTlHlp) + FreeLibrary(m_hTlHlp); + if (m_hNtApi) + FreeLibrary(m_hNtApi); +} + +//-------------------------------------------------------------------------------------------- +// Used to initialize the CProcessApi class +bool CProcessApi::Init (bool bNtApiFirst) +{ + bool loaded = m_bPsApi || m_bToolHelp || m_bNtApi; + + if (bNtApiFirst && !loaded) { + loaded = Load_NtApi(); + } + + if (!loaded) { + loaded = Load_PsApi(); + } + + if (!loaded) { + loaded = Load_TlHlp(); + } + + if (!bNtApiFirst && !loaded) { + loaded = Load_NtApi(); + } + + return (loaded ? (LastError = paeSuccess, true) : (LastError = paeNoApi, false)); +} + +//-------------------------------------------------------------------------------------------- +// This function returns a list id (list id) that can be used w/ Walking functions +// in order to navigate through the process list +// This function decides what to use from the helper apis +DWORD CProcessApi::ModulesGetList(DWORD pid) +{ + tModulesData *md = new tModulesData; + if ( ! md ) + return (LastError = paeNoMem, 0u); + + // create the list + md->ml = new tModulesList; + if ( ! md->ml ) + { + delete md; + return (LastError = paeNoMem, 0u); + } + + // decide what to use + if (m_bPsApi) + LastError = ModulesPopulatePsApi(pid, md); + else if (m_bToolHelp) + LastError = ModulesPopulateToolHelp(pid, md); + else if (m_bNtApi) + LastError = ModulesPopulateNtApi(pid, md); + + return (DWORD) md; +} + +//-------------------------------------------------------------------------------------------- +// Populates the modules of a process using ToolHelp api +DWORD CProcessApi::ModulesPopulateToolHelp(DWORD pid, tModulesData *md) +{ + MODULEENTRY32 me32 = {sizeof(MODULEENTRY32), 0}; + tModuleInfo mi = {0}; + + // Take a snapshot of all modules in the specified process. + HANDLE hModuleSnap = tlhlp_CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); + + if (hModuleSnap == INVALID_HANDLE_VALUE) + return paeNoSnap; + + // Start walking + BOOL bMore = tlhlp_Module32First(hModuleSnap, &me32); + do + { + lstrcpy (mi.FileName, me32.szExePath); + mi.ImageBase = me32.modBaseAddr; + mi.ImageSize = me32.modBaseSize; + + // save item + md->ml->Add (mi); + + // search next + bMore = tlhlp_Module32Next(hModuleSnap, &me32); + } while (bMore); + + CloseHandle (hModuleSnap); + md->Pos = 0; + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// Populates the modules of a process using PsApi api +DWORD CProcessApi::ModulesPopulatePsApi(DWORD pid, tModulesData *md) +{ + DWORD nModules, nCount = 4096; + HANDLE hProcess; + + // allocate memory for modules + HMODULE *modules = new HMODULE[nCount]; + + // open process for querying only + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) + return paeNoSnap; + + // now try to enum all modules + if (!psapi_EnumProcessModules(hProcess, modules, nCount * sizeof(DWORD), &nModules)) + { + CloseHandle(hProcess); + return paeNoSnap; + } + + // because nModules returned from EnumProcessModules() is in bytes, I divid by 4 to return n DWORDs + nModules /= 4; + + tModuleInfo mi = {0}; + MODULEINFO psapiMi = {0}; + + for (DWORD i=0; i < nModules; i++) + { + // get module name + psapi_GetModuleFileNameEx(hProcess, modules[i], mi.FileName, sizeof(mi.FileName)); + + // get module information + psapi_GetModuleInformation(hProcess, modules[i], &psapiMi, sizeof(MODULEINFO)); + + // get relevant data + mi.ImageBase = psapiMi.lpBaseOfDll; + mi.ImageSize = psapiMi.SizeOfImage; + + // save item + md->ml->Add (mi); + } + + md->Pos = 0; + CloseHandle(hProcess); + delete [] modules; + + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// It frees a modules list by its ID +void CProcessApi::ModulesFreeList(DWORD_PTR lid) +{ + tModulesData *md = reinterpret_cast(lid); + delete md->ml; + delete md; +} + +//-------------------------------------------------------------------------------------------- +// This function allows you to retrieve information about a certain module in a process +// You can either use this function using the Pos parameter controlled by the ModulesCount() +// Or you can keep calling it till it returns false +bool CProcessApi::ModulesWalk(DWORD_PTR lid, tModuleInfo *mi, DWORD Pos) +{ + tModulesData *md = reinterpret_cast(lid); + + // auto position ? + if (Pos == -1) + Pos = md->Pos; + + // out of bounds? + if (Pos > md->ml->GetCount()) + return (LastError = paeOutOfBounds, false); + + // end reached ? + else if (Pos == md->ml->GetCount()) + return (LastError = paeNoMore, false); + + // copy information to user buffer + *mi = md->ml->GetAt (Pos); + + // advance position to next item + md->Pos++; + + return (LastError = paeSuccess, true); +} + + +//-------------------------------------------------------------------------------------------- +// This function allows you to retrieve information about a certain process in the list +// You can either use this function using the Pos parameter controlled by the ProcessesCount() +// Or you can keep calling it till it returns false +bool CProcessApi::ProcessesWalk(DWORD_PTR lid, tProcessInfo *pi, DWORD Pos) +{ + tProcessesData *pd = reinterpret_cast(lid); + + // auto position ? + if (Pos == -1) + Pos = pd->Pos; + + // out of bounds? + if (Pos > pd->pl->GetCount()) + return (LastError = paeOutOfBounds, false); + // end reached ? + else if (Pos == pd->pl->GetCount()) + return (LastError = paeNoMore, false); + + // copy information to user buffer + *pi = pd->pl->GetAt (Pos); + + // advance position to next item + pd->Pos++; + return (LastError = paeSuccess, true); +} + + +//-------------------------------------------------------------------------------------------- +// This function returns a list id (list id) that can be used w/ Walking functions +// in order to navigate through the process list +// This function decides what to use from the helper apis +DWORD CProcessApi::ProcessesGetList() +{ + tProcessesData *pd = new tProcessesData; + if (!pd) + return (LastError = paeNoMem, 0u); + + // create the list + pd->pl = new tProcessesList; + if (!pd->pl) + { + delete pd; + return (LastError = paeNoMem, 0u); + } + + // decide what to use + if (m_bPsApi) + LastError = ProcessesPopulatePsApi(pd); + else if (m_bToolHelp) + LastError = ProcessesPopulateToolHelp(pd); + else if (m_bNtApi) + LastError = ProcessesPopulateNtApi(pd); + + return (DWORD) pd; +} + +//-------------------------------------------------------------------------------------------- +// It frees a process list by its ID +void CProcessApi::ProcessesFreeList(DWORD_PTR lid) +{ + tProcessesData *pd = reinterpret_cast(lid); + delete pd->pl; + delete pd; +} + +//-------------------------------------------------------------------------------------------- +// Dynamically loads the PsApi functions +bool CProcessApi::Load_PsApi() +{ + if (m_bPsApi) + return true; + if (!m_hPsApi) + m_hPsApi = LoadLibrary (_T("psapi.dll")); + if (!m_hPsApi) + return false; + + DynamicGetProcAddress(m_hPsApi, psapi_, GetModuleFileNameEx, Modifier); + DynamicGetProcAddress(m_hPsApi, psapi_, EnumProcessModules, ""); + DynamicGetProcAddress(m_hPsApi, psapi_, EnumProcesses, ""); + DynamicGetProcAddress(m_hPsApi, psapi_, GetModuleInformation, ""); + + m_bPsApi = true; + return true; +} + + +//-------------------------------------------------------------------------------------------- +// Dynamically loads the ToolHelp functions +bool CProcessApi::Load_TlHlp() +{ + if (m_bToolHelp) + return true; + if (!m_hTlHlp) + m_hTlHlp = LoadLibrary (_T("kernel32.dll")); + if (!m_hTlHlp) + return false; + + DynamicGetProcAddress(m_hTlHlp, tlhlp_, CreateToolhelp32Snapshot, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Process32First, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Process32Next, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Module32First, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Module32Next, ""); + + m_bToolHelp = true; + return true; +} + +bool CProcessApi::Load_NtApi() +{ + if (m_bNtApi) + return true; + if (!m_hNtApi) + m_hNtApi = LoadLibrary (_T("ntdll.dll")); + if (!m_hNtApi) + return false; + + DynamicGetProcAddress(m_hNtApi, ntapi_, ZwQuerySystemInformation, ""); + + m_bNtApi = true; + return true; +} + +//-------------------------------------------------------------------------------------------- +// Populates a tProcessesList with the help of ToolHelp API +// Returns an error code paeXXXX +DWORD CProcessApi::ProcessesPopulateToolHelp(tProcessesData *pd) +{ + // create a process snapshot + HANDLE hSnap = tlhlp_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap == INVALID_HANDLE_VALUE) + return paeNoSnap; + + BOOL bMore; + tProcessInfo pi = {0}; + + PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32), 0}; + + // clear the list + pd->pl->RemoveAll (); + + // initialize position + pd->Pos = 0; + + bMore = tlhlp_Process32First(hSnap, &pe32); + while (bMore) + { + // convert from PROCESSENTRY32 to my unified tProcessInfo struct + pi.pid = pe32.th32ProcessID; + lstrcpy (pi.FileName, pe32.szExeFile); + + pd->pl->Add(pi); + bMore = tlhlp_Process32Next(hSnap, &pe32); + } + + CloseHandle(hSnap); + return paeSuccess; +} + + +//-------------------------------------------------------------------------------------------- +// Populates the list using PsApi functions +DWORD CProcessApi::ProcessesPopulatePsApi(tProcessesData *pd) +{ + DWORD nProcess, // number of processes returned + nCount(4096); // maximum number of processes (defined by me) + + // Dynamic array for storing returned processes IDs + DWORD *processes = new DWORD[nCount]; + + // enum all processes + if (!psapi_EnumProcesses(processes, nCount * sizeof(DWORD), &nProcess)) + { + delete [] processes; + return paeNoSnap; + } + + // convert fron bytes count to items count + nProcess /= 4; + + // walk in process list + for (DWORD i = 0; i < nProcess; i++) { + + if (processes[i] == 0) + // Idle + continue; + + // open process for querying only + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]); + if (!hProcess) + continue; + + // get the process's image name by getting first module + DWORD nmod; + HMODULE mod1; + + tProcessInfo pi = {0}; + pi.pid = processes [i]; + if (!psapi_EnumProcessModules (hProcess, &mod1, sizeof(mod1), &nmod)) + lstrcpy (pi.FileName, _T("-")); + else + psapi_GetModuleFileNameEx (hProcess, mod1, pi.FileName, sizeof(pi.FileName)); + pd->pl->Add (pi); + + CloseHandle(hProcess); + } + + // reposition list to 0 + pd->Pos = 0; + delete [] processes; + + return paeSuccess; +} + +DWORD CProcessApi::ProcessesPopulateNtApi (tProcessesData *pd) +{ + ULONG cbBuffer = 0x10000; + char* pBuffer; + NTSTATUS Status; + do { + pBuffer = new char [cbBuffer]; + if (pBuffer == NULL) + return paeNoMem; + Status = ntapi_ZwQuerySystemInformation (SystemProcessesAndThreadsInformation, + pBuffer, cbBuffer, NULL); + if (Status == STATUS_INFO_LENGTH_MISMATCH) { + delete [] pBuffer; + cbBuffer *= 2; + } else + if (!NT_SUCCESS(Status)) { + delete [] pBuffer; + return paeNoSnap; + } + } while (Status == STATUS_INFO_LENGTH_MISMATCH); + + PSYSTEM_PROCESSES pProcesses = (PSYSTEM_PROCESSES) pBuffer; + for (;;) { + if (pProcesses->ProcessName.Buffer != NULL) { + tProcessInfo pi; + pi.pid = pProcesses->ProcessId; +#ifdef UNICODE + lstrcpy (pi.FileName, pProcesses->ProcessName.Buffer); +#else + WideCharToMultiByte (CP_ACP, 0, pProcesses->ProcessName.Buffer, -1, + pi.FileName, MAX_PATH, NULL, NULL); +#endif + pd->pl->Add (pi); + } // else + // Idle + + if (pProcesses->NextEntryDelta == 0) + break; + + // find the address of the next process structure + pProcesses = (PSYSTEM_PROCESSES)(((LPBYTE)pProcesses) + pProcesses->NextEntryDelta); + } + pd->Pos = 0; + delete [] pBuffer; + return paeSuccess; +} + +DWORD CProcessApi::ModulesPopulateNtApi(DWORD /* pid */, tModulesData* /* md */) +{ + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// Returns the count in the processes list +DWORD CProcessApi::ProcessesCount(DWORD_PTR lid) const +{ + return (DWORD)(reinterpret_cast(lid))->pl->GetCount(); +} + +//-------------------------------------------------------------------------------------------- +// Returns the count in the modules list +DWORD CProcessApi::ModulesCount(DWORD_PTR lid) const +{ + return (DWORD)(reinterpret_cast(lid))->ml->GetCount(); +} diff --git a/plugins/!NotAdopted/WinPopup/processapi.h b/plugins/!NotAdopted/WinPopup/processapi.h new file mode 100644 index 0000000000..b1875751ea --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/processapi.h @@ -0,0 +1,264 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +#pragma pack (push, 1) + +typedef LONG NTSTATUS; +typedef LONG KPRIORITY; +typedef LONG SYSTEM_INFORMATION_CLASS; + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +#define SystemProcessesAndThreadsInformation 5 + +typedef struct _CLIENT_ID { + DWORD UniqueProcess; + DWORD UniqueThread; +} CLIENT_ID; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING; + +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; +} VM_COUNTERS; + +typedef struct _SYSTEM_THREADS { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + LONG State; + LONG WaitReason; +} SYSTEM_THREADS, * PSYSTEM_THREADS; + +typedef struct _SYSTEM_PROCESSES { + ULONG NextEntryDelta; + ULONG ThreadCount; + ULONG Reserved1[6]; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ProcessName; + KPRIORITY BasePriority; + ULONG ProcessId; + ULONG InheritedFromProcessId; + ULONG HandleCount; + ULONG Reserved2[2]; + VM_COUNTERS VmCounters; +#if _WIN32_WINNT >= 0x500 + IO_COUNTERS IoCounters; +#endif + SYSTEM_THREADS Threads[1]; +} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; + +#pragma pack (pop) + +//-------------------------------------------------------------------------------------------- +// CProcessApi class - written by Elias Bachaalany. +// Check the implementation file for more information +// + +class CProcessApi +{ +public: + typedef struct tProcessInfo + { + DWORD pid; + TCHAR FileName[MAX_PATH]; + }; + + typedef struct tModuleInfo + { + LPVOID ImageBase; + DWORD ImageSize; + TCHAR FileName[MAX_PATH]; + }; + +private: + typedef CAtlArray tProcessesList; + typedef CAtlArray tModulesList; + + typedef struct tProcessesData + { + DWORD Pos; + tProcessesList *pl; + }; + + typedef struct tModulesData + { + DWORD Pos; + tModulesList *ml; + }; + + // PSAPI.DLL functions prototype + typedef BOOL (WINAPI *t_psapi_EnumProcesses)( + DWORD *lpidProcess, // array of process identifiers + DWORD cb, // size of array + DWORD *cbNeeded // number of bytes returned + ); + + typedef BOOL (WINAPI *t_psapi_EnumProcessModules)( + HANDLE hProcess, // handle to process + HMODULE *lphModule, // array of module handles + DWORD cb, // size of array + LPDWORD lpcbNeeded // number of bytes required + ); + + typedef DWORD (WINAPI *t_psapi_GetModuleFileNameEx)( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPTSTR lpFilename, // path buffer + DWORD nSize // maximum characters to retrieve + ); + + typedef BOOL (WINAPI *t_psapi_GetModuleInformation)( + HANDLE hProcess, + HMODULE hModule, + LPMODULEINFO lpmodinfo, + DWORD cb + ); + + // functions instances + t_psapi_GetModuleFileNameEx psapi_GetModuleFileNameEx; + t_psapi_EnumProcessModules psapi_EnumProcessModules; + t_psapi_EnumProcesses psapi_EnumProcesses; + t_psapi_GetModuleInformation psapi_GetModuleInformation; + + // TOOLHELP functions prototype + typedef HANDLE (WINAPI *t_tlhlp_CreateToolhelp32Snapshot)( + DWORD dwFlags, + DWORD th32ProcessID + ); + + typedef BOOL (WINAPI *t_tlhlp_Process32First)( + HANDLE hSnapshot, + LPPROCESSENTRY32 lppe + ); + + typedef BOOL (WINAPI *t_tlhlp_Process32Next)( + HANDLE hSnapshot, + LPPROCESSENTRY32 lppe + ); + + typedef BOOL (WINAPI *t_tlhlp_Module32First)( + HANDLE hSnapshot, + LPMODULEENTRY32 lpme + ); + + typedef BOOL (WINAPI *t_tlhlp_Module32Next)( + HANDLE hSnapshot, + LPMODULEENTRY32 lpme + ); + + // functions instances + t_tlhlp_CreateToolhelp32Snapshot tlhlp_CreateToolhelp32Snapshot; + t_tlhlp_Process32First tlhlp_Process32First; + t_tlhlp_Process32Next tlhlp_Process32Next; + t_tlhlp_Module32First tlhlp_Module32First; + t_tlhlp_Module32Next tlhlp_Module32Next; + + // NTDLL.DLL functions prototype + typedef NTSTATUS (NTAPI *t_ntapi_ZwQuerySystemInformation)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + + // functions instances + t_ntapi_ZwQuerySystemInformation ntapi_ZwQuerySystemInformation; + + // Private member variables + HMODULE m_hPsApi; + HMODULE m_hTlHlp; + HMODULE m_hNtApi; + + bool m_bPsApi; + bool m_bToolHelp; + bool m_bNtApi; + + bool Load_PsApi(); + bool Load_TlHlp(); + bool Load_NtApi(); + + DWORD ProcessesPopulatePsApi(tProcessesData *pd); + DWORD ProcessesPopulateToolHelp(tProcessesData *pd); + DWORD ProcessesPopulateNtApi(tProcessesData *pd); + + DWORD ModulesPopulatePsApi(DWORD pid, tModulesData *md); + DWORD ModulesPopulateToolHelp(DWORD pid, tModulesData *md); + DWORD ModulesPopulateNtApi(DWORD pid, tModulesData *md); + +public: + // CProcessApi error enum + enum + { + paeSuccess = 0, // No error + paeNoApi, // No process API helper dll found + paeNoEntryPoint, // One needed entrypoint not found in helper dll + paeNoMem, // Not enough memory + paeNoSnap, // Could not get a snapshot + paeNoMore, // List contains no more items + paeOutOfBounds, // Tried to access list w/ an invalid index + paeYYY + }; + + DWORD LastError; // Holds the last error + + CProcessApi(); + ~CProcessApi(); + + bool Init (bool bNtApiFirst = false); + + DWORD ProcessesGetList(); + bool ProcessesWalk(DWORD_PTR lid, tProcessInfo *pi, DWORD Pos = -1); + DWORD ProcessesCount(DWORD_PTR lid) const; + void ProcessesFreeList(DWORD_PTR lid); + + DWORD ModulesGetList(DWORD ProcessID); + bool ModulesWalk(DWORD_PTR lid, tModuleInfo *mi, DWORD Pos = -1); + DWORD ModulesCount(DWORD_PTR lid) const; + void ModulesFreeList(DWORD_PTR lid); +}; + +// Получение PID запущенного процесса по имени его выполнимого модуля +DWORD GetProcessId (LPCTSTR name); diff --git a/plugins/!NotAdopted/WinPopup/resource.h b/plugins/!NotAdopted/WinPopup/resource.h new file mode 100644 index 0000000000..be40ff446c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/resource.h @@ -0,0 +1,66 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by winpopup_proto.rc +// +#define IDI_WINPOPUP 102 +#define IDI_ONLINE 104 +#define IDI_OFFLINE 105 +#define IDD_OPTIONS 106 +#define IDI_AWAY 128 +#define IDI_FREECHAT 129 +#define IDI_INVISIBLE 130 +#define IDI_NA 131 +#define IDI_DND 158 +#define IDI_OCCUPIED 159 +#define IDC_AUTOANSWER 1001 +#define IDI_ONTHEPHONE 1002 +#define IDC_NICK1 1002 +#define IDI_OUTTOLUNCH 1003 +#define IDC_USER 1003 +#define IDC_NICK2 1004 +#define IDC_ADD 1005 +#define IDC_NAME 1006 +#define IDC_DUPS 1006 +#define IDC_TREE 1007 +#define IDC_LEGEND_1 1008 +#define IDC_LEGEND_2 1009 +#define IDC_LEGEND_3 1010 +#define IDC_LEGEND_4 1011 +#define IDC_LEGEND_5 1012 +#define IDC_LEGEND_6 1013 +#define IDC_USE_MAILSLOT 1014 +#define IDC_USE_NETBIOS 1015 +#define IDC_USE_NETSEND 1016 +#define IDC_CHECK_USER 1017 +#define IDC_CHECK_NICK 1018 +#define IDC_ABOUT 1019 +#define IDC_ONLINE_CHECK 1020 +#define IDC_ALWAYSCHECK00FORONLINE 1021 +#define IDC_CHECK00FORONLINE 1022 +#define IDC_CHECK1 1023 +#define IDC_GROUP 1023 +#define IDD_ADD 2000 +#define IDI_LANA 2001 +#define IDI_COMPUTER 2002 +#define IDI_GOOD_NAME 2003 +#define IDI_BAD_NAME 2004 +#define IDI_OTHER_NAME 2005 +#define IDI_OTHER_NAMES 2006 +#define IDI_BAD_NAMES 2007 +#define IDI_GOOD_NAMES 2008 +#define IDD_USERINFO 2009 +#define IDI_EXPLORE 2011 +#define IDI_COMPUTER_ERROR 2013 +#define IDI_ADD_COMPUTER 2014 +#define IDD_CREATE 2015 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 2016 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1024 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/!NotAdopted/WinPopup/scanner.cpp b/plugins/!NotAdopted/WinPopup/scanner.cpp new file mode 100644 index 0000000000..a6956ff51a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/scanner.cpp @@ -0,0 +1,218 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "scanner.h" +#include "netbios.h" +#include "chat.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +contact_scanner pluginScanner; + +contact_scanner::contact_scanner () : + m_ScannerTerm (NULL), + m_Scanner (NULL) +{ +} + +contact_scanner::~contact_scanner () +{ + Destroy (); +} + +bool contact_scanner::Create () +{ + // Запуск сканера контактов + if (m_ScannerTerm) + ResetEvent (m_ScannerTerm); + else + m_ScannerTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + + if ( ! m_Scanner ) + m_Scanner = (HANDLE)mir_forkthread( ScannerThread, this ); + + return ( m_Scanner != NULL ); +} + +void contact_scanner::AskForDestroy() +{ + if (m_ScannerTerm) + SetEvent (m_ScannerTerm); +} + +void contact_scanner::Destroy () +{ + AskForDestroy(); + + if (m_Scanner) + { + if (WaitForSingleObject (m_Scanner, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate scanner!"); + TerminateThread (m_Scanner, 0); + } + m_Scanner = NULL; + } + + if (m_ScannerTerm) { + CloseHandle (m_ScannerTerm); + m_ScannerTerm = NULL; + } +} + +contact_scanner::operator bool () const +{ + return ( m_Scanner != NULL ); +} + +// First, Next, ... Next, NULL, First, Next... +HANDLE contact_scanner::GetNextScannableContact() +{ + static HANDLE hContact = NULL; + if (!hContact) + hContact = (HANDLE) CallService (MS_DB_CONTACT_FINDFIRST, 0, 0); + + // Циклический перебор контактов + while( hContact ) + { + // Проверка на совпадение протокола контакта + if ( IsMyContact( hContact ) && + !DBGetContactSettingByte (hContact, "CList", "NotOnList", 0) && + !DBGetContactSettingByte (hContact, "CList", "Hidden", 0) ) + { + // Вычисление сколько секунд прошло со времени последнего + // обновления статуса контакта. Нужна проверка? + DWORD elapsed = GetElapsed (hContact, "LastSeen"); + if ( elapsed >= MIN_PING_INTERVAL ) + break; + } + hContact = (HANDLE) CallService (MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + return hContact; +} + +int contact_scanner::ScanContact(HANDLE hContact) +{ + if ( ! pluginInstalled ) + return ID_STATUS_OFFLINE; + +#ifdef CHAT_ENABLED + if ( IsChatRoom( hContact ) ) + { + CString sSession = GetChatSession( hContact ); + if ( pluginChatEnabled && ! sSession.IsEmpty() ) + { + CAtlList< CString > lst; + EnumWorkgroups( lst ); + for ( POSITION pos = lst.GetHeadPosition(); pos; ) + { + if ( lst.GetNext( pos ) == sSession ) + return ID_STATUS_ONLINE; + } + } + return ID_STATUS_OFFLINE; + } + else +#endif // CHAT_ENABLED + { + int status = ID_STATUS_OFFLINE; + + // Получение статуса "Always Online" + if ( DBGetContactSettingByte( hContact, modname, "AlwaysOnline", FALSE ) ) + status = ID_STATUS_ONLINE; + + // Получение имени контакта + CString sNick = GetNick( hContact ); + if ( ! sNick.IsEmpty() ) + { + if ( IsGroup( hContact ) ) + { + // Имя "ВСЕ" вегда онлайн + if ( sNick == _T("*") ) + return ID_STATUS_ONLINE; + + // Перечисление групп и сличение с нашей + CAtlList< CString > lst; + EnumWorkgroups( lst ); + for ( POSITION pos = lst.GetHeadPosition(); pos; ) + { + if ( lst.GetNext( pos ).CompareNoCase( sNick ) == 0 ) + return ID_STATUS_ONLINE; + } + } + else if ( IsLegacyOnline( NULL ) || IsLegacyOnline( hContact ) ) + { + // Синхронный опрос хоста на наличие NetBIOS-имени "Nick <00> U" + netbios_name nname( sNick, 0x00, false ); + UCHAR foo; + if ( pluginNetBIOS.FindNameLana( nname, foo ) ) + { + status = ID_STATUS_ONLINE; + + // Асинхронный опрос контакта "Nick <00> U" + pluginNetBIOS.AskStatus( nname ); + } + } + else + { + // Синхронный опрос хоста на наличие NetBIOS-имени "Nick <03> U" + netbios_name nname( sNick, 0x03, false ); + UCHAR foo; + if ( pluginNetBIOS.FindNameLana( nname, foo ) ) + { + status = ID_STATUS_ONLINE; + + // Асинхронный опрос контакта "Nick <03> U" + pluginNetBIOS.AskStatus( nname ); + } + } + } + return status; + } +} + +void contact_scanner::Scanner () +{ + while (WaitForSingleObject (m_ScannerTerm, 1000) == WAIT_TIMEOUT) + { + // Выборка следующего кандидата на проверку + if ( HANDLE hContact = GetNextScannableContact() ) + { + // Проверка контакта + SetContactStatus( hContact, ScanContact( hContact ), true ); + } + } +} + +void contact_scanner::ScannerThread (LPVOID lpParameter) +{ + if ( contact_scanner* pScanner = (contact_scanner*)lpParameter ) + { + pScanner->Scanner(); + pScanner->m_Scanner = NULL; + } +} diff --git a/plugins/!NotAdopted/WinPopup/scanner.h b/plugins/!NotAdopted/WinPopup/scanner.h new file mode 100644 index 0000000000..f2a5c87402 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/scanner.h @@ -0,0 +1,49 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#pragma once + +class contact_scanner +{ +public: + contact_scanner (); + ~contact_scanner (); + + bool Create (); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool () const; + + // Проверка статуса контакта (асинхронная и синхронная) + static int ScanContact(HANDLE hContact); + +protected: + HANDLE m_ScannerTerm; // Событие для остановки + HANDLE m_Scanner; // Хэндлер нити периодической проверки контактов + + // Получить следующий контакт нуждающийся в проверке + static HANDLE GetNextScannableContact (); + // Рабочая нить цикла периодической проверки контактов + void Scanner (); + static void ScannerThread (LPVOID lpParameter); +}; + +extern contact_scanner pluginScanner; diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h b/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h new file mode 100644 index 0000000000..9df013446f --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h @@ -0,0 +1,359 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Avatar service + +- load and maintain a cache of contact avatars. +- draw avatars to a given target device context +- maintain per protocol fallback images + +The avatar service builds on top of Mirandas core bitmap loading service (MS_UTILS_LOADBITMAP). +However, if imgdecoder.dll is installed in mirandas main or Plugins directory, it can be used +to support PNG images. The avatar service loads 32bit PNG images and peforms alpha channel +premultiplication so that these images can be rendered by using the Win32 AlphaBlend() API. + +The cache grows on demand only, that is, no avatars are PREloaded. An avatar is only loaded +if a plugin requests this by using the MS_AV_GETAVATAR service. Since avatars may update +asynchronously, the avatar iamge may not be ready when a plugin calls the service. In that +case, an event (ME_AV_AVATARCHANGED) is fired when a contacts avatar changes. This event +is also fired, when a contact avatar changes automatically. + +The service takes care about protocol capabilites (does not actively fetch avatars for +protocols which do not report avatar capabilities via PF4_AVATARS or for protocols which +have been disabled in the option dialog). It also does not actively fetch avatars for +protocols which are in invisible status mode (may cause privacy issues and some protocols +like MSN don't allow any outbound client communication when in invisible status mode) +unless AF_FETCHALWAYS is set. + +- TODO +- maintain recent avatars (store the last hashes to avoid re-fetching) +- cache expiration, based on least recently used algorithm. + +(c) 2005 by Nightwish, silvercircle@gmail.com + +*/ + +#ifndef _M_AVATARS_H +#define _M_AVATARS_H + +#define AVS_BITMAP_VALID 1 +#define AVS_BITMAP_EXPIRED 2 // the bitmap has been expired from the cache. (unused, currently. +#define AVS_HIDEONCLIST 4 +#define AVS_PREMULTIPLIED 8 // set in the dwFlags member of the struct avatarCacheEntry for 32 bit transparent + // images when loaded with imgdecoder. These images can be rendered transparently + // using the AlphaBlend() API with AC_SRC_ALPHA +#define AVS_PROTOPIC 16 // picture is a protocol picture +#define AVS_CUSTOMTRANSPBKG 32 // Bitmap was changed to set the background color transparent +#define AVS_HASTRANSPARENCY 64 // Bitmap has at least one pixel transparent +#define AVS_OWNAVATAR 128 // is own avatar entry +#define AVS_NOTREADY 4096 + +struct avatarCacheEntry { + DWORD cbSize; // set to sizeof(struct) + HANDLE hContact; // contacts handle, 0, if it is a protocol avatar + HBITMAP hbmPic; // bitmap handle of the picutre itself + DWORD dwFlags; // see above for flag values + LONG bmHeight, bmWidth; // bitmap dimensions + DWORD t_lastAccess; // last access time (currently unused, but plugins should still + // use it whenever they access the avatar. may be used in the future + // to implement cache expiration + LPVOID lpDIBSection; // unused field + char szFilename[MAX_PATH]; // filename of the avatar (absolute path) +}; + +typedef struct avatarCacheEntry AVATARCACHEENTRY; + +struct CacheNode { + struct CacheNode *pNextNode; + struct avatarCacheEntry ace; + //CRITICAL_SECTION cs; + BOOL loaded; + int mustLoad; + DWORD dwFlags; + int pa_format; +}; + +#define AVDRQ_FALLBACKPROTO 0x0001 // use the protocol picture as fallback (currently not used) +#define AVDRQ_FAILIFNOTCACHED 0x0002 // don't create a cache entry if it doesn't already exist. (currently not working) +#define AVDRQ_ROUNDEDCORNER 0x0004 // draw with rounded corners +#define AVDRQ_DRAWBORDER 0x0008 // draw a border around the picture +#define AVDRQ_PROTOPICT 0x0010 // draw a protocol picture (if available). +#define AVDRQ_HIDEBORDERONTRANSPARENCY 0x0020 // hide border if bitmap has transparency +#define AVDRQ_OWNPIC 0x0040 // draw own avatar (szProto is valid - use "" for global avatar) +#define AVDRQ_RESPECTHIDDEN 0x0080 // don't draw images marked as hidden +#define AVDRQ_DONTRESIZEIFSMALLER 0x0100 // don't resize images that are smaller then the draw area +#define AVDRQ_FORCEFASTALPHA 0x0200 // force rendering with simple AlphaBlend (will use FI_Resample otherwise) +#define AVDRQ_FORCEALPHA 0x0400 // force with simple AlphaBlend (may use StretchBlt otherwise) +#define AVDRQ_AERO 0x0800 // draw on aero surface + +// request to draw a contacts picture. See MS_AV_DRAWAVATAR service description + +typedef struct _avatarDrawRequest { + DWORD cbSize; // set this to sizeof(AVATARDRAWREQUEST) - mandatory, service will return failure code if + // cbSize is wrong + HANDLE hContact; // the contact for which the avatar should be drawn. set it to 0 to draw a protocol picture + HDC hTargetDC; // target device context + RECT rcDraw; // target rectangle. The avatar will be centered within the rectangle and scaled to fit. + DWORD dwFlags; // flags (see above for valid bitflags) + DWORD dwReserved; // for future use + DWORD dwInternal; // don't use it + COLORREF clrBorder; // color for the border (used with AVDRQ_DRAWBORDER) + UCHAR radius; // radius (used with AVDRQ_ROUNDEDCORNER) + UCHAR alpha; // alpha value for semi-transparent avatars (valid values form 1 to 255, if it is set to 0 + // the avatar won't be transparent. + char *szProto; // only used when AVDRQ_PROTOPICT or AVDRQ_OWNPIC is set +} AVATARDRAWREQUEST; + +#define CACHE_BLOCKSIZE 20 + +#define AVS_MODULE "AVS_Settings" // db settings module path +#define PPICT_MODULE "AVS_ProtoPics" // protocol pictures are saved here + +// obtain the bitmap handle of the avatar for the given contact +// wParam = (HANDLE)hContact +// lParam = 0; +// returns: pointer to a struct avatarCacheEntry *, NULL on failure +// if it returns a failure, the avatar may be ready later and the caller may receive +// a notification via ME_AV_AVATARCHANGED +// DONT modify the contents of the returned data structure + +#define MS_AV_GETAVATARBITMAP "SV_Avatars/GetAvatar" + +// obtain a avatar cache entry for one of my own avatars +// wParam = 0 +// lParam = (char *)szProto (protocol for which we need to obtain the own avatar information). Use "" to global +// returns: pointer to a struct avatarCacheEntry *, NULL on failure +// DONT modify the contents of the returned data structure + +#define MS_AV_GETMYAVATAR "SV_Avatars/GetMyAvatar" + +// protect the current contact picture from being overwritten by automatic +// avatar updates. Actually, it only backups the contact picture filename +// and will used the backuped version until the contact picture gets unlocked +// again. So this service does not disable avatar updates, but it "fakes" +// a locked contact picture to the users of the GetAvatar service. +// +// wParam = (HANDLE)hContact +// lParam = 1 -> lock the avatar, lParam = 0 -> unlock + +#define MS_AV_PROTECTAVATAR "SV_Avatars/ProtectAvatar" + +// set (and optionally protect) a local contact picture for the given hContact +// +// wParam = (HANDLE)hContact +// lParam = either a full picture filename or NULL. If lParam == NULL, the service +// will open a file selection dialog. + +#define MS_AV_SETAVATAR "SV_Avatars/SetAvatar" + +// set a local picture for the given protocol +// +// wParam = (char *) protocol name or NULL for all protocols +// lParam = either a full picture filename or NULL. If lParam == NULL, the service +// will open a file selection dialog. If lParam == "" the avatar will be removed + +#define MS_AV_SETMYAVATAR "SV_Avatars/SetMyAvatar" + +// see if is possible to set the avatar for the expecified protocol +// +// wParam = (char *) protocol name +// lParam = 0 +// return = 1 if can set, 0 if can't + +#define MS_AV_CANSETMYAVATAR "SV_Avatars/CanSetMyAvatar" + +// Call avatar option dialog for contact +// +// wParam = (HANDLE)hContact + +#define MS_AV_CONTACTOPTIONS "SV_Avatars/ContactOptions" + +// draw an avatar picture +// +// wParam = 0 (not used) +// lParam = AVATARDRAWREQUEST *avdr +// draw a contact picture to a destination device context. see description of +// the AVATARDRAWREQUEST structure for more information on how to use this +// service. +// return value: 0 -> failure, avatar probably not available, or not ready. The drawing +// service DOES schedule an avatar update so your plugin will be notified by the ME_AV_AVATARCHANGED +// event when the requested avatar is ready for use. +// 1 -> success. avatar was found and drawing should be ok. +// -1 -> global avatar is incosistent + +#define MS_AV_DRAWAVATAR "SV_Avatars/Draw" + +// fired when a contacts avatar cached by avs changes +// it includes changes made by the user +// wParam = hContact +// lParam = struct avatarCacheEntry *cacheEntry +// the event CAN pass a NULL pointer in lParam which means that the avatar has changed, +// but is no longer valid (happens, when a contact removes his avatar, for example). +// DONT DESTROY the bitmap handle passed in the struct avatarCacheEntry * +// +// It is also possible that this event passes 0 as wParam (hContact), in which case, +// a protocol picture (pseudo - avatar) has been changed. + +#define ME_AV_AVATARCHANGED "SV_Avatars/AvatarChanged" + + +typedef struct _contactAvatarChangedNotification { + int cbSize; // sizeof() + HANDLE hContact; // this might have to be set by the caller too + int format; // PA_FORMAT_* + char filename[MAX_PATH]; // full path to filename which contains the avatar + char hash[128]; // avatar hash +} CONTACTAVATARCHANGEDNOTIFICATION; + +// fired when the contacts avatar is changed by the contact +// wParam = hContact +// lParam = struct CONTACTAVATARCHANGENOTIFICATION *cacn +// the event CAN pass a NULL pointer in lParam which means that the contact deleted its avatar + +#define ME_AV_CONTACTAVATARCHANGED "SV_Avatars/ContactAvatarChanged" + +// fired when one of our own avatars was changed +// wParam = (char *)szProto (protocol for which a new avatar was set) +// lParam = AVATARCACHEENTRY *ace (new cache entry, NULL if the new avatar is not valid) + +#define ME_AV_MYAVATARCHANGED "SV_Avatars/MyAvatarChanged" + +// Service to be called by protocols to report an avatar has changed. Some avatar changes +// can be detected automatically, but some not (by now only Skype ones) +// wParam = (char *)szProto (protocol for which a new avatar was set) +// lParam = 0 + +#define MS_AV_REPORTMYAVATARCHANGED "SV_Avatars/ReportMyAvatarChanged" + + + +// Bitmap services ////////////////////////////////////////////////////////////////////// + +// Load an image +// wParam = NULL +// lParam = filename +#define MS_AV_LOADBITMAP32 "SV_Avatars/LoadBitmap32" + +// Save an HBITMAP to an image +// wParam = HBITMAP +// lParam = full path of filename +#define MS_AV_SAVEBITMAP "SV_Avatars/SaveBitmap" +#define MS_AV_SAVEBITMAPW "SV_Avatars/SaveBitmapW" + +#if defined(UNICODE) + #define MS_AV_SAVEBITMAPT MS_AV_SAVEBITMAPW +#else + #define MS_AV_SAVEBITMAPT MS_AV_SAVEBITMAP +#endif + +// Returns != 0 if can save that type of image, = 0 if cant +// wParam = 0 +// lParam = PA_FORMAT_* // image format +#define MS_AV_CANSAVEBITMAP "SV_Avatars/CanSaveBitmap" + +// Returns a copy of the bitmap with the size especified or the original bitmap if nothing has to be changed +// wParam = ResizeBitmap * +// lParam = NULL +#define MS_AV_RESIZEBITMAP "SV_Avatars/ResizeBitmap" + +/* + * flags for internal use ONLY + */ + +#define MC_ISMASTERCONTACT 0x01 +#define MC_ISSUBCONTACT 0x02 +#define AVH_MUSTNOTIFY 0x04 // node->dwFlags (loader thread must notify avatar history about change/delete event) +#define AVS_DELETENODEFOREVER 0x08 + + + +// Protocol services ////////////////////////////////////////////////////////////////////// + +/* +wParam=0 +lParam=(const char *)Avatar file name or NULL to remove the avatar +return=0 for sucess +*/ +#define PS_SETMYAVATAR "/SetMyAvatar" + +/* +wParam=(char *)Buffer to file name +lParam=(int)Buffer size +return=0 for sucess +*/ +#define PS_GETMYAVATAR "/GetMyAvatar" + + +#define PIP_NONE 0 +#define PIP_SQUARE 1 + +// Avatar image max size +// lParam = (POINT*) maxSize (use -1 for no max) +// return 0 for success +#define AF_MAXSIZE 1 + +// Avatar image proportion +// lParam = 0 +// return or of PIP_* +#define AF_PROPORTION 2 + +// Avatar format supported when setting avatars +// lParam = PA_FORMAT_* +// return = 1 (supported) or 0 (not supported) +#define AF_FORMATSUPPORTED 3 + +// Avatars are enabled for protocol? +// lParam = 0 +// return = 1 (avatars ready) or 0 (disabled) +#define AF_ENABLED 4 + +// This protocol don't need delays for fetching contact avatars +// lParam = 0 +// return = 1 (don't need) or 0 (need) +#define AF_DONTNEEDDELAYS 5 + +// Avatar file max size +// return size in bytes (0 for no limit) +#define AF_MAXFILESIZE 6 + +// The amount of time avs should wait after a download avatar failed for a contact +// lParam = 0 +// return = the time, in ms +#define AF_DELAYAFTERFAIL 7 + +// Fetching avatars is always possible and allowed +// lParam = 0 +// return = 1 (always) or 0 (depending on our or contacts status mode) +#define AF_FETCHALWAYS 8 + + +/* +Query avatar caps for a protocol +wParam = One of AF_* +lParam = See descr of each AF_* +return = See descr of each AF_*. Return 0 by default +*/ +#define PS_GETAVATARCAPS "/GetAvatarCaps" + + + +#endif diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_chat.h b/plugins/!NotAdopted/WinPopup/sdk/m_chat.h new file mode 100644 index 0000000000..e3cd416c6d --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_chat.h @@ -0,0 +1,685 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 JГ¶rgen Persson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + + +/* + This plugin provides event driven chat rooms for protocols that wish to use it. + It is built for IRC, which I also develop and is naturally biased towards IRC, + but it should work very well with other protocols too. I will try to explain as + careful as possible in this document how to use chat.dll + + -- General guidelines -- + + There is ONE rule a protocol MUST follow to use this: + + 1. Do NOT touch hContacts that has a byte "ChatRoom" set to ANYTHING other than 0! (Could be 1, 2, 3, ...) + This is because chat.dll adds contacts to the clist using the protocol name + supplied by the protocol. But this will naturally not work well if the + protocol also tampers with the contacts. The value of the BYTE indicates which type of + window/contact it is (see the GCW_* flags below). There is two exceptions to this rule: + + * You should continue to handle the right click menu items of these + contacts as usual, by hooking the menu prebuild hook etc. Chat.dll can not + handle this in an efficient manner! + + * You should also handle when the user deletes the contact/room from the + contact list, as the protocol will then most likely have to send some message + to the server that the user has left the room. + + NOTE. Chat keeps its own copies of strings passed. + + + * * Example of implementing this rule * *: + * * This is a code snippet that is common in protocols * *: + + + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) + { + ... do something with the hContact here; + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + + + * * You should do this instead * *: + + + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) + { + if (DBGetContactSettingByte(hContact, PROTONAME, "ChatRoom", 0) == 0) + { + ... do something with the hContact here; + } + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + + There is not more to it than that! To recapitulate: do NOT touch contacts where the + BYTE "ChatRoom" is set to anything other than 0, + + + + + + + OK, enough of the precautions, HOW DO YOU USE CHAT? In short you need to do FOUR things: + + 1. REGISTER your protocol with Chat + Only registered protocols can use Chat + + 2. CREATE SESSIONS when your protocol are joining a group chat room. (One per room joined) + These sessions will be put on the contact-list and are managed totally by chat. + This is the reason you must obey to the "precautions" I mentioned above. + Do not tamper directly with Chat's hContacts. Use Services provided by Chat instead. + + 3. SEND EVENTS to the sessions created in #3. + These events reflect users joining/leaving/speaking etc. + + 4. DESTROY SESSIONS when the user leaves the room (ie the session is not needed anymore). + + These four points are implemented in three services: MS_GC_REGISTER, MS_GC_NEWSESSION + and MS_GC_EVENT. +*/ + + +//------------------------- SERVICES ------------------------ +/* + Step 1. -- REGISTER with Chat -- + + The first thing that a protocol need to do is register with Chat. This is best done + when ALL modules has loaded (ME_SYSTEM_MODULESLOADED). The registration is + needed to make sure that the protocol obey rule 1 mentioned above, but also to + set protocol specific preferences. + + * Use MS_GC_REGISTER like this: CallService(MS_GC_REGISTER, 0, (LPARAM)(GCREGISTER *) &gcr; + + * returns 0 on success or error code on failure. +*/ + +// Flags +#define GC_BOLD 0x0001 //enable the 'bold' button +#define GC_ITALICS 0x0002 //enable the 'italics' button +#define GC_UNDERLINE 0x0004 //enable the 'underline' button +#define GC_COLOR 0x0008 //enable the 'foreground color' button +#define GC_BKGCOLOR 0x0010 //enable the 'background color' button +#define GC_ACKMSG 0x0020 //the protocol must acknowlege messages sent +#define GC_TYPNOTIF 0x0040 //NOT SUPPORTED YET! Enable typing notifications. +#define GC_CHANMGR 0x0080 //enable the 'channel settings' button +#define GC_SINGLEFORMAT 0x0100 //the protocol supports only 1 formatting per message +#define GC_FONTSIZE 0x0200 //enable font size selection + +#define GC_UNICODE 0x01000 //NOT SUPPORTED YET! Enable unicode (if chat supports it), + //Pass UNICODE instead of ASCII. Note that + //registration will fail if the unicode version of chat is not installed +#if defined( _UNICODE ) + #define GC_TCHAR GC_UNICODE +#else + #define GC_TCHAR 0 +#endif + +// Error messages +#define GC_REGISTER_WRONGVER 1 //You appear to be using the wrong version of this API. Registration failed. +#define GC_REGISTER_ERROR 2 //An internal error occurred. Registration failed. +#define GC_REGISTER_NOUNICODE 3 //MS_GC_REGISTER returns this error if the Unicode version of chat + //is not installed and GC_UNICODE is set. Registration failed + +// GCREGISTER struct +typedef struct { + int cbSize; //Set to sizeof(GCREGISTER); + DWORD dwFlags; //Use GC_* flags above to indicate features supported + const char* pszModule; //This MUST be the protocol name as registered with Miranda IM + union { + const char* pszModuleDispName; //This is the protocol's real name as it will be displayed to the user + const TCHAR* ptszModuleDispName; // used if GC_TCHAR flag is passed + }; + int iMaxText; //Max message length the protocol supports. Will limit the typing area input. 0 = no limit + int nColors; //Number of colors in the colorchooser menu for the color buttons. Max = 100 + COLORREF* pColors; //pointer to the first item in a static COLORREF array containing the colors + //that should be showed in the colorchooser menu. + //ie: COLORREF crCols[nColors]; + // pColors = &crCols[0]; +} + GCREGISTER; + +#define MS_GC_REGISTER "GChat/Register" + +/* + Step 2. -- CREATE a new SESSION -- + + Create a new session (chat room) and set various settings related to it. + The chat room will not be shown to the user until the 'set up' phase is + completed and SESSION_INITDONE is sent. See the MS_GC_EVENT for that. + + * Use MS_GC_NEWSESSION like this: CallService(MS_GC_NEWSESSION, 0, (LPARAM)(GCSESSION *) &gcr; + + * returns 0 on success or error code on failure +*/ + + +// Session type +#define GCW_CHATROOM 1 // the session is a dedicated multi user chat room. ex "IRC channels". + // A hContact will be added for the session +#define GCW_SERVER 2 // the session is used as a network console. ex "IRC server window" + // A hContact will be added for the session, but it will default to being hidden (on the CList) +#define GCW_PRIVMESS 3 // NOT SUPPORTED YET! the session is a 1 to 1 session, but with additional + // support for adding more users etc. ex "MSN session". + + + +// Error messages +#define GC_NEWSESSION_WRONGVER 1 //You appear to be using the wrong version of this API. +#define GC_NEWSESSION_ERROR 2 //An internal error occurred. + + +// GCREGISTER structure +typedef struct { + int cbSize; //Set to sizeof(GCSESSION); + int iType; //Use one of the GCW_* flags above to set the type of session + const char *pszModule; //The name of the protocol owning the session (the same as pszModule when you register) + union { + const char* pszName; //The name of the session as it will be displayed to the user + const TCHAR* ptszName; + }; + union { + const char* pszID; //The unique identifier for the session. + const TCHAR* ptszID; + }; + union { + const char* pszStatusbarText; //Optional text to set in the statusbar of the chat room window, or NULL. + const TCHAR* ptszStatusbarText; + }; + DWORD dwFlags; + DWORD dwItemData; //Set user defined data for this session. Retrieve it by using the GC_EVENT_GETITEMDATA event + } GCSESSION; +#define MS_GC_NEWSESSION "GChat/NewChat" + + + + + + +/* + Step 3 -- SEND an EVENT -- + + Events is what drives Chat! After having created the session in Step 2 + it is time to make it work for real. Follow these guidelines: + + 1. Start off by telling Chat what possible statuses a user can have (in the nicklist) + by sending GC_EVENT_ADDGROUP as many times as needed. Also supply an icon + to go with this status. Ex "Voice status" on IRC + + 2.Then send "JOIN" events (GC_EVENT_JOIN) to populate the user list. + You will need to send one event per user that should be added. As long as + SESSION_INITDONE has not been sent these events will not show up in the log. + + 3.When you are done with filling the user list it is a good time to end + the set up phase and make the window visible by calling GC_EVENT_CONTROL event + with wParam = SESSION_INITDONE. + + 4.You will also want to send a GC_EVENT_CONTROL with wParam = SESSION_ONLINE to + make the statusbar and the CList item go to "online" status + + You have now set up the session and made it active. A CList hContact has been added + to the contact list and a chat room window is associated to the session. Send EVENTS to + Chat users speaking, users joining and so on. See below for full + list of what events are possible. + + IMPORTANT: For sending events you'll use the GCEVENT and GCDEST structures. A GCDEST + structure pointer is passed inside GCEVENT and it tells Chat what event type it is + and what session it is related to. The GCDEST structure and its members are ALWAYS + used (but the members can be NULL in some occasions). Depending on what type of event + you are sending, the members of GCEVENT have different usage. Each event and how to + use the members are discussed below. The "bAddToLog" and "time" members are always valid + and always mean the same. bAddToLog = TRUE means that the event is added to the disk log + (at least when this makes sense). This can be used by Jabber for instance, when + it needs to add channel history to the window, but without logging to disk. + The "time" member is the timestamp of the event.(Tip. use the function time(NULL) + to set the current time) + + NOTE. It is possible to send formatted text (bold, italics, underlined, foreground color + and background color) to Chat by using the following identifiers in the text (pszText): + + %cXX - set the foreground color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) + %C - reset foreground color to default + %fXX - set the background color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) + %F - reset the background color to default + %b - enable bold + %B - disable bold + %u - enable underlined + %U - disable underlined + %i - enable italics + %I - disable italics + %r - reset all to default + %% - escape the formatting. Translates to % + + IMPORTANT. If you have specified GC_COLOR or GC_BKGCOLOR when you registered you can expect to + get these identifiers in the text you receive from Chat as well. Make sure % is ALWAYS + translated to %% in text you send to Chat to avoid accidental formatting. + NOTE. You will not get %cRRRGGGBBB back, instead you will get the index of the colour as + registered with GC_REGISTER. Eg %c3 (the fourth colour of your index) + + * Use MS_GC_EVENT like this: CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce; + + * returns 0 on success or error code on failure + +*/ + +// * List of possible events to send to Chat. Unlisted members are not valid * +// * for the event. Listed members are mandatory unless otherwise specified * + + +// GC_EVENT_JOIN - " has joined" (A user is joining the session) +// pszNick - Display name +// pszUID - Unique identifier of the user +// pszStatus - Which status does the user have. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +// bIsMe - Set to TRUE if it is the Miranda user +// Chat needs to know which user in the userlist that is "self" +// It cannot highlight a message containing the "own" nick without this info +// NOTE. if time == NULL, then the event will not be shown in the message log +#define GC_EVENT_JOIN 0x0001 + +// GC_EVENT_PART - " has left: " (A user left the session) +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Optional part message, can be NULL +#define GC_EVENT_PART 0x0002 + +// GC_EVENT_QUIT - " disconnected: pszText" (A user disconnected from the network) +// pszID(in GCDEST) - Should be NULL as a disconnect event is global. +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Optional disconnect message, can be NULL +#define GC_EVENT_QUIT 0x0004 + +// GC_EVENT_KICK - " kicked : " (A user is kicking another user from the room) +// pszNick - Display name of the one being being kicked +// pszUID - Unique identifier of the one being kicked +// pszStatus - Name of user who is doing the kicking +// pszText - Optional kick message, can be NULL +#define GC_EVENT_KICK 0x0008 + +// GC_EVENT_NICK - " is now known as " (A user changed his name) +// NOTE, see GC_EVENT_CHUID also +// pszID(in GCDEST) - Should be NULL as a nick change event is global. +// pszNick - Old display name +// pszUID - Unique identifier +// pszText - New display name of the user. Color codes are not valid +#define GC_EVENT_NICK 0x0010 + +// GC_EVENT_NOTICE - "Notice from : " (An IRC type notice) +// pszID(in GCDEST) - Should be NULL to send to the active window +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Notice text +#define GC_EVENT_NOTICE 0x0020 + +// GC_EVENT_MESSAGE - ": (A user is speaking) +// pszNick - Display name +// pszUID - Unique identifier +// bIsMe - Set to TRUE if it is the Miranda user +// pszText - Message text. +#define GC_EVENT_MESSAGE 0x0040 + +// GC_EVENT_TOPIC - "Topic is (Set by: " (The room topic was changed/set) +// pszNick - Optional display name of who set the topic, can be NULL +// pszUID - Optional unique identifier of who set the topic, can be NULL +// pszText - Topic text +#define GC_EVENT_TOPIC 0x0080 + +// GC_EVENT_INFORMATION (Informational text) Ex a server response to a /WHO command in IRC +// pszID(in GCDEST) - NULL to send to the active window +// pszText - Information text +#define GC_EVENT_INFORMATION 0x0100 + +// GC_EVENT_ACTION - " " (An IRC Style action event) +// pszNick - Display name +// pszUID - Unique identifier +// bIsMe - Set to TRUE if it is the Miranda user +// pszText - Message text. +#define GC_EVENT_ACTION 0x0200 + +// GC_EVENT_ADDSTATUS - " enables '' for " (A status change has occured for a user) +// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. +// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" +// pszNick - Display name of the one who receives a new status +// pszUID - Unique identifier of the one who receives a new status +// pszText - The display name of the one who is setting the status. Color codes are not valid +// pszStatus - The status. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +#define GC_EVENT_ADDSTATUS 0x0400 + +// GC_EVENT_REMOVESTATUS - " disables '' for " (A status change has occured for a user) +// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. +// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" +// pszNick - Display name of the one who got a status mode disabled +// pszUID - Unique identifier of the one who got a status mode disabled +// pszText - The display name of the one disabling the status. Color codes are not valid +// pszStatus - The status. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +#define GC_EVENT_REMOVESTATUS 0x0800 + +// GC_EVENT_CHUID - not shown in the log (Change the unique identifier of a contact) +// pszID(in GCDEST) - Should be NULL as a unique id's are global. +// pszUID - The current unique identifier +// pszText - The new unique identifier. Color codes are not valid +#define GC_EVENT_CHUID 0x1000 + +// GC_EVENT_CHANGESESSIONAME - not shown in the log (Change the display name of a session) +// pszText - The new name. Color codes are not valid +#define GC_EVENT_CHANGESESSIONAME 0x1001 + +// GC_EVENT_ADDGROUP - not shown in the log (Add a possible status mode to the nicklist, ex IRC uses "Op", "Voice", "Normal" etc ) +// NOTE. When adding several statuses, start with the highest status +// pszStatus - The new group name +// dwItemData - Optional HICON handle to a 10x10 icon. Set to NULL to use the built in icons. +#define GC_EVENT_ADDGROUP 0x1002 + +// GC_EVENT_SETITEMDATA & GC_EVENT_SETITEMDATA - not shown in the log (Get/Set the user defined data of a session) +// dwItemData - The itemdata to set or get +#define GC_EVENT_SETITEMDATA 0x1003 +#define GC_EVENT_GETITEMDATA 0x1004 + +// GC_EVENT_SETSBTEXT - not shown in the log (Set the text of the statusbar for a chat room window) +// pszText - Statusbar text. Color codes are not valid +#define GC_EVENT_SETSBTEXT 0x1006 + +// GC_EVENT_ACK - not shown in the log (Acknowledge a outgoing message, when GC_ACKMSG is set +#define GC_EVENT_ACK 0x1007 + +// GC_EVENT_SENDMESSAGE - not shown in the log ("Fake" a message from a chat room as if the user had typed it). Used by IRC to broadcast /AME and /AMSG messages +// pszText - The text +#define GC_EVENT_SENDMESSAGE 0x1008 + +// GC_EVENT_SETSTATUSEX - not shown in the log (Space or tab delimited list of pszUID's to indicate as away). +// Used by IRC to mark users as away in the nicklist. If UIDs can contain spaces, use tabs +// pszText - Space or tab delimited list of pszUID's + +#define GC_SSE_ONLYLISTED 0x0001 // processes only listed contacts, resets all contacts otherwise +#define GC_SSE_ONLINE 0x0002 // displays a contact online, otherwise away +#define GC_SSE_TABDELIMITED 0x0004 // use tabs as delimiters + +#define GC_EVENT_SETSTATUSEX 0x1009 + +// GC_EVENT_SETCONTACTSTATUS - sets status icon for contact +// pszUID - Unique identifier of the one who receives a new status +// dwItemData - (DWORD)ID_STATUS_* or zero to remove status icon +#define GC_EVENT_SETCONTACTSTATUS 0x100A + +// GC_EVENT_CONTROL - not shown in the log (Control window associated to a session and the session itself) +// NOTE 1: No members of GCEVENT are used, send one of the below flags in wParam instead, +// Ex CallService(GC_EVENT_CONTROL, SESSION_INITDONE, (LPARAM)&gce); +// NOTE 2: The first four control events are the only ones you should use most likely! +// The ones below them are used by IRC to join channels hidden or maximized and show the server window from the system menu. +// The SESSION_VISIBLE, SESSION_HIDDEN, SESSION_MAXIMIZE and SESSION_MINIMIZE events CAN replace SESSION_INITDONE but I urge you not to +// do that as it will override any settings the user has made in the Chat options +// NOTE 3: If pszID (of GCDEST) = NULL then this message will be broadcasted to all sessions, which can be usefule for terminating +// all sessions when the protocol was disconnected +#define SESSION_INITDONE 1 //send this when the session is fully set up (all users have ben added to the nicklist) +#define SESSION_TERMINATE 7 //send to terminate a session and close the window associated with it +#define SESSION_OFFLINE 8 //send to set the session as "online" (hContact is set to Online etc) +#define SESSION_ONLINE 9 //send to set the session as "offline" (hContact is set to Offline etc) +//------------ +#define WINDOW_VISIBLE 2 //make the room window visible +#define WINDOW_HIDDEN 3 //close the room window. Session is not terminated. +#define WINDOW_MAXIMIZE 4 //make the room window maximized +#define WINDOW_MINIMIZE 5 //make the room window minimized +#define WINDOW_CLEARLOG 6 //clear the log of the room window + +#define GC_EVENT_CONTROL 0x1005 + +// Error messages +#define GC_EVENT_WRONGVER 1 //You appear to be using the wrong version of this API. +#define GC_EVENT_ERROR 2 //An internal error occurred. + +// The GCDEST structure. It is passed to Chat inside GCEVENT. +typedef struct { + char* pszModule; //Name of the protocol (same as you registered with) + union { + char* pszID; //Unique identifier of the session, or NULL to broadcast to all sessions as specified above + TCHAR* ptszID; + }; + int iType; //Use GC_EVENT_* as defined above. Only one event per service call. +} GCDEST; + + +// The GCEVENT structure +typedef struct { + int cbSize; // Set to sizeof(GCEVENT); + GCDEST* pDest; // pointer to a GCDEST structure which specifies the session to receive the event + union { + const char *pszText; // usage depends on type of event, max 2048 characters + const TCHAR *ptszText; + }; + union { + const char* pszNick; // usage depends on type of event + const TCHAR* ptszNick; + }; + union { + const char* pszUID; // usage depends on type of event, Do NOT use spaces for unique user identifiers. + const TCHAR* ptszUID; + }; + union { + const char* pszStatus; // usage depends on type of event + const TCHAR* ptszStatus; + }; + union { + const char* pszUserInfo; // Additional user information that is displayed after the nickname. + const TCHAR* ptszUserInfo; + }; + // IRC use it to display a hostmask for JOIN, PART (and more) events. + BOOL bIsMe; // Is this event from the Miranda user? + DWORD dwFlags; // event flags: GCEF_ADDTOLOG, GC_UNICODE + + // FALSE any other time than when initializing the window (before sending SESSION_INITDONE) + DWORD_PTR dwItemData; // User specified data. + DWORD time; // Timestamp of the event +} + GCEVENT; + +#define MS_GC_EVENT "GChat/NewEvent" + +#define GCEF_ADDTOLOG 0x0001 + +// OK! That was about everything that you need to know about for operating Chat in a basic way. +// There are however some more things you will need to know about. Some you may use and some you may not need, + +/* + -- GETTING info about a SESSION or session data -- + + Use this service to get information on different aspects of the sessions that are registered with Chat. + + * Use MS_GC_GETINFO like this: CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)(char *) pszModule); + + * returns -1 on failure and the sessioncount on success +*/ + +#define MS_GC_GETSESSIONCOUNT "GChat/GetCount" + +/* + -- GETTING info about a SESSION or session data -- + + Use this service to get information on different aspects of the sessions that are registered with Chat. + + * Use MS_GC_GETINFO like this: CallService(MS_GC_GETINFO, 0, (LPARAM)(GC_INFO *) &gci; + + * returns 0 on success or error code on failure +*/ + +// Flags +#define BYINDEX 0x0001 // iItem is valid and should contain the index of the session to get +#define BYID 0x0002 // pszID is valid and should contain the ID of the session to get. This is the default if no +#define HCONTACT 0x0004 // hContact is valid +#define DATA 0x0008 // wItemData is valid +#define ID 0x0010 // pszID is valid. +#define NAME 0x0020 // pszName is valid +#define TYPE 0x0040 // iType is valid +#define COUNT 0x0080 // iCount is valid +#define USERS 0x0100 // pszUsers is valid + + +// The GC_INFO structure +typedef struct { + DWORD Flags; // use a combination of the above flags + int iItem; // session type (GCW_*) + int iType; // session type (GCW_*) + char* pszModule; // the module name as registered in MS_GC_REGISTER + TCHAR* pszID; // unique ID of the session + TCHAR* pszName; // display name of the session + DWORD_PTR dwItemData; // user specified data. + int iCount; // count of users in the nicklist + char* pszUsers; // space separated string containing the UID's of the users in the user list. + // NOTE. Use Mirandas mmi_free() on the returned string. + HANDLE hContact; // hContact for the session (can be NULL) +} + GC_INFO; + +#define MS_GC_GETINFO "GChat/GetInfo" + +//------------------------- HOOKS ------------------------ +/* + -- user interaction -- + Hook this to receive notifications about when user take actions in a chat room window. + Check for the below flags to find out what type of user interaction it is. See the + to find out which members of GCHOOK that are valid. + + * wParam=0 + * lParam=(LPARAM)(GCEVENT *)pgch + + * Returning nonzero from your hook will stop other hooks from being called. +*/ +#define GC_USER_MESSAGE 1 // user sent a message, with \n delimiting lines, pszText contains the text. +#define GC_USER_CHANMGR 2 // user clicked the settings button in a chat room +#define GC_USER_LOGMENU 3 // user has selected a message log menu item, dwData is valid. See ME_GC_BUILDMENU +#define GC_USER_NICKLISTMENU 4 // user has selected a userlist menu item, valid members: dwData. See ME_GC_BUILDMENU +#define GC_USER_TYPNOTIFY 5 // NOT IMPLEMENTED YET! user is typing +#define GC_USER_PRIVMESS 6 // user requests to send a private message to a user. pszUID is valid +#define GC_USER_LEAVE 8 // user requests to leave the session +#define GC_USER_CLOSEWND 9 // user closed the window (this is usually not an indication that the protocol + // should take action, but MSN may want to terminate the session here) +#define GC_SESSION_TERMINATE 7 // the session is about to be terminated, the "user defined data" is passed in dwData, which can be good free'ing any allocated memory. +#define ME_GC_EVENT "GChat/OutgoingEvent" + +typedef struct { + GCDEST* pDest; // pointer to a GCDEST structure which specifies from which session the hook was triggered + union { + char* pszText; // usage depends on type of event + TCHAR* ptszText; + }; + union { + char* pszUID; // unique identifier, usage depends on type of event + TCHAR* ptszUID; + }; + DWORD_PTR dwData; // user defined data, usage depends on type of event +} + GCHOOK; + +/* + -- Build the pop up menus -- + The user wants to show a right click (popup) menu and your protocol should tell what + items should be added to the menu. You should create a static array of struct gc_item's. + When you get this notification you should set "nItems" to the number of gc_item's + you want to show on the user's popup menu and then set the "Item" member to point to that array. + + * wParam=0 + * lParam=(LPARAM)(GCMENUITEM *)gcmi + + Returning nonzero from your hook will stop other hooks from being called. + +*/ + +// type of item to add to the popup menu +#define MENU_NEWPOPUP 1 // add submenu +#define MENU_POPUPITEM 2 // add item to current submenu +#define MENU_POPUPSEPARATOR 3 // add separator to current submenu +#define MENU_SEPARATOR 4 // add separator to menu +#define MENU_ITEM 5 // add item + +// Added in Miranda IM 0.8.0.6+ +#define MENU_POPUPCHECK 6 // add checked item to current submenu +#define MENU_CHECK 7 // add checked item +#define MENU_POPUPHMENU 8 // add custom submenu to current submenu, use dwID to specify HMENU +#define MENU_HMENU 9 // add custom submenu, use dwID to specify HMENU + +// type of menu that is being requested +#define MENU_ON_LOG 1 // pop up menu on the message log +#define MENU_ON_NICKLIST 2 // pop up menu on the user list + +// contains info on a menuitem to be added +struct gc_item { + TCHAR* pszDesc; // Textual description of the menu item to add + DWORD dwID; // when/if the user selects this menu item this + // value will be returned via the above hook, GC_USER_LOGMENU + // or GC_USER_NICKLISTMENU. Must not be 0 and must be unique. + int uType; // What kind of menu item is it? Use MENU_* flags above + BOOL bDisabled; // should the menu item be shown as disabled +}; + +typedef struct { + char * pszModule; // Contains the protocol name, do NOT change. + TCHAR* pszID; // The unique identifier of the session that triggered the hook, do NOT change. + TCHAR* pszUID; // Contains the unique identifier if Type = MENU_ON_NICKLIST. do NOT change. + int Type; // Type of menu. MENU_ON_* flags used. do NOT change. + int nItems; // Set this to the number of menu items you want to add + struct gc_item* Item; // pointer to the first in the array of gc_item's +} + GCMENUITEMS; + +#define ME_GC_BUILDMENU "GChat/BuildMenu" + +/* + * Example of how to add 2 items to the popup menu for the userlist * + + GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; + if (gcmi->Type == MENU_ON_NICKLIST) + { + static struct gc_item Item[] = { + {Translate("User &details"), 1, MENU_ITEM, FALSE}, + {Translate("&Op"), 2, MENU_POPUPITEM, FALSE}, + }; + + gcmi->nItems = sizeof(Item)/sizeof(Item[0]); + gcmi->Item = &Item[0]; + gcmi->Item[gcmi->nItems-1].bDisabled = bFlag; + + return 0; + } +*/ + +////////////////////////////////////////////////////////////////////////// +// Get Chat ToolTip Text for buddy +// wParam = (WPARAM)(TCHAR*) roomID parentdat->ptszID +// lParam = (WPARAM)(TCHAR*) userID ui1->pszUID +// result (int)(TCHAR*)mir_tstrdup("tooltip text") +// returns pointer to text of tooltip and starts owns it +#define MS_GC_PROTO_GETTOOLTIPTEXT "/GetChatToolTipText" diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_clist.h b/plugins/!NotAdopted/WinPopup/sdk/m_clist.h new file mode 100644 index 0000000000..c0bbd3853a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_clist.h @@ -0,0 +1,637 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_CLIST_H__ +#define M_CLIST_H__ 1 + +#ifdef _MSC_VER + #pragma warning(disable:4201 4204) +#endif + +#include "statusmodes.h" + +#if defined _STATIC + typedef struct _tagIntMenuItem* HGENMENU; +#else + DECLARE_HANDLE(HGENMENU); +#endif + +//sent when the user asks to change their status +//wParam=new status, from statusmodes.h +//lParam=protocol name, NULL if for all protocols (added in v0.3.1alpha) +//also sent due to a ms_clist_setstatusmode call +#define ME_CLIST_STATUSMODECHANGE "CList/StatusModeChange" + +//force a change of status mode +//wParam=new status, from statusmodes.h +#define MS_CLIST_SETSTATUSMODE "CList/SetStatusMode" + +//get the current status mode +//wParam=lParam=0 +//returns the current status +//This is the status *as set by the user*, not any protocol-specific status +//All protocol modules will attempt to conform to this setting at all times +#define MS_CLIST_GETSTATUSMODE "CList/GetStatusMode" + +//gets a textual description of the given status mode (v0.1.0.1+) +//wParam=status mode, from statusmodes.h +//lParam=flags, below +//returns a static buffer of the description of the given status mode +//returns NULL if the status mode was unknown +#define GSMDF_PREFIXONLINE 1 //prefix "Online: " to all status modes that + //imply online, eg "Online: Away" +#define GCMDF_UNICODE 2 //will return TCHAR* instead of char* +#if defined( _UNICODE ) + #define GCMDF_TCHAR GCMDF_UNICODE //will return TCHAR* instead of char* +#else + #define GCMDF_TCHAR 0 //will return char*, as usual +#endif +#define GSMDF_UNTRANSLATED 4 +#define MS_CLIST_GETSTATUSMODEDESCRIPTION "CList/GetStatusModeDescription" + +//add a new item to the main menu +//wParam=0 +//lParam=(LPARAM)(CLISTMENUITEM*)&mi +//returns a handle to the new item, or NULL on failure +//the service that is called when the item is clicked is called with +//wParam=0, lParam=hwndContactList +//dividers are inserted every 100000 positions +//pszContactOwner is ignored for this service. +//there is a #define PUTPOSITIONSINMENU in clistmenus.c which, when set, will +//cause the position numbers to be placed in brackets after the menu items + +// WARNING: do not use Translate(TS) for p(t)szName or p(t)szPopupName as they +// are translated by the core, which may lead to double translation. +// Use LPGEN instead which are just dummy wrappers/markers for "lpgen.pl". +typedef struct { + int cbSize; //size in bytes of this structure + union { + char* pszName; //[TRANSLATED-BY-CORE] text of the menu item + TCHAR* ptszName; //Unicode text of the menu item + }; + DWORD flags; //set of CMIF_* flags + int position; //approx position on the menu. lower numbers go nearer the top + union { + HICON hIcon; //icon to put by the item. If this was not loaded from + //a resource, you can delete it straight after the call + HANDLE icolibItem; //set CMIF_ICONFROMICOLIB to pass this value + }; + char* pszService; //name of service to call when the item gets selected + union { + char* pszPopupName; //[TRANSLATED-BY-CORE] name of the popup menu that this item is on. If this + TCHAR* ptszPopupName; //is NULL the item is on the root of the menu + HGENMENU hParentMenu; // valid if CMIF_ROOTHANDLE is set. NULL or (HGENMENU)-1 means the root menu + }; + + int popupPosition; //position of the popup menu on the root menu. Ignored + //if pszPopupName is NULL or the popup menu already + //existed + DWORD hotKey; //keyboard accelerator, same as lParam of WM_HOTKEY,0 for none + char *pszContactOwner; //contact menus only. The protocol module that owns + //the contacts to which this menu item applies. NULL if it + //applies to all contacts. If it applies to multiple but not all + //protocols, add multiple menu items or use ME_CLIST_PREBUILDCONTACTMENU +} CLISTMENUITEM; + +#define HGENMENU_ROOT (( HGENMENU )-1) + +#define CMIF_GRAYED 1 +#define CMIF_CHECKED 2 +#define CMIF_HIDDEN 4 //only works on contact menus +#define CMIF_NOTOFFLINE 8 //item won't appear for contacts that are offline +#define CMIF_NOTONLINE 16 // " online +#define CMIF_NOTONLIST 32 //item won't appear on standard contacts +#define CMIF_NOTOFFLIST 64 //item won't appear on contacts that have the 'NotOnList' setting +#define CMIF_ROOTHANDLE 384 //means that hParentMenu member is set + +#define CMIF_UNICODE 512 //will return TCHAR* instead of char* +#if defined( _UNICODE ) + #define CMIF_TCHAR CMIF_UNICODE //will return TCHAR* instead of char* +#else + #define CMIF_TCHAR 0 //will return char*, as usual +#endif + +#define CMIF_KEEPUNTRANSLATED 1024 // don't translate a menu item +#define CMIF_ICONFROMICOLIB 2048 // use icolibName instead of hIcon +#define CMIF_DEFAULT 4096 // this menu item is the default one + +// for compatibility. since 0.8.0 they both mean nothing +#define CMIF_ROOTPOPUP 128 //root item for new popup(save return id for childs) +#define CMIF_CHILDPOPUP 256 //child for rootpopup menu + +#define MS_CLIST_ADDMAINMENUITEM "CList/AddMainMenuItem" + +//add a new item to the user contact menus +//identical to clist/addmainmenuitem except when item is selected the service +//gets called with wParam=(WPARAM)(HANDLE)hContact +//pszContactOwner is obeyed. +//popup menus are not supported. pszPopupName and popupPosition are ignored. +//If ctrl is held down when right clicking, the menu position numbers will be +//displayed in brackets after the menu item text. This only works in debug +//builds. +#define MS_CLIST_ADDCONTACTMENUITEM "CList/AddContactMenuItem" +#define MS_CLIST_ADDSTATUSMENUITEM "CList/AddStatusMenuItem" + +//modify an existing menu item v0.1.0.1+ +//wParam=(WPARAM)(HANDLE)hMenuItem +//lParam=(LPARAM)(CLISTMENUITEM*)&clmi +//returns 0 on success, nonzero on failure +//hMenuItem will have been returned by clist/add*menuItem +//clmi.flags should contain cmim_ constants below specifying which fields to +//update. Fields without a mask flag cannot be changed and will be ignored +#define CMIM_NAME 0x80000000 +#define CMIM_FLAGS 0x40000000 +#define CMIM_ICON 0x20000000 +#define CMIM_HOTKEY 0x10000000 +#define CMIM_ALL 0xF0000000 +#define MS_CLIST_MODIFYMENUITEM "CList/ModifyMenuItem" + +//the context menu for a contact is about to be built v0.1.0.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//modules should use this to change menu items that are specific to the +//contact that has them +#define ME_CLIST_PREBUILDCONTACTMENU "CList/PreBuildContactMenu" + +//sets the service to call when a contact is double-clicked +//wParam=0 +//lParam=(LPARAM)(CLISTDOUBLECLICKACTION*)&dca +//contactType is one or more of the constants below +//pszService is called with wParam=hContact, lParam=0 +//pszService will only be called if there is no outstanding event on the +//selected contact +//returns 0 on success, nonzero on failure +//in case of conflicts, the first module to have registered will get the +//double click, no others will. This service will return success even for +//duplicates. +/* + Note: During development of 0.3.0.0 (2003/02/15) this service was completely dropped + by default it always returns 1 to mark failure, see ME_CLIST_DOUBLECLICKED for + a better implementation as a hook. +*/ +typedef struct { + int cbSize; + char *pszContactOwner; //name of protocol owning contact, or NULL for all + DWORD flags; //any of the CMIF_NOT... flags above + char *pszService; //service to call on double click +} CLISTDOUBLECLICKACTION; +#define MS_CLIST_SETDOUBLECLICKACTION "CList/SetDoubleClickAction" + +/* +wParam=(WPARAM)hContact +lParam=0 + +Event is fired when there is a double click on a CList contact, +it is upto the caller to check for the protocol & status +of the HCONTACT, it's not done for you anymore since it didn't make +sense to store all this information in memory, etc. + +*/ +#define ME_CLIST_DOUBLECLICKED "CList/DoubleClicked" +//gets the string that the contact list will use to represent a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=flags +//returns a pointer to the name, will always succeed, even if it needs to +//return "(Unknown Contact)" +//this pointer is to a statically allocated buffer which will be overwritten +//on every call to this service. Callers should make sure that they copy the +//information before they call this service again. +#define GCDNF_NOMYHANDLE 1 //will never return the user's custom name +#define GCDNF_UNICODE 2 //will return TCHAR* instead of char* +#define GCDNF_NOCACHE 4 //will not use the cache + +#if defined( _UNICODE ) + #define GCDNF_TCHAR GCDNF_UNICODE //will return TCHAR* instead of char* +#else + #define GCDNF_TCHAR 0 //will return char*, as usual +#endif + + //even if it's the one that should be displayed. v0.1.2.0+ + //v0.3.0.0+ if using GCDNF_NOMYHANDLE you must free your string +#define MS_CLIST_GETCONTACTDISPLAYNAME "CList/GetContactDisplayName" + +// Invalidates the display name cache +//wParam=(WPARAM)(HANDLE)hContact +//lParam=not used +#define MS_CLIST_INVALIDATEDISPLAYNAME "CList/InvalidateDiplayName" + +//adds an event to the contact list's queue +//wParam=0 +//lParam=(LPARAM)(CLISTEVENT*)cle +//The contact list will flash hIcon next to the contact hContact (use NULL for +//a system message). szServiceName will be called when the user double clicks +//the icon, at which point the event will be removed from the contact list's +//queue automatically +//pszService is called with wParam=(WPARAM)(HWND)hwndContactList, +//lParam=(LPARAM)(CLISTEVENT*)cle. Its return value is ignored. cle is +//invalidated when your service returns, so take copies of any important +//information in it. +//hDbEvent should be unique since it and hContact are the identifiers used by +//clist/removeevent if, for example, your module implements a 'read next' that +//bypasses the double-click. +typedef struct { + int cbSize; //size in bytes of this structure + HANDLE hContact; //handle to the contact to put the icon by + HICON hIcon; //icon to flash + DWORD flags; //...of course + union + { + HANDLE hDbEvent; //caller defined but should be unique for hContact + char * lpszProtocol; + }; + LPARAM lParam; //caller defined + char *pszService; //name of the service to call on activation + union { + char *pszTooltip; //short description of the event to display as a + TCHAR *ptszTooltip; //tooltip on the system tray + }; +} CLISTEVENT; +#define CLEF_URGENT 1 //flashes the icon even if the user is occupied, + //and puts the event at the top of the queue +#define CLEF_ONLYAFEW 2 //the icon will not flash for ever, only a few + //times. This is for eg online alert +#define CLEF_UNICODE 4 //set pszTooltip as unicode + +#define CLEF_PROTOCOLGLOBAL 8 //set event globally for protocol, hContact has to be NULL, + //lpszProtocol the protocol ID name to be set + +#if defined( _UNICODE ) + #define CLEF_TCHAR CLEF_UNICODE //will use TCHAR* instead of char* +#else + #define CLEF_TCHAR 0 //will return char*, as usual +#endif + +#define MS_CLIST_ADDEVENT "CList/AddEvent" + +//removes an event from the contact list's queue +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(HANDLE)hDbEvent +//returns 0 if the event was successfully removed, or nonzero if the event +//was not found +#define MS_CLIST_REMOVEEVENT "Clist/RemoveEvent" + +//gets the details of an event in the queue v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=iEvent +//returns a CLISTEVENT* on success, NULL on failure +//Returns the iEvent-th event from the queue for hContact, so iEvent=0 will +//get the event that will be got when the user clicks on that contact. +//Use hContact=INVALID_HANDLE_VALUE to search over all contacts, so iEvent=0 +//will get the event that will be got if the user clicks the systray icon. +#define MS_CLIST_GETEVENT "CList/GetEvent" + +//process a WM_MEASUREITEM message for user context menus v0.1.1.0+ +//wParam, lParam, return value as for WM_MEASUREITEM +//This is for displaying the icons by the menu items. If you don't call this +//and clist/menudrawitem whne drawing a menu returned by one of the three menu +//services below then it'll work but you won't get any icons +#define MS_CLIST_MENUMEASUREITEM "CList/MenuMeasureItem" + +//process a WM_DRAWITEM message for user context menus v0.1.1.0+ +//wParam, lParam, return value as for WM_MEASUREITEM +//See comments for clist/menumeasureitem +#define MS_CLIST_MENUDRAWITEM "CList/MenuDrawItem" + +//builds the context menu for a specific contact v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns a HMENU identifying the menu. This should be DestroyMenu()ed when +//finished with. +#define MS_CLIST_MENUBUILDCONTACT "CList/MenuBuildContact" + +//gets the image list with all the useful icons in it v0.1.1.0+ +//wParam=lParam=0 +//returns a HIMAGELIST +//the members of this image list are opaque, and you should trust what you +//are given +#define MS_CLIST_GETICONSIMAGELIST "CList/GetIconsImageList" +#define IMAGE_GROUPOPEN 11 +#define IMAGE_GROUPSHUT 12 + +//get the icon that should be associated with a contact v0.1.2.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns an index into the contact list imagelist. See clist/geticonsimagelist +//If the contact is flashing an icon, this function will not return that +//flashing icon. Use me_clist_contacticonchanged to get info about that. +#define MS_CLIST_GETCONTACTICON "CList/GetContactIcon" + +//The icon of a contact in the contact list has changed v0.1.2.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=iconId +//iconId is an offset into the clist's imagelist. See clist/geticonsimagelist +#define ME_CLIST_CONTACTICONCHANGED "CList/ContactIconChanged" + +/******************************* CLUI only *********************************/ + +// Stuff below here is ideally for the use of a CList UI module only. + +//get a handle to the main Miranda menu v0.1.1.0+ +//wParam=lParam=0 +//returns a HMENU. This need not be freed since it's owned by clist +#define MS_CLIST_MENUGETMAIN "CList/MenuGetMain" + +//get a handle to the Miranda status menu v0.1.1.0+ +//wParam=lParam=0 +//returns a HMENU. This need not be freed since it's owned by clist +#define MS_CLIST_MENUGETSTATUS "CList/MenuGetStatus" + + + + +//processes a menu selection from a menu v0.1.1.0+ +//wParam=MAKEWPARAM(LOWORD(wParam from WM_COMMAND),flags) +//lParam=(LPARAM)(HANDLE)hContact +//returns TRUE if it processed the command, FALSE otherwise +//hContact is the currently selected contact. It it not used if this is a main +//menu command. If this is NULL and the command is a contact menu one, the +//command is ignored + +#define CLISTMENUIDMIN 0x4000 // reserved range for clist menu ids +#define CLISTMENUIDMAX 0x7fff +////////////////////////////////////////////////////////////////////////// +// NOTE: v0.7.0.26+ +// Due to it is generic practice to handle menu command via WM_COMMAND +// window message handle and practice to process it via calling service +// in form: CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) hContact)) +// to ensure that WM_COMMAND was realy from clist menu not from other menu +// it is reserved range of menu ids from CLISTMENUIDMIN to CLISTMENUIDMAX +// the menu items with ids outside from such range will not be processed by service. +// Moreover if you process WM_COMMAND youself and your window contains self menu +// please be sure that you will not call service for non-clist menu items. +// The simplest way is to ensure that your menus are not use item ids from such range. +// Otherwise, you HAVE TO distinguish WM_COMMAND from clist menus and from youк internal menu and +// DO NOT call MS_CLIST_MENUPROCESSCOMMAND for non clist menus. + + +#define MPCF_CONTACTMENU 1 //test commands from a contact menu +#define MPCF_MAINMENU 2 //test commands from the main menu +#define MS_CLIST_MENUPROCESSCOMMAND "CList/MenuProcessCommand" + +//processes a menu hotkey v0.1.1.0+ +//wParam=virtual key code +//lParam=MPCF_ flags +//returns TRUE if it processed the command, FALSE otherwise +//this should be called in WM_KEYDOWN +#define MS_CLIST_MENUPROCESSHOTKEY "CList/MenuProcessHotkey" + +//process all the messages required for docking v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_DOCKINGPROCESSMESSAGE "CList/DockingProcessMessage" + +//determines whether the contact list is docked v0.1.1.0+ +//wParam=lParam=0 +//returns nonzero if the contact list is docked, of 0 if it is not +#define MS_CLIST_DOCKINGISDOCKED "CList/DockingIsDocked" + +//process all the messages required for the tray icon v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_TRAYICONPROCESSMESSAGE "CList/TrayIconProcessMessage" + +//process all the messages required for hotkeys v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_HOTKEYSPROCESSMESSAGE "CList/HotkeysProcessMessage" + +//toggles the show/hide status of the contact list v0.1.1.0+ +//wParam=lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_SHOWHIDE "CList/ShowHide" + +//temporarily disable the autohide feature v0.1.2.1+ +//wParam=lParam=0 +//returns 0 on success, nonzero on failure +//This service will restart the autohide timer, so if you need to keep the +//window visible you'll have to be getting user input regularly and calling +//this function each time +#define MS_CLIST_PAUSEAUTOHIDE "CList/PauseAutoHide" + +//sent when the group get modified (created, renamed or deleted) +//or contact is moving from group to group +//wParam=hContact - NULL if operation on group +//lParam=pointer to CLISTGROUPCHANGE +typedef struct { + int cbSize; //size in bytes of this structure + TCHAR* pszOldName; //old group name + TCHAR* pszNewName; //new group name +} CLISTGROUPCHANGE; + +#define ME_CLIST_GROUPCHANGE "CList/GroupChange" + +//creates a new group and calls CLUI to display it v0.1.1.0+ +//wParam=hParentGroup +//lParam=groupName +//returns a handle to the new group +//hParentGroup is NULL to create the new group at the root, or can be the +//handle of the group of which the new group should be a subgroup. +//groupName is a TCHAR* pointing to the group name to create or NULL for +//API to create unique name by itself +#define MS_CLIST_GROUPCREATE "CList/GroupCreate" + +//deletes a group and calls CLUI to display the change v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_GROUPDELETE "CList/GroupDelete" + +//change the expanded state flag for a group internally v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=newState +//returns 0 on success, nonzero on failure +//newState is nonzero if the group is expanded, 0 if it's collapsed +//CLUI is not called when this change is made +#define MS_CLIST_GROUPSETEXPANDED "CList/GroupSetExpanded" + +//changes the flags for a group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=MAKELPARAM(flags,flagsMask) +//returns 0 on success, nonzero on failure +//Only the flags given in flagsMask are altered. +//CLUI is called on changes to GROUPF_HIDEOFFLINE. +#define MS_CLIST_GROUPSETFLAGS "CList/GroupSetFlags" + +//get the name of a group v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(int*)&isExpanded +//returns a static buffer pointing to the name of the group +//returns NULL if hGroup is invalid. +//this buffer is only valid until the next call to this service +//&isExpanded can be NULL if you don't want to know if the group is expanded +//or not. +#define MS_CLIST_GROUPGETNAME "CList/GroupGetName" + +//get the name of a group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(DWORD*)&flags +//returns a static buffer pointing to the name of the group +//returns NULL if hGroup is invalid. +//this buffer is only valid until the next call to this service +//&flags can be NULL if you don't want any of that info. +#define GROUPF_EXPANDED 0x04 +#define GROUPF_HIDEOFFLINE 0x08 +#define MS_CLIST_GROUPGETNAME2 "CList/GroupGetName2" + +//move a group to directly before another group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(HANDLE)hBeforeGroup +//returns the new handle of the group on success, NULL on failure +//The order is represented by the order in which MS_CLUI_GROUPADDED is called, +//however UIs are free to ignore this order and sort alphabetically if they +//wish. +#define MS_CLIST_GROUPMOVEBEFORE "CList/GroupMoveBefore" + +//rename a group internally v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(char*)szNewName +//returns 0 on success, nonzero on failure +//this will fail if the group name is a duplicate of an existing name +//CLUI is not called when this change is made +#define MS_CLIST_GROUPRENAME "CList/GroupRename" + +//build a menu of the group tree v0.1.2.1+ +//wParam=0 +//lParam=0 +//returns a HMENU on success, or NULL on failure +//The return value must be DestroyMenu()ed when you're done with it. +//NULL will be returned if the user doesn't have any groups +//The dwItemData of every menu item is the handle to that group. +//Menu item IDs are assigned starting at 100, in no particular order. +#define MS_CLIST_GROUPBUILDMENU "CList/GroupBuildMenu" + +//changes the 'hide offline contacts' flag and call CLUI v0.1.1.0+ +//wParam=newValue +//lParam=0 +//returns 0 on success, nonzero on failure +//newValue is 0 to show all contacts, 1 to only show online contacts +//or -1 to toggle the value +#define MS_CLIST_SETHIDEOFFLINE "CList/SetHideOffline" + +//do the message processing associated with double clicking a contact v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_CONTACTDOUBLECLICKED "CList/ContactDoubleClicked" + +//do the processing for when some files are dropped on a contact v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(char**)ppFiles +//returns 0 on success, nonzero on failure +//ppFiles is an array of fully qualified filenames, ending with a NULL. +#define MS_CLIST_CONTACTFILESDROPPED "CList/ContactFilesDropped" + +//change the group a contact belongs to v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(HANDLE)hGroup +//returns 0 on success, nonzero on failure +//use hGroup=NULL to put the contact in no group +#define MS_CLIST_CONTACTCHANGEGROUP "CList/ContactChangeGroup" + +//determines the ordering of two contacts v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact1 +//lParam=(LPARAM)(HANDLE)hContact2 +//returns 0 if hContact1 is the same as hContact2 +//returns +1 if hContact2 should be displayed after hContact1 +//returns -1 if hContact1 should be displayed after hContact2 +#define MS_CLIST_CONTACTSCOMPARE "CList/ContactsCompare" + +/* + wParam=0 (not used) + lParam=(LPARAM) &MIRANDASYSTRAYNOTIFY + + Affects: Show a message in a ballon tip against a protocol icon (if installed) + Returns: 0 on success, non zero on failure + Notes : This service will not be created on systems that haven't got the Windows + support for ballontips, also note that it's upto Windows if it shows your + message and it keeps check of delays (don't be stupid about showing messages) + + Version: 0.3.1a +*/ +#define NIIF_INFO 0x00000001 +#define NIIF_WARNING 0x00000002 +#define NIIF_ERROR 0x00000003 +#define NIIF_ICON_MASK 0x0000000F +#define NIIF_NOSOUND 0x00000010 +#define NIIF_INTERN_UNICODE 0x00000100 + + +typedef struct { + int cbSize; // sizeof(MIRANDASYSTRAY) + char *szProto; // protocol to show under (may have no effect) + union { + char *szInfoTitle; // only 64chars of it will be used + TCHAR *tszInfoTitle; // used if NIIF_INTERN_UNICODE is specified + }; + union { + char *szInfo; // only 256chars of it will be used + TCHAR *tszInfo; // used if NIIF_INTERN_UNICODE is specified + }; + DWORD dwInfoFlags; // see NIIF_* stuff + UINT uTimeout; // how long to show the tip for +} MIRANDASYSTRAYNOTIFY; +#define MS_CLIST_SYSTRAY_NOTIFY "Miranda/Systray/Notify" + +#define SETTING_TOOLWINDOW_DEFAULT 1 +#define SETTING_SHOWMAINMENU_DEFAULT 1 +#define SETTING_SHOWCAPTION_DEFAULT 1 +#define SETTING_CLIENTDRAG_DEFAULT 1 +#define SETTING_ONTOP_DEFAULT 0 +#define SETTING_MIN2TRAY_DEFAULT 1 +#define SETTING_TRAY1CLICK_DEFAULT (IsWinVer7Plus()?1:0) +#define SETTING_HIDEOFFLINE_DEFAULT 0 +#define SETTING_HIDEEMPTYGROUPS_DEFAULT 0 +#define SETTING_USEGROUPS_DEFAULT 1 +#define SETTING_SORTBYSTATUS_DEFAULT 0 +#define SETTING_SORTBYPROTO_DEFAULT 0 +#define SETTING_TRANSPARENT_DEFAULT 0 +#define SETTING_ALPHA_DEFAULT 200 +#define SETTING_AUTOALPHA_DEFAULT 150 +#define SETTING_CONFIRMDELETE_DEFAULT 1 +#define SETTING_AUTOHIDE_DEFAULT 0 +#define SETTING_HIDETIME_DEFAULT 30 +#define SETTING_CYCLETIME_DEFAULT 4 +#define SETTING_TRAYICON_DEFAULT SETTING_TRAYICON_SINGLE +#define SETTING_ALWAYSSTATUS_DEFAULT 0 +#define SETTING_ALWAYSMULTI_DEFAULT 0 + +#define SETTING_TRAYICON_SINGLE 0 +#define SETTING_TRAYICON_CYCLE 1 +#define SETTING_TRAYICON_MULTI 2 + +#define SETTING_STATE_HIDDEN 0 +#define SETTING_STATE_MINIMIZED 1 +#define SETTING_STATE_NORMAL 2 + +#define SETTING_BRINGTOFRONT_DEFAULT 0 + +#endif // M_CLIST_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_database.h b/plugins/!NotAdopted/WinPopup/sdk/m_database.h new file mode 100644 index 0000000000..c1bf7dafd3 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_database.h @@ -0,0 +1,1199 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_DATABASE_H__ +#define M_DATABASE_H__ 1 + +/******************* DATABASE MODULE ***************************/ + +/* Notes (as I think of them): +- The module is 100% thread-safe +- The database is the main routing point for the vast majority of Miranda. + Events are sent from the protocol module to here, and the send/recv message + module (for example) hooks the db/event/added event. Events like 'contact + online status changed' do not come through here - icqlib will send that one. +- contacts work much the same. the find/add users module calls db/contact/add + and db/contact/writesetting and the contact list will get db/contact/added + and db/contact/settingchanged events +- The user is just a special contact. A hcontact of NULL in most functions + means the user. Functions in which it cannot be used will be stated +- events attached to the user are things like system messages +- also in this module are crypt/decrypt functions for stuff that should be + obfuscated on the disk, and some time functions for dealing with timestamps + in events. +- the contactsettings system is designed for being read by many different + modules. eg lots of people will be interested in "ICQ"/"UIN", but the module + name passed to contact/writesetting should always be your own. The Mirabilis + ICQ database importer clearly has to be an exception to this rule, along with + a few other bits. +- the current database format means that geteventcontact is exceptionally slow. + It should be avoidable in most cases so I'm not too concerned, but if people + really need to use it a lot, I'll sort it out. +- handles do not need to be closed unless stated +- the database is loaded as a memory mapped file. This has various + disadvantages but a massive advantage in speed for random access. +- The database is optimised for reading. Write performance is fairly bad, + except for adding events which is the most common activity and pretty good. +- I'll work on caching to improve this later +- Deleted items are left as empty space and never reused. All new items are + put at the end. A count is kept of this slack space and at some point a + separate programme will need to be written to repack the database when the + slack gets too high. It's going to be a good few months of usage before this + can happen to anyone though, so no rush. +*/ + +/******************** GENERALLY USEFUL STUFF***********************/ + +#include + +#if !defined(M_SYSTEM_H__) + #include "m_system.h" +#endif + +#if !defined(M_UTILS_H__) + #include "m_utils.h" +#endif + +#ifdef _MSC_VER + #pragma warning(disable:4201 4204) +#endif + +//DBVARIANT: used by db/contact/getsetting and db/contact/writesetting +#define DBVT_DELETED 0 //this setting just got deleted, no other values are valid +#define DBVT_BYTE 1 //bVal and cVal are valid +#define DBVT_WORD 2 //wVal and sVal are valid +#define DBVT_DWORD 4 //dVal and lVal are valid +#define DBVT_ASCIIZ 255 //pszVal is valid +#define DBVT_BLOB 254 //cpbVal and pbVal are valid +#define DBVT_UTF8 253 //pszVal is valid +#define DBVT_WCHAR 252 //pszVal is valid +#if defined( _UNICODE ) + #define DBVT_TCHAR DBVT_WCHAR +#else + #define DBVT_TCHAR DBVT_ASCIIZ +#endif +#define DBVTF_VARIABLELENGTH 0x80 +#define DBVTF_DENYUNICODE 0x10000 +typedef struct { + BYTE type; + union { + BYTE bVal; char cVal; + WORD wVal; short sVal; + DWORD dVal; long lVal; + struct { + union { + char *pszVal; + TCHAR *ptszVal; + WCHAR *pwszVal; + }; + WORD cchVal; //only used for db/contact/getsettingstatic + }; + struct { + WORD cpbVal; + BYTE *pbVal; + }; + }; +} DBVARIANT; + +/******************************************************************/ +/************************* SERVICES *******************************/ +/******************************************************************/ + +/* DB/Contact/GetProfileName service +Gets the name of the profile currently being used by the database module. This +is the same as the filename of the database + wParam=(WPARAM)(UINT)cbName + lParam=(LPARAM)(char*)pszName +pszName is a pointer to the buffer that receives the name of the profile +cbName is the size in bytes of the pszName buffer +Returns 0 on success or nonzero otherwise +*/ +#define MS_DB_GETPROFILENAME "DB/GetProfileName" + +/* DB/Contact/GetProfilePath service +Gets the path of the profile currently being used by the database module. This +path does not include the last '\'. + wParam=(WPARAM)(UINT)cbName + lParam=(LPARAM)(char*)pszName +pszName is a pointer to the buffer that receives the path of the profile +cbName is the size in bytes of the pszName buffer +Returns 0 on success or nonzero otherwise +*/ +#define MS_DB_GETPROFILEPATH "DB/GetProfilePath" + +/************************* Contact ********************************/ + +/* DB/Contact/GetSetting service +Look up the value of a named setting for a specific contact in the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +Caller is responsible for free()ing dbcgs.pValue->pszVal and pbVal if they are +returned. This should be done with db/contact/freevariant if you have your own +heap (like DLLs do). +Note that DBCONTACTGETSETTING takes a pointer to a DBVARIANT, whereas +DBCONTACTWRITESETTING contains a DBVARIANT. +Returns 0 on success or nonzero if the setting name was not found or hContact +was invalid +Because this is such a common function there are some short helper function at +the bottom of this header that use it. + +(Added during 0.3.3+ development!!) + +If a setting is queried under for contact and it is deleted it will +not be returned as a successful attempt, prior to 0.3.3 a *deleted* +setting would be successfully read (which was a bug because the pValue +was often garbage and maybe not even NULL terminated) + +To test for existing but 'deleted' settings, the return value will +be 2, and pValue->type==DBVT_DELETED, at this point pValue is undefined. +*/ +typedef struct { + const char *szModule; // pointer to name of the module that wrote the + // setting to get + const char *szSetting; // pointer to name of the setting to get + DBVARIANT *pValue; // pointer to variant to receive the value +} DBCONTACTGETSETTING; +#define MS_DB_CONTACT_GETSETTING "DB/Contact/GetSetting" + +/* DB/Contact/GetSettingString service 0.4.3+ +Same as DB/Contact/GetSetting, but also gets the required string type inside +the dbcgs->type parameter +*/ +#define MS_DB_CONTACT_GETSETTING_STR "DB/Contact/GetSettingStr" + +/* DB/Contact/GetSettingStatic service +Look up the value of a named setting for a specific contact in the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +This service differs from db/contact/getsetting in that it won't malloc() +memory for the return value if it needs to do so. This introduces some extra +constraints: +Upon calling dbcgs.pValue->type should be initialised to the expected type of +the setting. If the setting is of an integral type it won't matter if it's +wrong and the service will correct it before returning, however if the setting +is a string or a blob the service needs to know where to put the data and will +fail if type is set wrongly. +If dbcgs.pValue->type is DBVT_ASCIIZ or DBVT_BLOB upon calling, the +corresponding data field (pszVal or pbVal) must point to a buffer allocated by +the caller and the length field (cchVal or cpbVal) must contain the size of +that buffer in bytes. +If the setting type is variable length (DBVT_ASCIIZ or DBVT_BLOB), on exit the +length field (cchVal or cpbVal) will be filled with the full length of the +setting's value (excluding the terminating nul if it's DBVT_ASCIIZ). +This service exists as well as db/contact/getsetting because malloc()/free() +can be too slow for frequently queried settings. +Returns 0 on success or nonzero if the setting name was not found or hContact +was invalid. +*/ +#define MS_DB_CONTACT_GETSETTINGSTATIC "DB/Contact/GetSettingStatic" + +/* DB/Contact/FreeVariant service +Free the memory in a DBVARIANT that is allocated by a call to +db/contact/getsetting + wParam=0 + lParam=(LPARAM)(DBVARIANT*)&dbv +Returns 0 on success, nonzero otherwise +This service is actually just a wrapper around a call to free() and a test to +check that it is a string or a blob in the variant. It exists because DLLs have +their own heap and cannot free the memory allocated in db/contact/getsetting. +Thus it need not be called if you know the variant contains some form of int, +and you will often see free() used instead in code written before I noticed +this problem. +Good style, of course, dictates that it should be present to match all calls to +db/contact/getsetting, but that's not going to happen of course. +There's a helper function for this at the bottom of this header too. +*/ +#define MS_DB_CONTACT_FREEVARIANT "DB/Contact/FreeVariant" + +/* DB/Contact/WriteSetting service +Change the value of, or create a new value with, a named setting for a specific +contact in the database to the given value + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws +hContact should have been returned by find*contact or addcontact +Returns 0 on success or nonzero if hContact was invalid +Note that DBCONTACTGETSETTING takes a pointer to a DBVARIANT, whereas +DBCONTACTWRITESETTING contains a DBVARIANT. +Because this is such a common function there are some short helper function at +the bottom of this header that use it. +Triggers a db/contact/settingchanged event just before it returns. +*/ +typedef struct { + const char *szModule; // pointer to name of the module that wrote the + // setting to get + const char *szSetting; // pointer to name of the setting to get + DBVARIANT value; // variant containing the value to set +} DBCONTACTWRITESETTING; +#define MS_DB_CONTACT_WRITESETTING "DB/Contact/WriteSetting" + +/* DB/Contact/DeleteSetting service +Removes a named setting for a specific contact from the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +pValue from dbcgs is not used. +Returns 0 on success or nonzero if the setting was not present or hContact was +invalid +Triggers a db/contact/settingchanged event before it deletes the setting. The +'new value' of the setting is set to type=0 and all the other fields are +undefined. +*/ +#define MS_DB_CONTACT_DELETESETTING "DB/Contact/DeleteSetting" + +/* db/contact/enumsettings v0.1.0.1+ +Lists all the settings a specific modules has stored in the database for a +specific contact. +wParam=(WPARAM)(HANDLE)hContact +lParam=(LPARAM)(DBCONTACTENUMSETTINGS*)&dbces +Returns the return value of the last call to pfnEnumProc, or -1 if there are +no settings for that module/contact pair +Writing to or deleting from the database while enumerating will have +unpredictable results for the enumeration, but the write will succeed. +Use db/modules/enum to get a complete list of module names +szSetting is only guaranteed to be valid for the duration of the callback. If +you want to keep it for longer you must allocation your own storage. +*/ +typedef int (*DBSETTINGENUMPROC)(const char *szSetting,LPARAM lParam); +typedef struct { + DBSETTINGENUMPROC pfnEnumProc; + LPARAM lParam; //passed direct to pfnEnumProc + const char *szModule; //name of the module to get settings for + DWORD ofsSettings; //filled by the function to contain the offset from + //the start of the database of the requested settings group. +} DBCONTACTENUMSETTINGS; +#define MS_DB_CONTACT_ENUMSETTINGS "DB/Contact/EnumSettings" + +/* DB/Contact/GetCount service +Gets the number of contacts in the database, which does not count the user + wParam=lParam=0 +Returns the number of contacts. They can be retrieved using contact/findfirst +and contact/findnext +*/ +#define MS_DB_CONTACT_GETCOUNT "DB/Contact/GetCount" + +/* DB/Contact/FindFirst service +Gets the handle of the first contact in the database. This handle can be used +with loads of functions. It does not need to be closed. + wParam=lParam=0 +Returns a handle to the first contact in the db on success, or NULL if there +are no contacts in the db. +*/ +#define MS_DB_CONTACT_FINDFIRST "DB/Contact/FindFirst" + +/* DB/Contact/FindNext service +Gets the handle of the next contact after hContact in the database. This handle +can be used with loads of functions. It does not need to be closed. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns a handle to the contact after hContact in the db on success or NULL if +hContact was the last contact in the db or hContact was invalid. +*/ +#define MS_DB_CONTACT_FINDNEXT "DB/Contact/FindNext" + +/* DB/Contact/Delete +Deletes the contact hContact from the database and all events and settings +associated with it. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns 0 on success or nonzero if hContact was invalid +Please don't try to delete the user contact (hContact=NULL) +Triggers a db/contact/deleted event just *before* it removes anything +Because all events are deleted, lots of people may end up with invalid event +handles from this operation, which they should be prepared for. +*/ +#define MS_DB_CONTACT_DELETE "DB/Contact/Delete" + +/* DB/Contact/Add +Adds a new contact to the database. New contacts initially have no settings +whatsoever, they must all be added with db/contacts/writesetting. + wParam=lParam=0 +Returns a handle to the newly created contact on success, or NULL otherwise. +Triggers a db/contact/added event just before it returns. +*/ +#define MS_DB_CONTACT_ADD "DB/Contact/Add" + +/* DB/Contact/Is +Checks if a given value is a valid contact handle, note that due +to the nature of multiple threading, a valid contact can still become +invalid after a call to this service. + wParam=(WPARAM)hContact + lParam=0 +Returns 1 if the contact is a contact, or 0 if the contact is not valid. +*/ +#define MS_DB_CONTACT_IS "DB/Contact/Is" + +/************************** Event *********************************/ + +/* DB/EventType/Register service (0.7+) +Registers the specified database event type, with module, id & description. +When someone needs to retrieve an event's text, a service named Module/GetEventText +will be called. For example, for module named 'foo' and event id 2000 a service +foo/GetEventText2000 should be defined to process this request. That handler should +decode a blob and return the event text in the required format, its prototype is identical +to a call of MS_DB_EVENT_GETTEXT (see below) + wParam=0 + lParam=(LPARAM)(DBEVENTTYPEDESCR*) +Always returns 0. +*/ + +#define DBEVENTTYPEDESCR_SIZE sizeof(DBEVENTTYPEDESCR) +#define DBEVENTTYPEDESCR_SIZE_V1 0x10 + +typedef struct +{ + int cbSize; // structure size in bytes + char* module; // event module name + int eventType; // event id, unique for this module + char* descr; // event type description (i.e. "File Transfer") + char* textService; // service name for MS_DB_EVENT_GETTEXT (0.8+, default Module+'/GetEventText'+EvtID) + char* iconService; // service name for MS_DB_EVENT_GETICON (0.8+, default Module+'/GetEventIcon'+EvtID) + HANDLE eventIcon; // icolib handle to eventicon (0.8+, default 'eventicon_'+Module+EvtID) + DWORD flags; // flags, combination of the DETF_* +} + DBEVENTTYPEDESCR; + +// constants for default event behaviour +#define DETF_HISTORY 1 // show event in history +#define DETF_MSGWINDOW 2 // show event in message window +#define DETF_NONOTIFY 4 // block event notify (e.g. Popups) + + +#define MS_DB_EVENT_REGISTERTYPE "DB/EventType/Register" + +/* DB/EventType/Get service (0.7+) +Retrieves the previously registered database event type, by module & id. + wParam=(WPARAM)(char*)szModule + lParam=(LPARAM)(int)eventType +Returns DBEVENTTYPEDESCR* or NULL, if an event isn't found. +*/ + +#define MS_DB_EVENT_GETTYPE "DB/EventType/Get" + +/* DB/Event/GetCount service +Gets the number of events in the chain belonging to a contact in the database. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the number of events in the chain owned by hContact or -1 if hContact +is invalid. They can be retrieved using the event/find* services. +*/ +#define MS_DB_EVENT_GETCOUNT "DB/Event/GetCount" + +/* DB/Event/Add +Adds a new event to a contact's event list + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBEVENTINFO*)&dbe +Returns a handle to the newly added event, or NULL on failure +Triggers a db/event/added event just before it returns. +Events are sorted chronologically as they are entered, so you cannot guarantee +that the new hEvent is the last event in the chain, however if a new event is +added that has a timestamp less than 90 seconds *before* the event that should +be after it, it will be added afterwards, to allow for protocols that only +store times to the nearest minute, and slight delays in transports. +There are a few predefined eventTypes below for easier compatibility, but +modules are free to define their own, beginning at 2000 +DBEVENTINFO.timestamp is in GMT, as returned by time(). There are services +db/time/x below with useful stuff for dealing with it. +*/ +#define DBEF_FIRST 1 //this is the first event in the chain; + //internal only: *do not* use this flag +#define DBEF_SENT 2 //this event was sent by the user. If not set this + //event was received. +#define DBEF_READ 4 //event has been read by the user. It does not need + //to be processed any more except for history. +#define DBEF_RTL 8 //event contains the right-to-left aligned text +#define DBEF_UTF 16 //event contains a text in utf-8 + +typedef struct { + int cbSize; //size of the structure in bytes + char *szModule; //pointer to name of the module that 'owns' this + //event, ie the one that is in control of the data format + DWORD timestamp; //seconds since 00:00, 01/01/1970. Gives us times until + //2106 unless you use the standard C library which is + //signed and can only do until 2038. In GMT. + DWORD flags; //the omnipresent flags + WORD eventType; //module-defined event type field + DWORD cbBlob; //size of pBlob in bytes + PBYTE pBlob; //pointer to buffer containing module-defined event data +} DBEVENTINFO; +#define EVENTTYPE_MESSAGE 0 +#define EVENTTYPE_URL 1 +#define EVENTTYPE_CONTACTS 2 //v0.1.2.2+ +#define EVENTTYPE_ADDED 1000 //v0.1.1.0+: these used to be module- +#define EVENTTYPE_AUTHREQUEST 1001 //specific codes, hence the module- +#define EVENTTYPE_FILE 1002 //specific limit has been raised to 2000 +#define MS_DB_EVENT_ADD "DB/Event/Add" + +/* DB/Event/Delete +Removes a single event from the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns 0 on success, or nonzero if hDbEvent was invalid +Triggers a db/event/deleted event just *before* the event is deleted +*/ +#define MS_DB_EVENT_DELETE "DB/Event/Delete" + +/* DB/Event/GetBlobSize +Retrieves the space in bytes required to store the blob in hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns the space required in bytes, or -1 if hDbEvent is invalid +*/ +#define MS_DB_EVENT_GETBLOBSIZE "DB/Event/GetBlobSize" + +/* DB/Event/Get +Retrieves all the information stored in hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=(LPARAM)(DBEVENTINFO*)&dbe +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns 0 on success or nonzero if hDbEvent is invalid +Don't forget to set dbe.cbSize, dbe.pBlob and dbe.cbBlob before calling this +service +The correct value dbe.cbBlob can be got using db/event/getblobsize +If successful, all the fields of dbe are filled. dbe.cbBlob is set to the +actual number of bytes retrieved and put in dbe.pBlob +If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob +and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob +On return, dbe.szModule is a pointer to the database module's own internal list +of modules. Look but don't touch. +*/ +#define MS_DB_EVENT_GET "DB/Event/Get" + +/* DB/Event/GetText (0.7.0+) +Retrieves the event's text + wParam=(WPARAM)0 (unused) + lParam=(LPARAM)(DBEVENTGETTEXT*)egt - pointer to structure with parameters + egt->dbei should be the valid database event read via MS_DB_EVENT_GET + egt->datatype = DBVT_WCHAR or DBVT_ASCIIZ or DBVT_TCHAR. If a caller wants to +suppress Unicode part of event in answer, add DBVTF_DENYUNICODE to this field. + egt->codepage is any valid codepage, CP_ACP by default. + +Function returns a pointer to a string in the required format. +This string should be freed by a call of mir_free +*/ +typedef struct { + DBEVENTINFO* dbei; + int datatype; + int codepage; +} DBEVENTGETTEXT; + +#define MS_DB_EVENT_GETTEXT "DB/Event/GetText" + +__inline static char* DbGetEventTextA( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_ASCIIZ, codepage }; + return (char*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +__inline static WCHAR* DbGetEventTextW( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_WCHAR, codepage }; + return (WCHAR*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +__inline static TCHAR* DbGetEventTextT( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_TCHAR, codepage }; + return (TCHAR*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +/* DB/Event/GetIcon (0.7.0.1+) +Retrieves the event's icon + wParam=(WPARAM)(int)flags - use LR_SHARED for shared HICON + lParam=(LPARAM)(DBEVENTINFO*)dbei +dbei should be a valid database event read via MS_DB_EVENT_GET + +Function returns HICON (use DestroyIcon to release resources if not LR_SHARED) + +A plugin can register the standard event icon in IcoLib named +'eventicon_'+Module+EvtID, like eventicon_ICQ2001. Otherwise, to declare an icon +with the non-standard name, you can declare the special service, Module/GetEventIcon, +which will retrieve the custom icon handle (HICON). This service function has the +same parameters MS_DB_EVENT_GETICON does. +*/ +#define MS_DB_EVENT_GETICON "DB/Event/GetIcon" + +/* DB/Event/GetString (0.9.0+) +Converts the event's string to TCHAR* depending on the event's format + wParam=(LPARAM)(DBEVENTINFO*)dbei + lParam=(WPARAM)(char*)str - string to be converted + returns TCHAR* - the converted string +Caller must free the result using mir_free +*/ + +#define MS_DB_EVENT_GETSTRINGT "DB/Event/GetStringT" + +__inline static TCHAR* DbGetEventStringT( DBEVENTINFO* dbei, const char* str ) +{ + return (TCHAR*)CallService( MS_DB_EVENT_GETSTRINGT, (WPARAM)dbei, (LPARAM)str ); +} + +/* DB/Event/MarkRead +Changes the flags for an event to mark it as read. + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns the entire flag DWORD for the event after the change, or -1 if hDbEvent +is invalid. +This is the one database write operation that does not trigger an event. +Modules should not save flags states for any length of time. +*/ +#define MS_DB_EVENT_MARKREAD "DB/Event/MarkRead" + +/* DB/Event/GetContact +Retrieves a handle to the contact that owns hDbEvent. + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +hDbEvent should have been returned by db/event/add or db/event/find*event +NULL is a valid return value, meaning, as usual, the user. +Returns (HANDLE)(-1) if hDbEvent is invalid, or the handle to the contact on +success +This service is exceptionally slow. Use only when you have no other choice at +all. +*/ +#define MS_DB_EVENT_GETCONTACT "DB/Event/GetContact" + +/* DB/Event/FindFirst +Retrieves a handle to the first event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or has no events +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDFIRST "DB/Event/FindFirst" + +/* DB/Event/FindFirstUnread +Retrieves a handle to the first unread event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or all its events have been +read +Events in a chain are sorted chronologically automatically, but this does not +necessarily mean that all events after the first unread are unread too. They +should be checked individually with event/findnext and event/get +This service is designed for startup, reloading all the events that remained +unread from last time +*/ +#define MS_DB_EVENT_FINDFIRSTUNREAD "DB/Event/FindFirstUnread" + +/* DB/Event/FindLast +Retrieves a handle to the last event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or has no events +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDLAST "DB/Event/FindLast" + +/* DB/Event/FindNext +Retrieves a handle to the next event in a chain after hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +Returns the handle, or NULL if hDbEvent is invalid or is the last event +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDNEXT "DB/Event/FindNext" + +/* DB/Event/FindPrev +Retrieves a handle to the previous event in a chain before hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +Returns the handle, or NULL if hDbEvent is invalid or is the first event +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDPREV "DB/Event/FindPrev" + +/************************** Encryption ****************************/ + +/* DB/Crypt/EncodeString +Scrambles pszString in-place using a strange encryption algorithm + wParam=(WPARAM)(int)cbString + lParam=(LPARAM)(char*)pszString +cbString is the size of the buffer pointed to by pszString, *not* the length +of pszString. This service may be changed at a later date such that it +increases the length of pszString +Returns 0 always +*/ +#define MS_DB_CRYPT_ENCODESTRING "DB/Crypt/EncodeString" + +/* DB/Crypt/DecodeString +Descrambles pszString in-place using the strange encryption algorithm + wParam=(WPARAM)(int)cbString + lParam=(LPARAM)(char*)pszString +Reverses the operation done by crypt/encodestring +cbString is the size of the buffer pointed to by pszString, *not* the length +of pszString. +Returns 0 always +*/ +#define MS_DB_CRYPT_DECODESTRING "DB/Crypt/DecodeString" + +/**************************** Time ********************************/ + +/* DB/Time/TimestampToLocal +Converts a GMT timestamp into local time + wParam=(WPARAM)(DWORD)timestamp + lParam=0 +Returns the converted value +Timestamps have zero at midnight 1/1/1970 GMT, this service converts such a +value to be based at midnight 1/1/1970 local time. +This service does not use a simple conversion based on the current offset +between GMT and local. Rather, it figures out whether daylight savings time +would have been in place at the time of the stamp and gives the local time as +it would have been at the time and date the stamp contains. +This service isn't nearly as useful as db/time/TimestampToString below and I +recommend avoiding its use when possible so that you don't get your timezones +mixed up (like I did. Living at GMT makes things easier for me, but has certain +disadvantages :-) ). +*/ +#define MS_DB_TIME_TIMESTAMPTOLOCAL "DB/Time/TimestampToLocal" + +/* DB/Time/TimestampToString +Converts a GMT timestamp into a customisable local time string + wParam=(WPARAM)(DWORD)timestamp + lParam=(LPARAM)(DBTIMETOSTRING*)&tts +Returns 0 always +Uses db/time/timestamptolocal for the conversion so read that description to +see what's going on. +The string is formatted according to the current user's locale, language and +preferences. +szFormat can have the following special characters: + t Time without seconds, eg hh:mm + s Time with seconds, eg hh:mm:ss + m Time without minutes, eg hh + d Short date, eg dd/mm/yyyy + D Long date, eg d mmmm yyyy +All other characters are copied across to szDest as-is +*/ +typedef struct { + char *szFormat; // format string, as above + char *szDest; // place to put the output string + int cbDest; // maximum number of bytes to put in szDest +} DBTIMETOSTRING; +#define MS_DB_TIME_TIMESTAMPTOSTRING "DB/Time/TimestampToString" + +typedef struct { + TCHAR *szFormat; // format string, as above + TCHAR *szDest; // place to put the output string + int cbDest; // maximum number of bytes to put in szDest +} DBTIMETOSTRINGT; +#define MS_DB_TIME_TIMESTAMPTOSTRINGT "DB/Time/TimestampToStringT" + +/*************************** Random *******************************/ + +/* +Switches safety settings on or off +wParam=(WPARAM)(BOOL)newSetting +lParam=0 +returns 0 always +newSetting is TRUE initially. +Miranda's database is normally protected against corruption by agressively +flushing data to the disk on writes. If you're doing a lot of writes (eg in +an import plugin) it can sometimes be desirable to switch this feature off to +speed up the process. If you do switch it off, you must remember that crashes +are far more likely to be catastrophic, so switch it back on at the earliest +possible opportunity. +Note that if you're doing a lot of setting writes, the flush is already delayed +so you need not use this service for that purpose. +*/ +#define MS_DB_SETSAFETYMODE "DB/SetSafetyMode" + +/*************************** Modules ******************************/ + +/* db/modules/enum v0.1.0.1+ +Enumerates the names of all modules that have stored or requested information +from the database. +wParam=lParam +lParam=(WPARAM)(DBMODULEENUMPROC)dbmep +Returns the value returned by the last call to dbmep +This service is only really useful for debugging, in conjunction with +db/contact/enumsettings +lParam is passed directly to dbmep +dbmep should return 0 to continue enumeration, or nonzero to stop. +ofsModuleName is the offset of the module name from the start of the profile +database, and is only useful for really heavyweight debugging +Modules names will be enumerated in no particular order +Writing to the database while module names are being enumerated will cause +unpredictable results in the enumeration, but the write will work. +szModuleName is only guaranteed to be valid for the duration of the callback. +If you want to keep it for longer you must allocation your own storage. +**BUG**: Prior to 0.1.2.0 dbmep was called as (lParam)(szMod,ofsMod,lParam). + This means that the lParam parameter to dbmep was useless, and explains the + slightly odd 'wParam=lParam' in the definition. +*/ +typedef int (*DBMODULEENUMPROC)(const char *szModuleName,DWORD ofsModuleName,LPARAM lParam); +#define MS_DB_MODULES_ENUM "DB/Modules/Enum" + +/* DB/Module/Delete 0.8.0+ + +Removes all settings for the specified module. +wParam=0 (unused) +lParam=(LPARAM)(char*)szModuleName - the module name to be deleted +*/ + +#define MS_DB_MODULE_DELETE "DB/Module/Delete" + +/******************************************************************/ +/************************** EVENTS ********************************/ +/******************************************************************/ + +/* DB/Event/Added event +Called when a new event has been added to the event chain for a contact + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent is a valid handle to the event. hContact is a valid handle to the +contact to which hDbEvent refers. +Since events are sorted chronologically, you cannot guarantee that hDbEvent is +at any particular position in the chain. +*/ +#define ME_DB_EVENT_ADDED "DB/Event/Added" + +/* DB/Event/FilterAdd (NOTE: Added during 0.3.3+ development!) +Called **before** a new event is made of a DBEVENTINFO structure, this +hook is not SAFE unless you know what you're doing with it, the arguments +are passed as-is (with errors, pointer problems, if any) from any arguments +passed to MS_DB_EVENT_ADD. + +The point of this hook is to stop any unwanted database events, to stop +an event being added, return 1, to allow the event to pass through return +0. + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)&DBEVENTINFO + +Any changed made to the said DBEVENTINFO are also passed along to the database, +therefore it is possible to shape the data, however DO NOT DO THIS. +*/ +#define ME_DB_EVENT_FILTER_ADD "DB/Event/FilterAdd" + +/* DB/Event/Deleted event +Called when an event is about to be deleted from the event chain for a contact + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent is a valid handle to the event which is about to be deleted, but it +won't be once your hook has returned. +hContact is a valid handle to the contact to which hDbEvent refers, and will +remain valid. +Returning nonzero from your hook will not stop the deletion, but it will, as +usual, stop other hooks from being called. +*/ +#define ME_DB_EVENT_DELETED "DB/Event/Deleted" + +/* DB/Contact/Added event +Called when a new contact has been added to the database + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +hContact is a valid handle to the new contact. +Contacts are initially created without any settings, so if you hook this event +you will almost certainly also want to hook db/contact/settingchanged as well. +*/ +#define ME_DB_CONTACT_ADDED "DB/Contact/Added" + +/* DB/Contact/Deleted event +Called when an contact is about to be deleted + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +hContact is a valid handle to the contact which is about to be deleted, but it +won't be once your hook has returned. +Returning nonzero from your hook will not stop the deletion, but it will, as +usual, stop other hooks from being called. +Deleting a contact invalidates all events in its chain. +*/ +#define ME_DB_CONTACT_DELETED "DB/Contact/Deleted" + +/* DB/Contact/SettingChanged event +Called when a contact has had one of its settings changed + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws +hContact is a valid handle to the contact that has changed. +This event will be triggered many times rapidly when a whole bunch of values +are set. +Modules which hook this should be aware of this fact and quickly return if they +are not interested in the value that has been changed. +Careful not to get into infinite loops with this event. +The structure dbcws is the same one as is passed to the original service, so +don't change any of the members. +*/ +#define ME_DB_CONTACT_SETTINGCHANGED "DB/Contact/SettingChanged" + +/* DB/Contact/SetSettingResident service (0.6+) +Disables a setting saving to the database. + wParam=(WPARAM)(BOOL)bIsResident + lParam=(LPARAM)(char*)pszSettingName +*/ +#define MS_DB_SETSETTINGRESIDENT "DB/SetSettingResident" + +/******************************************************************/ +/********************* SETTINGS HELPER FUNCTIONS ******************/ +/******************************************************************/ + +#ifndef DB_NOHELPERFUNCTIONS + +#define db_byte_get(a,b,c,d) DBGetContactSettingByte(a,b,c,d) +#define db_word_get(a,b,c,d) DBGetContactSettingWord(a,b,c,d) +#define db_dword_get(a,b,c,d) DBGetContactSettingDword(a,b,c,d) +#define db_get(a,b,c,d) DBGetContactSetting(a,b,c,d) + +#define db_byte_set(a,b,c,d) DBWriteContactSettingByte(a,b,c,d) +#define db_word_set(a,b,c,d) DBWriteContactSettingWord(a,b,c,d) +#define db_dword_set(a,b,c,d) DBWriteContactSettingDword(a,b,c,d) +#define db_string_set(a,b,c,d) DBWriteContactSettingString(a,b,c,d) + +#define db_unset(a,b,c) DBDeleteContactSetting(a,b,c); + +#ifdef _DEBUG + #define DBGetContactSettingByte(a,b,c,d) DBGetContactSettingByte_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingWord(a,b,c,d) DBGetContactSettingWord_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingDword(a,b,c,d) DBGetContactSettingDword_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSetting(a,b,c,d) DBGetContactSetting_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_ASCIIZ) + #define DBGetContactSettingWString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_WCHAR) + #define DBGetContactSettingUTF8String(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_UTF8) +#else + #define DBGetContactSettingByte(a,b,c,d) DBGetContactSettingByte_Helper(a,b,c,d) + #define DBGetContactSettingWord(a,b,c,d) DBGetContactSettingWord_Helper(a,b,c,d) + #define DBGetContactSettingDword(a,b,c,d) DBGetContactSettingDword_Helper(a,b,c,d) + #define DBGetContactSetting(a,b,c,d) DBGetContactSetting_Helper(a,b,c,d) + #define DBGetContactSettingString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_ASCIIZ) + #define DBGetContactSettingWString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_WCHAR) + #define DBGetContactSettingUTF8String(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_UTF8) +#endif + +#ifdef _UNICODE +#define DBGetContactSettingTString DBGetContactSettingWString +#else +#define DBGetContactSettingTString DBGetContactSettingString +#endif + +#define db_msg_dbg(s) MessageBoxA(0,(s),"",0); + +/* Deprecated & bizarre aliases */ +#define DBGetContactSettingStringUtf DBGetContactSettingUTF8String +#define DBWriteContactSettingStringUtf DBWriteContactSettingUTF8String +#ifdef _DEBUG + #define DBGetContactSettingW(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,0) +#else + #define DBGetContactSettingW(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,0) +#endif + +#ifdef _DEBUG +#include +#endif + +__inline static int DBGetContactSettingByte_Helper(HANDLE hContact, const char *szModule, const char *szSetting, int errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_BYTE) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a byte, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.bVal; +} + +__inline static int DBGetContactSettingWord_Helper(HANDLE hContact,const char *szModule,const char *szSetting,int errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_WORD) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a word, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.wVal; +} + +__inline static DWORD DBGetContactSettingDword_Helper(HANDLE hContact,const char *szModule, const char *szSetting, DWORD errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_DWORD) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a dword, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.dVal; +} + +__inline static INT_PTR DBGetContactSetting_Helper(HANDLE hContact,const char *szModule,const char *szSetting,DBVARIANT *dbv +#if defined(_DEBUG) + ,const char *szFile, const int nLine +#endif +) +{ + INT_PTR rc; + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=dbv; + + rc=CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs); +#if defined(_DEBUG) && defined(DBCHECKSETTINGS) + if (rc != 0) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d failed to fetch %s/%s",szFile,nLine,szModule,szSetting); + db_msg_dbg(buf); + } +#endif + return rc; +} + +__inline static INT_PTR DBGetContactSettingString_Helper(HANDLE hContact,const char *szModule,const char *szSetting,DBVARIANT *dbv, +#if defined(_DEBUG) + const char *szFile, const int nLine, +#endif + const int nType) +{ + INT_PTR rc; + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=dbv; + dbv->type=(BYTE)nType; + + rc=CallService(MS_DB_CONTACT_GETSETTING_STR,(WPARAM)hContact,(LPARAM)&cgs); +#if defined(_DEBUG) && defined(DBCHECKSETTINGS) + if (rc != 0) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d failed to fetch %s/%s",szFile,nLine,szModule,szSetting); + db_msg_dbg(buf); + } +#endif + return rc; +} + +__inline static INT_PTR DBFreeVariant(DBVARIANT *dbv) +{ + return CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)dbv); +} + +__inline static char *DBGetString(HANDLE hContact,const char *szModule,const char *szSetting) +{ + char *str=NULL; + DBVARIANT dbv={0}; + DBGetContactSettingString(hContact,szModule,szSetting,&dbv); + if(dbv.type==DBVT_ASCIIZ) + str=mir_strdup(dbv.pszVal); + DBFreeVariant(&dbv); + return str; +} + +#define DBGetStringA DBGetString + +__inline static wchar_t *DBGetStringW(HANDLE hContact,const char *szModule,const char *szSetting) +{ + wchar_t *str=NULL; + DBVARIANT dbv={0}; + DBGetContactSettingWString(hContact,szModule,szSetting,&dbv); + if(dbv.type==DBVT_WCHAR) + str=mir_wstrdup(dbv.pwszVal); + DBFreeVariant(&dbv); + return str; +} + +#ifdef _UNICODE +#define DBGetStringT DBGetStringW +#else +#define DBGetStringT DBGetString +#endif + +__inline static INT_PTR DBDeleteContactSetting(HANDLE hContact,const char *szModule,const char *szSetting) +{ + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + return CallService(MS_DB_CONTACT_DELETESETTING,(WPARAM)hContact,(LPARAM)&cgs); +} + +__inline static INT_PTR DBWriteContactSettingByte(HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_BYTE; + cws.value.bVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingWord(HANDLE hContact,const char *szModule,const char *szSetting,WORD val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_WORD; + cws.value.wVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingDword(HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_DWORD; + cws.value.dVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingString(HANDLE hContact,const char *szModule,const char *szSetting,const char *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_ASCIIZ; + cws.value.pszVal=(char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingWString(HANDLE hContact,const char *szModule,const char *szSetting,const WCHAR *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_WCHAR; + cws.value.pwszVal=(WCHAR*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +#ifdef _UNICODE +#define DBWriteContactSettingTString DBWriteContactSettingWString +#else +#define DBWriteContactSettingTString DBWriteContactSettingString +#endif + +__inline static INT_PTR DBWriteContactSettingUTF8String(HANDLE hContact,const char *szModule,const char *szSetting,const char *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_UTF8; + cws.value.pszVal=(char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingBlob(HANDLE hContact,const char *szModule,const char *szSetting,void *val,unsigned len) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_BLOB; + cws.value.cpbVal = (WORD)len; + cws.value.pbVal=(unsigned char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +/* inlined range tolerate versions */ + +__inline static BYTE DBGetContactSettingRangedByte(HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue, BYTE minValue, BYTE maxValue) { + BYTE bVal = (BYTE)DBGetContactSettingByte(hContact, szModule, szSetting, errorValue); + + if (bVal < minValue || bVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedByte failed",MB_ICONERROR); +#endif + return errorValue; + } + return bVal; +} + +__inline static WORD DBGetContactSettingRangedWord(HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue, WORD minValue, WORD maxValue) { + WORD wVal = (WORD)DBGetContactSettingWord(hContact, szModule, szSetting, errorValue); + + if (wVal < minValue || wVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedWord failed",MB_ICONERROR); +#endif + return errorValue; + } + return wVal; +} + +__inline static DWORD DBGetContactSettingRangedDword(HANDLE hContact, const char *szModule, const char *szSetting, DWORD errorValue, DWORD minValue, DWORD maxValue) { + DWORD dVal = DBGetContactSettingDword(hContact, szModule, szSetting, errorValue); + + if (dVal < minValue || dVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedDword failed",MB_ICONERROR); +#endif + return errorValue; + } + return dVal; +} + +#endif + +#endif // M_DATABASE_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h b/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h new file mode 100644 index 0000000000..a903313cb8 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h @@ -0,0 +1,114 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_LANGPACK_H__ +#define M_LANGPACK_H__ + +#define LANG_UNICODE 0x1000 + +//translates a single string into the user's local language v0.1.1.0+ +//wParam=0 +//lParam=(LPARAM)(const char*)szEnglish +//returns a pointer to the localised string. If there is no known translation +//it will return szEnglish. The return value does not need to be freed in any +//way +//Note that the Translate() macro as defined below will crash plugins that are +//loaded into Miranda 0.1.0.1 and earlier. If anyone's actually using one of +//these versions, I pity them. +#define MS_LANGPACK_TRANSLATESTRING "LangPack/TranslateString" +#define Translate(s) ((char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)(s))) +#define TranslateW(s) ((WCHAR*)CallService(MS_LANGPACK_TRANSLATESTRING,LANG_UNICODE,(LPARAM)(s))) +#ifdef _UNICODE + #define TranslateT(s) TranslateW(_T(s)) + #define TranslateTS(s) TranslateW(s) +#else + #define TranslateT(s) Translate(s) + #define TranslateTS(s) Translate(s) +#endif + +// If you're storing some string for calling later-on Translate or using it +// with an API call that does translation automatically marked with +// [TRANSLATED-BY-CORE] please wrap it with one of LPGEN macros in order to +// generate proper language pack. +#define LPGEN(s) s +#define LPGENW(s) L ## s +#ifdef _UNICODE + #define LPGENT(s) _T(s) +#else + #define LPGENT(s) s +#endif +//Those macros do NOTHING. They are just markers for lpgen.pl. + +//translates a dialog into the user's local language v0.1.1.0+ +//wParam=0 +//lParam=(LPARAM)(LANGPACKTRANSLATEDIALOG*)&lptd +//returns 0 on success, nonzero on failure +//This service only knows about the following controls: +//Window titles, STATIC, EDIT, Hyperlink, BUTTON +typedef struct { + int cbSize; + DWORD flags; + HWND hwndDlg; + const int *ignoreControls; //zero-terminated list of control IDs *not* to + //translate +} LANGPACKTRANSLATEDIALOG; +#define LPTDF_NOIGNOREEDIT 1 //translate all edit controls. By default + //non-read-only edit controls are not translated +#define LPTDF_NOTITLE 2 //do not translate the title of the dialog + +#define MS_LANGPACK_TRANSLATEDIALOG "LangPack/TranslateDialog" +__inline static INT_PTR TranslateDialogDefault(HWND hwndDlg) +{ + LANGPACKTRANSLATEDIALOG lptd; + lptd.cbSize=sizeof(lptd); + lptd.flags=0; + lptd.hwndDlg=hwndDlg; + lptd.ignoreControls=NULL; + return CallService(MS_LANGPACK_TRANSLATEDIALOG,0,(LPARAM)&lptd); +} + +//translates a menu into the user's local language v0.1.1.0+ +//wParam=(WPARAM)(HMENU)hMenu +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_LANGPACK_TRANSLATEMENU "LangPack/TranslateMenu" + +//returns the codepage used in the language pack v0.4.3.0+ +//wParam=0 +//lParam=0 +//returns the codepage stated in the langpack, or CP_ACP if no langpack is present +#define MS_LANGPACK_GETCODEPAGE "LangPack/GetCodePage" + +//returns the locale id associated with the language pack v0.4.3.0+ +//wParam=0 +//lParam=0 +//returns the Windows locale id stated in the langpack, or LOCALE_USER_DEFAULT if no langpack is present +#define MS_LANGPACK_GETLOCALE "LangPack/GetLocale" + +//returns the strdup/wcsdup of lparam according to the langpack v0.4.3.0+ +//wParam=0 +//lParam=(LPARAM)(char*)source string +//returns a string converted from char* to TCHAR* using the langpack codepage. +//This string should be freed using mir_free() then +#define MS_LANGPACK_PCHARTOTCHAR "LangPack/PcharToTchar" +#endif // M_LANGPACK_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h b/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h new file mode 100644 index 0000000000..086ca25d02 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h @@ -0,0 +1,832 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_NETLIB_H__ +#define M_NETLIB_H__ 1 + +#include "m_utils.h" + +//this module was created in 0.1.2.2 +//All error codes are returned via GetLastError() (or WSAGetLastError(): +//they're the same). +//This module is thread-safe where it is sensible for it to be so. This +//basically means that you can call anything from any thread, but don't try +//to predict what will happen if you try to recv() on the same connection from +//two different threads at the same time. +//Note that because the vast majority of the routines in this module return +//a pointer, I have decided to diverge from the rest of Miranda and go with +//the convention that functions return false on failure and nonzero on success. + +struct NETLIBHTTPREQUEST_tag; +typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; +struct NETLIBOPENCONNECTION_tag; +typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; + +//Initialises the netlib for a set of connections +//wParam=0 +//lParam=(LPARAM)(NETLIBUSER*)&nu +//Returns a HANDLE to be used for future netlib calls, NULL on failure +//NOTE: Netlib is loaded after any plugins, so you need to wait until +// ME_SYSTEM_MODULESLOADED before calling this function +//Netlib settings are stored under the module szSettingsModule +//All netlib settings being with "NL". +//The default settings for registered users that don't have any settings stored +//in the database are the same as those displayed by the page +//of the netlib options page. +//See notes below this function for the behaviour of HTTP gateways +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME +typedef int (*NETLIBHTTPGATEWAYINITPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc,NETLIBHTTPREQUEST *nlhr); +typedef int (*NETLIBHTTPGATEWAYBEGINPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc); +typedef int (*NETLIBHTTPGATEWAYWRAPSENDPROC)(HANDLE hConn,PBYTE buf,int len,int flags,MIRANDASERVICE pfnNetlibSend); +typedef PBYTE (*NETLIBHTTPGATEWAYUNWRAPRECVPROC)(NETLIBHTTPREQUEST *nlhr,PBYTE buf,int len,int *outBufLen,void *(*NetlibRealloc)(void*,size_t)); +typedef struct { + int cbSize; + char *szSettingsModule; //used for db settings and log + union { + char *szDescriptiveName; //used in options dialog, already translated + TCHAR *ptszDescriptiveName; + }; + DWORD flags; + char *szHttpGatewayHello; + char *szHttpGatewayUserAgent; //can be NULL to send no user-agent, also used by HTTPS proxies + NETLIBHTTPGATEWAYINITPROC pfnHttpGatewayInit; + NETLIBHTTPGATEWAYBEGINPROC pfnHttpGatewayBegin; //can be NULL if no beginning required + NETLIBHTTPGATEWAYWRAPSENDPROC pfnHttpGatewayWrapSend; //can be NULL if no wrapping required + NETLIBHTTPGATEWAYUNWRAPRECVPROC pfnHttpGatewayUnwrapRecv; //can be NULL if no wrapping required + int minIncomingPorts; //only if NUF_INCOMING. Will be used for validation of user input. +} NETLIBUSER; +#define NUF_INCOMING 0x01 //binds incoming ports +#define NUF_OUTGOING 0x02 //makes outgoing plain connections +#define NUF_HTTPGATEWAY 0x04 //can use HTTP gateway for plain sockets. ???HttpGateway* are valid. Enables the HTTP proxy option in options. +#define NUF_NOOPTIONS 0x08 //don't create an options page for this. szDescriptiveName is never used. +#define NUF_HTTPCONNS 0x10 //at least some connections are made for HTTP communication. Enables the HTTP proxy option in options. +#define NUF_NOHTTPSOPTION 0x20 //disable the HTTPS proxy option in options. Use this if all communication is HTTP. +#define NUF_UNICODE 0x40 //if set ptszDescriptiveName points to Unicode, otherwise it points to ANSI string +#define MS_NETLIB_REGISTERUSER "Netlib/RegisterUser" + +#if defined(_UNICODE) + #define NUF_TCHAR NUF_UNICODE +#else + #define NUF_TCHAR 0 +#endif + + + +//Assign a Netlib user handle a set of dynamic HTTP headers to be used with all +// +//HTTP connections that enable the HTTP-use-sticky headers flag. +//The headers persist until cleared with lParam=NULL. +// +//All memory should be allocated by the caller using malloc() from MS_SYSTEM_GET_MMI +//Once it has passed to Netlib, Netlib is the owner of it, the caller should not refer to the memory +//In any way after this point. +// +//wParam=(WPARAM)hNetLibUser +//lParam=(LPARAM)(char*)szHeaders +// +//NOTE: The szHeaders parameter should be a NULL terminated string following the HTTP header syntax. +//This string will be injected verbatim, thus the user should be aware of setting strings that are not +//headers. This service is NOT THREAD SAFE, only a single thread is expected to set the headers and a single +//thread reading the pointer internally, stopping race conditions and mutual exclusion don't happen. +// +//Version 0.3.2a+ (2003/10/27) +// +#define MS_NETLIB_SETSTICKYHEADERS "Netlib/SetStickyHeaders" + +/* Notes on HTTP gateway usage +When a connection is initiated through an HTTP proxy using +MS_NETLIB_OPENCONNECTION, netlib will GET nlu.szHttpGatewayHello and read +the replied headers. Once this succeeds nlu.pfnHttpGatewayInit will be called +with a valid handle to the connection, the NETLIBOPENCONNECTION structure that +MS_NETLIB_OPENCONNECTION was called with, and the replied HTTP headers as its +parameters. This function is responsible for recving and parsing the data then +calling MS_NETLIB_SETHTTPPROXYINFO with the appropriate information. +nlu.pfnHttpGatewayInit should return nonzero on success. If it returns zero +then the entire connection attempt will return signalling failure. If your +function needs to return an error code it can do so via SetLastError(). +If nlu.pfnHttpGatewayInit returns success without having called +MS_NETLIB_SETHTTPPROXYINFO then the connection attempt will fail anyway. +If you need more fine-tuned control over the GET/POST URLs than just appending +sequence numbers you can call MS_NETLIB_SETHTTPPROXYINFO from within your +wrap/unwrap functions (see below). + +Just prior to MS_NETLIB_OPENCONNECTION returning nlu.pfnHttpGatewayBegin is +called with the handle to the connection and the NETLIBOPENCONNECTION structure +as its parameters. This is for gateways that need special non-protocol +initialisation. If you do send any packets in this function, you probably want +to remember to use the MSG_NOHTTPGATEWAYWRAP flag. This function pointer can be +NULL if this functionality isn't needed. This function must return nonzero on +success. If it fails the connect attempt will return failure without changing +LastError. + +Whenever MS_NETLIB_SEND is called on a connection through an HTTP proxy and +the MSG_NOHTTPGATEWAYWRAP flags is not set and nlu.pfnHttpGatewayWrapSend is +not NULL, nlu.pfnHttpGatewayWrapSend will be called *instead* of sending the +data. It is this function's responsibility to wrap the sending data +appropriately for transmission and call pfnNetlibSend to send it again. +The flags parameter to nlu.pfnHttpGatewayWrapSend should be passed straight +through to the pfnNetlibSend call. It has already been ORed with +MSG_NOHTTPGATEWAYWRAP. nlu.pfnHttpGatewayWrapSend should return the a +number of the same type as MS_NETLIB_SEND, ie the number of bytes sent or +SOCKET_ERROR. The number of wrapping bytes should be subtracted so that the +return value appears as if the proxy wasn't there. +pfnNetlibSend() is identical to CallService(MS_NETLIB_SEND,...) but it's +quicker to call using this pointer than to do the CallService() lookup again. + +Whenever an HTTP reply is received inside MS_NETLIB_RECV the headers and data +are read into memory. If the headers indicate success then the data is passed +to nlu.pfnHttpGatewayUnwrapRecv (if it's non-NULL) for processing. This +function should remove (and do other processing if necessary) all HTTP proxy +specific headers and return a pointer to the buffer whose size is returned in +*outBufLen. If the buffer needs to be resized then NetlibRealloc() should be +used for that purpose, *not* your own CRT's realloc(). NetlibRealloc() behaves +identically to realloc() so it's possible to free the original buffer and +create a new one if that's the most sensible way to write your parser. +If errors are encountered you should SetLastError() and return NULL; +MS_NETLIB_RECV will return SOCKET_ERROR. If the passed buffer unwraps to +contain no actual data you should set *outBufLen to 0 but make sure you return +some non-NULL buffer that can be freed. + +When you call MS_NETLIB_SEND or MS_NETLIB_RECV from any of these functions, you +should use the MSG_DUMPPROXY flag so that the logging is neat. +*/ + +//Gets the user-configured settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//The pointers referred to in the returned struct will remain valid until +//the hUser handle is closed, or until the user changes the settings in the +//options page, so it's best not to rely on them for too long. +//Errors: ERROR_INVALID_PARAMETER +#define PROXYTYPE_SOCKS4 1 +#define PROXYTYPE_SOCKS5 2 +#define PROXYTYPE_HTTP 3 +#define PROXYTYPE_HTTPS 4 +#define PROXYTYPE_IE 5 +typedef struct { + int cbSize; // to be filled in before calling + int useProxy; // 1 or 0 + int proxyType; // a PROXYTYPE_ + char *szProxyServer; // can be NULL + int wProxyPort; // host byte order + int useProxyAuth; // 1 or 0. Always 0 for SOCKS4 + char *szProxyAuthUser; // can be NULL, always used by SOCKS4 + char *szProxyAuthPassword; // can be NULL + int useProxyAuthNtlm; // 1 or 0, only used by HTTP, HTTPS + int dnsThroughProxy; // 1 or 0 + int specifyIncomingPorts; // 1 or 0 + char *szIncomingPorts; // can be NULL. Of form "1024-1050,1060-1070,2000" + int specifyOutgoingPorts; // 0.3.3a+ + char *szOutgoingPorts; // 0.3.3a+ + int enableUPnP; // 0.6.1+ only for NUF_INCOMING + int validateSSL; +} NETLIBUSERSETTINGS; +#define MS_NETLIB_GETUSERSETTINGS "Netlib/GetUserSettings" + +//Changes the user-configurable settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is only really useful for people that specify NUF_NOOPTIONS +//and want to create their own options. +//Even if a setting is not active (eg szProxyAuthPassword when useProxyAuth is +//zero) that settings is still set for use in the options dialog. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_SETUSERSETTINGS "Netlib/SetUserSettings" + +//Closes a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function should be called on all handles returned by netlib functions +//once you are done with them. If it's called on a socket-type handle, the +//socket will be closed. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_CLOSEHANDLE "Netlib/CloseHandle" +__inline static INT_PTR Netlib_CloseHandle(HANDLE h) {return CallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)h,0);} + +//Open a port and wait for connections on it +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBBIND*)&nlb +//Returns a HANDLE on success, NULL on failure +//hUser should have been returned by MS_NETLIB_REGISTERUSER +//This function does the equivalent of socket(), bind(), getsockname(), +//listen(), accept() +//Internally this function creates a new thread which waits around in accept() +//for new connections. When one is received it calls nlb.pfnNewConnection *from +//this new thread* and then loops back to wait again. +//Close the returned handle to end the thread and close the open port. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket() or bind() or +// listen() or getsockname() +// +// Notes: +// +// During development of 0.3.1a+ (2003/07/04) passing wPort != 0 +// will result in an attempt to bind on the port given in wPort +// if this port is taken then you will get an error, so be sure to check +// for such conditions. +// +// passing wPort != 0 is for people who need to open a set port for +// daemon activities, usually passing wPort==0 is what you want and +// will result in a free port given by the TCP/IP socket layer and/or +// seeded from the user selected port ranges. +// +// also note that wPort if != 0, will have be converted to network byte order +// +/* pExtra was added during 0.3.4+, prior its just two args, since we use the cdecl convention +it shouldnt matter */ + +#define NETLIBBIND_SIZEOF_V1 16 // sizeof(NETLIBBIND) prior to 0.3.4+ (2004/08/05) +#define NETLIBBIND_SIZEOF_V2 20 // sizeof(NETLIBBIND) prior to 0.6+ (2006/07/03) + +typedef void (*NETLIBNEWCONNECTIONPROC_V2)(HANDLE hNewConnection,DWORD dwRemoteIP, void * pExtra); +typedef void (*NETLIBNEWCONNECTIONPROC)(HANDLE hNewConnection,DWORD dwRemoteIP); +/* This is NETLIBBIND prior to 2004/08/05+, DONT use this anymore unless you want to work +with older cores, pExtra isnt available on older cores and never will be - for a period of time, the ABI +for this service was broken and older NETLIBBINDs were not supported, if NULL is returned and the +argument is good, then tell the user to upgrade to the latest CVS. + +The older structure was used til around 2004/08/05 */ +typedef struct { + int cbSize; + NETLIBNEWCONNECTIONPROC pfnNewConnection; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order +} NETLIBBINDOLD; + +typedef struct { + int cbSize; + union { // new code should use V2 + NETLIBNEWCONNECTIONPROC pfnNewConnection; + NETLIBNEWCONNECTIONPROC_V2 pfnNewConnectionV2; + }; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order + void * pExtra; //argument is sent to callback, added during 0.3.4+ + DWORD dwExternalIP; //set on return, host byte order + WORD wExPort; //set on return, host byte order +} NETLIBBIND; +#define MS_NETLIB_BINDPORT "Netlib/BindPort" + +//Open a connection +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBOPENCONNECTION*)&nloc +//Returns a HANDLE to the new connection on success, NULL on failure +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//Internally this function is the equivalent of socket(), gethostbyname(), +//connect() +//If NLOCF_HTTP is set and hUser is configured for an HTTP or HTTPS proxy then +//this function will connect() to the proxy server only, without performing any +//initialisation conversation. +//If hUser is configured for an HTTP proxy and does not support HTTP gateways +//and you try to open a connection without specifying NLOCF_HTTP then this +//function will first attempt to open an HTTPS connection, if that fails it +//will try a direct connection, if that fails it will return failure with the +//error from the connect() during the direct connection attempt. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(), +// connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select() +// ERROR_TIMEOUT (during proxy communication) +// ERROR_BAD_FORMAT (very invalid proxy reply) +// ERROR_ACCESS_DENIED (by proxy) +// ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd) +// ERROR_INVALID_ACCESS (proxy refused identd auth) +// ERROR_INVALID_DATA (proxy returned invalid code) +// ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported) +// ERROR_GEN_FAILURE (socks5/https general failure) +// ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported) +// ERROR_INVALID_ADDRESS (socks5 address type not supported) +// HTTP: anything from nlu.pfnHttpGatewayInit, nlu.pfnHttpGatewayBegin, +// MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS +#define NLOCF_HTTP 0x0001 //this connection will be used for HTTP communications. If configured for an HTTP/HTTPS proxy the connection is opened as if there was no proxy. +#define NLOCF_STICKYHEADERS 0x0002 //this connection should send the sticky headers associated with NetLib user apart of any HTTP request +#define NLOCF_V2 0x0004 //this connection understands the newer structure, newer cbSize isnt enough +#define NLOCF_UDP 0x0008 // this connection is UDP +#define NLOCF_SSL 0x0010 // this connection is SSL +#define NLOCF_HTTPGATEWAY 0x0020 // this connection is HTTP Gateway + +/* Added during 0.4.0+ development!! (2004/11/29) prior to this, connect() blocks til a connection is made or +a hard timeout is reached, this can be anywhere between 30-60 seconds, and it stops Miranda from unloading whilst +this is attempted, clearing sucking - so now you can set a timeout of any value, there is still a hard limit which is +always reached by Windows, If a timeout occurs, or Miranda is exiting then you will get ERROR_TIMEOUT as soon as possible. +*/ +#define NETLIBOPENCONNECTION_V1_SIZE 16 /* old sizeof() is 14 bytes, but there is padding of 2 bytes */ +struct NETLIBOPENCONNECTION_tag { + int cbSize; + const char *szHost; //can contain the string representation of an IP + WORD wPort; //host byte order + DWORD flags; + unsigned int timeout; + /* optional, called in the context of the thread that issued the attempt, if it returns 0 the connection attempt is + stopped, the remaining timeout value can also be adjusted */ + int (*waitcallback) (unsigned int * timeout); +}; +//typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; //(above for reasons of forward referencing) +#define MS_NETLIB_OPENCONNECTION "Netlib/OpenConnection" + +//Sets the required information for an HTTP proxy connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPPROXYINFO*)&nlhpi +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is designed to be called from within pfnHttpGatewayInit +//See notes below MS_NETLIB_REGISTERUSER. +//Errors: ERROR_INVALID_PARAMETER +#define NLHPIF_USEGETSEQUENCE 0x0001 //append sequence numbers to GET requests +#define NLHPIF_USEPOSTSEQUENCE 0x0002 //append sequence numbers to POST requests +#define NLHPIF_GETPOSTSAMESEQUENCE 0x0004 //GET and POST use the same sequence +#define NLHPIF_HTTP11 0x0008 //HTTP 1.1 proxy +typedef struct { + int cbSize; + DWORD flags; + char *szHttpPostUrl; + char *szHttpGetUrl; + int firstGetSequence,firstPostSequence; +#if MIRANDA_VER >= 0x0900 + int combinePackets; +#endif +} NETLIBHTTPPROXYINFO; +#define MS_NETLIB_SETHTTPPROXYINFO "Netlib/SetHttpProxyInfo" + +//Gets the SOCKET associated with a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns the SOCKET on success, INVALID_SOCKET on failure +//hNetlibHandle should have been returned by MS_NETLIB_BINDPORT or +//MS_NETLIB_OPENCONNECTION only. +//Be careful how you use this socket because you might be connected via an +//HTTP proxy in which case calling send() or recv() will totally break things. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_GETSOCKET "Netlib/GetSocket" + +//URL-encode a string for x-www-form-urlencoded (and other) transmission +//wParam=0 +//lParam=(LPARAM)(const char *)pszString +//Returns a char* containing the new string. This must be freed with +//HeapFree(GetProcessHeap(),0,pszReturnString) when you're done with it. +//Returns NULL on error. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_URLENCODE "Netlib/UrlEncode" + +//Base64 decode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pszEncoded and nlb64.cchEncoded contain the input string and its length +//(excluding terminating zero). +//nlb64.pbDecoded and nlb64.cbDecoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64DecodedBufferSize() below. +//On return nlb64.cbDecoded is set to the actual length of the decoded data. +//Errors: ERROR_INVALID_PARAMETER, ERROR_INVALID_DATA, ERROR_BUFFER_OVERFLOW +typedef struct { + char *pszEncoded; + int cchEncoded; + PBYTE pbDecoded; + int cbDecoded; +} NETLIBBASE64; +#define Netlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3) +#define MS_NETLIB_BASE64DECODE "Netlib/Base64Decode" + +//Base64 encode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pbDecoded and nlb64.cbDecoded contain the input buffer and its length +//nlb64.pszEncoded and nlb64.cchEncoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64EncodedBufferSize() below. +//nlb64.pszEncoded is terminated with a 0. +//On return nlb64.cchEncoded is set to the actual length of the decoded data, +//excluding the terminating 0. +//Errors: ERROR_INVALID_PARAMETER, ERROR_BUFFER_OVERFLOW +#define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) +#define MS_NETLIB_BASE64ENCODE "Netlib/Base64Encode" + +//Send an HTTP request over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns number of bytes sent on success, SOCKET_ERROR on failure +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//Note that if you use NLHRF_SMARTAUTHHEADER and NTLM authentication is in use +//then the full NTLM authentication transaction occurs, comprising sending the +//domain, receiving the challenge, then sending the response. +//nlhr.resultCode and nlhr.szResultDescr are ignored by this function. +//Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND +typedef struct { + char *szName; + char *szValue; +} NETLIBHTTPHEADER; + +#define REQUEST_RESPONSE 0 //used by structure returned by MS_NETLIB_RECVHTTPHEADERS +#define REQUEST_GET 1 +#define REQUEST_POST 2 +#define REQUEST_CONNECT 3 +#define REQUEST_HEAD 4 // new in 0.5.1 +#define REQUEST_PUT 5 +#define REQUEST_DELETE 6 + +#define NLHRF_GENERATEHOST 0x00000001 //auto-generate a "Host" header from szUrl +#define NLHRF_REMOVEHOST 0x00000002 //remove any host and/or protocol portion of szUrl before sending it +#define NLHRF_SMARTREMOVEHOST 0x00000004 //removes host and/or protocol from szUrl unless the connection was opened through an HTTP or HTTPS proxy. +#define NLHRF_SMARTAUTHHEADER 0x00000008 //if the connection was opened through an HTTP or HTTPS proxy then send a Proxy-Authorization header if required. +#define NLHRF_HTTP11 0x00000010 //use HTTP 1.1 +#define NLHRF_PERSISTENT 0x00000020 //preserve connection on exit, open connection provided in the nlc field of the reply + //it should be supplied in nlc field of request for reuse or closed if not needed +#define NLHRF_SSL 0x00000040 //use SSL connection +#define NLHRF_NOPROXY 0x00000080 //do not use proxy server +#define NLHRF_REDIRECT 0x00000100 //handle HTTP redirect requests (response 30x), the resulting url provided in szUrl of the response +#define NLHRF_NODUMP 0x00010000 //never dump this to the log +#define NLHRF_NODUMPHEADERS 0x00020000 //don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION) +#define NLHRF_DUMPPROXY 0x00040000 //this transaction is a proxy communication. For dump filtering only. +#define NLHRF_DUMPASTEXT 0x00080000 //dump posted and reply data as text. Headers are always dumped as text. +#define NLHRF_NODUMPSEND 0x00100000 //do not dump sent message. +struct NETLIBHTTPREQUEST_tag { + int cbSize; + int requestType; //a REQUEST_ + DWORD flags; + char *szUrl; + NETLIBHTTPHEADER *headers; //If this is a POST request and headers + //doesn't contain a Content-Length it'll be added automatically + int headersCount; + char *pData; //data to be sent in POST request. + int dataLength; //must be 0 for REQUEST_GET/REQUEST_CONNECT + int resultCode; + char *szResultDescr; + HANDLE nlc; +}; +//typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; //(above for reasons of forward referencing) +#define MS_NETLIB_SENDHTTPREQUEST "Netlib/SendHttpRequest" + +//Receive HTTP headers +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=0 +//Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//nlhr->pData=NULL and nlhr->dataLength=0 always. The requested data should +//be retrieved using MS_NETLIB_RECV once the header has been parsed. +//If the headers haven't finished within 60 seconds the function returns NULL +//and ERROR_TIMEOUT. +//Errors: ERROR_INVALID_PARAMETER, any from MS_NETLIB_RECV or select() +// ERROR_HANDLE_EOF (connection closed before headers complete) +// ERROR_TIMEOUT (headers still not complete after 60 seconds) +// ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank) +// ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long) +// ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line) +#define MS_NETLIB_RECVHTTPHEADERS "Netlib/RecvHttpHeaders" + +//Free the memory used by a NETLIBHTTPREQUEST structure +//wParam=0 +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)pnlhr +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This should only be called on structures returned by +//MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an +//arbitrary structure will have disastrous results. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_FREEHTTPREQUESTSTRUCT "Netlib/FreeHttpRequestStruct" + +//Do an entire HTTP transaction +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//nlhr.szUrl should be a full HTTP URL. If it does not start with http://, that +//will be assumed (but it's best not to use this fact, for reasons of +//extensibility). +//This function is the equivalent of MS_NETLIB_OPENCONNECTION, +//MS_NETLIB_SENDHTTPREQ, MS_NETLIB_RECVHTTPHEADERS, MS_NETLIB_RECV, +//MS_NETLIB_CLOSEHANDLE +//nlhr.headers will be augmented with the following headers unless they have +//already been set by the caller: +// "Host" (regardless of whether it is requested in nlhr.flags) +// "User-Agent" (of the form "Miranda/0.1.2.2 (alpha)" or "Miranda/0.1.2.2") +// "Content-Length" (for POSTs only. Set to nlhr.dataLength) +//If you do not want to send one of these headers, create a nlhr.headers with +//szValue=NULL. +//In the return value headers, headerCount, pData, dataLength, resultCode and +//szResultDescr are all valid. +//In the return value pData[dataLength]==0 always, as an extra safeguard +//against programming slips. +//Note that the function can succeed (ie not return NULL) yet result in an HTTP +//error code. You should check that resultCode==2xx before proceeding. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above +// list of functions +#define MS_NETLIB_HTTPTRANSACTION "Netlib/HttpTransaction" + +//Send data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes sent on success, SOCKET_ERROR on failure +//Errors: ERROR_INVALID_PARAMETER +// anything from send(), nlu.pfnHttpGatewayWrapSend() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// anything from socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS +//flags: +#define MSG_NOHTTPGATEWAYWRAP 0x010000 //don't wrap the outgoing packet using nlu.pfnHttpGatewayWrapSend +#define MSG_NODUMP 0x020000 //don't dump this packet to the log +#define MSG_DUMPPROXY 0x040000 //this is proxy communiciation. For dump filtering only. +#define MSG_DUMPASTEXT 0x080000 //this is textual data, don't dump as hex +#define MSG_RAW 0x100000 //send as raw data, bypass any HTTP proxy stuff +#define MSG_DUMPSSL 0x200000 //this is SSL traffic. For dump filtering only. +typedef struct { + char *buf; + int len; + int flags; +} NETLIBBUFFER; +#define MS_NETLIB_SEND "Netlib/Send" +static __inline INT_PTR Netlib_Send(HANDLE hConn,const char *buf,int len,int flags) { + NETLIBBUFFER nlb={(char*)buf,len,flags}; + return CallService(MS_NETLIB_SEND,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Receive data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes read on success, SOCKET_ERROR on failure, +//0 if the connection has been closed +//Flags supported: MSG_PEEK, MSG_NODUMP, MSG_DUMPPROXY, MSG_NOHTTPGATEWAYWRAP, +// MSG_DUMPASTEXT, MSG_RAW +//On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are +// batched and cached and stuff, using this flag is not a guarantee that it +// will be obeyed, and if it is it may even be propogated to future calls +// even if you don't specify it then. Because of this, the flag should be +// considered an all-or-nothing thing: either use it for the entire duration +// of a connection, or not at all. +//Errors: ERROR_INVALID_PARAMETER, anything from recv() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// ERROR_INVALID_DATA (no Content-Length header in reply) +// ERROR_NOT_ENOUGH_MEMORY (Content-Length very large) +// ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved) +// anything from select(), MS_NETLIB_RECVHTTPHEADERS, +// nlu.pfnHttpGatewayUnwrapRecv, socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST +#define MS_NETLIB_RECV "Netlib/Recv" +static __inline INT_PTR Netlib_Recv(HANDLE hConn,char *buf,int len,int flags) { + NETLIBBUFFER nlb={buf,len,flags}; + return CallService(MS_NETLIB_RECV,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Determine the status of one or more connections +//wParam=0 +//lParam=(LPARAM)(NETLIBSELECT*)&nls +//Returns the number of ready connections, SOCKET_ERROR on failure, +//0 if the timeout expired. +//All handles passed to this function must have been returned by either +//MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT. +//The last handle in each list must be followed by either NULL or +//INVALID_HANDLE_VALUE. +//Errors: ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select() +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; +} NETLIBSELECT; + +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; + /* Added in v0.3.3+ */ + BOOL hReadStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hWriteStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hExceptStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ +} NETLIBSELECTEX; + +#define MS_NETLIB_SELECT "Netlib/Select" +// added in v0.3.3 +#define MS_NETLIB_SELECTEX "Netlib/SelectEx" + +//Shutdown connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)0 +//Returns 0 +#define MS_NETLIB_SHUTDOWN "Netlib/Shutdown" +__inline static void Netlib_Shutdown(HANDLE h) {CallService(MS_NETLIB_SHUTDOWN,(WPARAM)h,0);} + +//Create a packet receiver +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(int)maxPacketSize +//Returns a HANDLE on success, NULL on failure +//The packet receiver implements the common situation where you have variable +//length packets coming in over a connection and you want to split them up +//in order to handle them. +//The major limitation is that the buffer is created in memory, so you can't +//have arbitrarily large packets. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_CREATEPACKETRECVER "Netlib/CreatePacketRecver" + +//Get the next set of packets from a packet receiver +//wParam=(WPARAM)(HANDLE)hPacketRecver +//lParam=(LPARAM)(NETLIBPACKETRECVER*)&nlpr +//Returns the total number of bytes available in the buffer, 0 if the +//connection was closed, SOCKET_ERROR on error. +//hPacketRecver must have been returned by MS_NETLIB_CREATEPACKETRECVER +//If nlpr.bytesUsed is set to zero and the buffer is already full up to +//maxPacketSize, it is assumed that too large a packet has been received. All +//data in the buffer is discarded and receiving is begun anew. This will +//probably cause alignment problems so if you think this is likely to happen +//then you should deal with it yourself. +//Closing the packet receiver will not close the associated connection, but +//will discard any bytes still in the buffer, so if you intend to carry on +//reading from that connection, make sure you have processed the buffer first. +//This function is the equivalent of a memmove() to remove the first bytesUsed +//from the buffer, select() if dwTimeout is not INFINITE, then MS_NETLIB_RECV. +//Errors: ERROR_INVALID_PARAMETER, ERROR_TIMEOUT, +// anything from select(), MS_NETLIB_RECV +typedef struct { + int cbSize; + DWORD dwTimeout; //fill before calling. In milliseconds. INFINITE is valid + int bytesUsed; //fill before calling. This many bytes are removed from the start of the buffer. Set to 0 on return + int bytesAvailable; //equal to the return value, unless the return value is 0 + int bufferSize; //same as parameter to MS_NETLIB_CREATEPACKETRECVER + BYTE *buffer; //contains the recved data +} NETLIBPACKETRECVER; +#define MS_NETLIB_GETMOREPACKETS "Netlib/GetMorePackets" + +//Add a message to the log (if it's running) +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(const char *)szMessage +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//Do not include a final line ending in szMessage. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_LOG "Netlib/Log" + +//Sets a gateway polling timeout interval +//wParam=(WPARAM)(HANDLE)hConn +//lParam=(LPARAM)timeout +//Returns previous timeout value +//Errors: -1 +#define MS_NETLIB_SETPOLLINGTIMEOUT "Netlib/SetPollingTimeout" + +//Makes connection SSL +//wParam=(WPARAM)(HANDLE)hConn +//lParam=(LPARAM)(NETLIBSSL*)&nlssl or null if no certficate validation required +//Returns 0 on failure 1 on success +#define MS_NETLIB_STARTSSL "Netlib/StartSsl" + +typedef struct +{ + int cbSize; + const char *host; //Expected host name + int flags; //Reserved +} NETLIBSSL; + + +//here's a handy piece of code to let you log using printf-style specifiers: +//#include and before including this header in order to +//use it. +#if defined va_start && (defined _STDIO_DEFINED || defined _STDIO_H_) && (!defined NETLIB_NOLOGGING) +static INT_PTR Netlib_Logf(HANDLE hUser,const char *fmt,...) +{ + va_list va; + char szText[1024]; + + __try + { + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + return CallService(MS_NETLIB_LOG,(WPARAM)hUser,(LPARAM)szText); + } + __except(EXCEPTION_EXECUTE_HANDLER) {} + return 0; +} +#endif //defined va_start + +///////////////////////////////////////////////////////////////////////////////////////// +// Security providers (0.6+) + +#define NNR_UNICODE 1 + +#ifdef UNICODE +#define NNR_TCHAR 1 +#else +#define NNR_TCHAR 0 +#endif + +// Inits a required security provider. Right now only NTLM is supported +// Returns HANDLE = NULL on error or non-null value on success +#define MS_NETLIB_INITSECURITYPROVIDER "Netlib/InitSecurityProvider" + +static __inline HANDLE Netlib_InitSecurityProvider( char* szProviderName ) +{ + return (HANDLE)CallService( MS_NETLIB_INITSECURITYPROVIDER, 0, (LPARAM)szProviderName ); +} + +typedef struct { + size_t cbSize; + const TCHAR* szProviderName; + const TCHAR* szPrincipal; + unsigned flags; +} + NETLIBNTLMINIT2; + +#define MS_NETLIB_INITSECURITYPROVIDER2 "Netlib/InitSecurityProvider2" + +static __inline HANDLE Netlib_InitSecurityProvider2( const TCHAR* szProviderName, const TCHAR* szPrincipal ) +{ + NETLIBNTLMINIT2 temp = { sizeof(temp), szProviderName, szPrincipal, NNR_TCHAR }; + return (HANDLE)CallService( MS_NETLIB_INITSECURITYPROVIDER2, 0, (LPARAM)&temp ); +} + + +// Destroys a security provider's handle, provided by Netlib_InitSecurityProvider. +// Right now only NTLM is supported +#define MS_NETLIB_DESTROYSECURITYPROVIDER "Netlib/DestroySecurityProvider" + +static __inline void Netlib_DestroySecurityProvider( char* szProviderName, HANDLE hProvider ) +{ + CallService( MS_NETLIB_DESTROYSECURITYPROVIDER, (WPARAM)szProviderName, (LPARAM)hProvider ); +} + +// Returns the NTLM response string. The result value should be freed using mir_free + +typedef struct { + char* szChallenge; + char* userName; + char* password; +} + NETLIBNTLMREQUEST; + +#define MS_NETLIB_NTLMCREATERESPONSE "Netlib/NtlmCreateResponse" + +static __inline char* Netlib_NtlmCreateResponse( HANDLE hProvider, char* szChallenge, char* login, char* psw ) +{ + NETLIBNTLMREQUEST temp = { szChallenge, login, psw }; + return (char*)CallService( MS_NETLIB_NTLMCREATERESPONSE, (WPARAM)hProvider, (LPARAM)&temp ); +} + +typedef struct { + size_t cbSize; + const char* szChallenge; + const TCHAR* szUserName; + const TCHAR* szPassword; + unsigned complete; + unsigned flags; +} + NETLIBNTLMREQUEST2; + +#define MS_NETLIB_NTLMCREATERESPONSE2 "Netlib/NtlmCreateResponse2" + +static __inline char* Netlib_NtlmCreateResponse2( HANDLE hProvider, char* szChallenge, TCHAR* szLogin, TCHAR* szPass, unsigned *complete ) +{ + NETLIBNTLMREQUEST2 temp = { sizeof(temp), szChallenge, szLogin, szPass, 0, NNR_TCHAR }; + char* res = (char*)CallService( MS_NETLIB_NTLMCREATERESPONSE2, (WPARAM)hProvider, (LPARAM)&temp ); + *complete = temp.complete; + return res; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Netlib hooks (0.8+) + +// WARNING: these hooks are being called in the context of the calling thread, without switching +// to the first thread, like all another events do. The hook procedure should be ready for the +// multithreaded mode +// +// Parameters: +// wParam: NETLIBNOTIFY* - points to the data being sent/received +// lParam: NETLIBUSER* - points to the protocol definition + +typedef struct { + NETLIBBUFFER* nlb; // pointer to the request buffer + int result; // amount of bytes really sent/received +} + NETLIBNOTIFY; + +#define ME_NETLIB_FASTRECV "Netlib/OnRecv" // being called on every receive +#define ME_NETLIB_FASTSEND "Netlib/OnSend" // being called on every send +#define ME_NETLIB_FASTDUMP "Netlib/OnDump" // being called on every dump + +#endif // M_NETLIB_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_options.h b/plugins/!NotAdopted/WinPopup/sdk/m_options.h new file mode 100644 index 0000000000..0231efaedd --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_options.h @@ -0,0 +1,138 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_OPTIONS_H__ +#define M_OPTIONS_H__ + +/* Opt/Initialise +The user opened the options dialog. Modules should do whatever initialisation +they need and call opt/addpage one or more times if they want pages displayed +in the options dialog +wParam=addInfo +lParam=0 +addInfo should be passed straight to the wParam of opt/addpage +*/ +#define ME_OPT_INITIALISE "Opt/Initialise" + +/* Opt/AddPage +Must only be called during an opt/initialise hook +Adds a page to the options dialog +wParam=addInfo +lParam=(LPARAM)(OPTIONSDIALOGPAGE*)odp +addInfo must have come straight from the wParam of opt/initialise +Pages in the options dialog operate just like pages in property sheets. See the +Microsoft documentation for details on how they operate. +Strings in the structure can be released as soon as the service returns, but +icons must be kept around. This is not a problem if you're loading them from a +resource. +Prior to v0.1.2.1 the options dialog would resize to fit the largest page, but +since then it is fixed in size. The largest page that fits neatly is 314x240 +DLUs. +*/ + +// WARNING: do not use Translate(TS) for pszTitle, pszGroup or pszTab as they +// are translated by the core, which may lead to double translation. +// Use LPGEN instead which are just dummy wrappers/markers for "lpgen.pl". +typedef struct { + int cbSize; + int position; //a position number, lower numbers are topmost + union { + char* pszTitle; // [TRANSLATED-BY-CORE] + TCHAR* ptszTitle; + }; + DLGPROC pfnDlgProc; + char *pszTemplate; + HINSTANCE hInstance; + HICON hIcon; //v0.1.0.1+ + union { + char* pszGroup; //v0.1.0.1+ [TRANSLATED-BY-CORE] + TCHAR* ptszGroup; //v0.1.0.1+ + }; + int groupPosition; //v0.1.0.1+ + HICON hGroupIcon; //v0.1.0.1+ + DWORD flags; //v0.1.2.1+ + int nIDBottomSimpleControl; //v0.1.2.1+ if in simple mode the dlg will be cut off after this control, 0 to disable + int nIDRightSimpleControl; //v0.1.2.1+ if in simple mode the dlg will be cut off after this control, 0 to disable + UINT *expertOnlyControls; + int nExpertOnlyControls; //v0.1.2.1+ these controls will be hidden in simple mode. Array must remain valid for duration of dlg. + + #if MIRANDA_VER >= 0x0600 + union { + char* pszTab; //v0.6.0.0+ [TRANSLATED-BY-CORE] + TCHAR* ptszTab; //v0.6.0.0+ + }; + #endif + + #if MIRANDA_VER >= 0x0800 + LPARAM dwInitParam; //v0.8.0.0+ a value to pass to lParam of WM_INITDIALOG message + #endif +} + OPTIONSDIALOGPAGE; + +#define OPTIONPAGE_OLD_SIZE (offsetof(OPTIONSDIALOGPAGE, flags)) +#if MIRANDA_VER >= 0x0600 + #define OPTIONPAGE_OLD_SIZE2 (offsetof(OPTIONSDIALOGPAGE, pszTab)) +#endif +#if MIRANDA_VER >= 0x0800 + #define OPTIONPAGE_OLD_SIZE3 (offsetof(OPTIONSDIALOGPAGE, dwInitParam)) +#endif + +#define ODPF_SIMPLEONLY 1 // page is only shown when in simple mode +#define ODPF_EXPERTONLY 2 // " expert mode +#define ODPF_BOLDGROUPS 4 // give group box titles a bold font +#define ODPF_UNICODE 8 // string fields in OPTIONSDIALOGPAGE are WCHAR* +#define ODPF_USERINFOTAB 16 // options page is tabbed + +#if defined( _UNICODE ) + #define ODPF_TCHAR ODPF_UNICODE +#else + #define ODPF_TCHAR 0 +#endif + +#define PSN_EXPERTCHANGED 2 //sent to pages via WM_NOTIFY when the expert checkbox is clicked. lParam=new state +#define PSM_ISEXPERT (WM_USER+101) //returns true/false +#define PSM_GETBOLDFONT (WM_USER+102) //returns HFONT used for group box titles +#define MS_OPT_ADDPAGE "Opt/AddPage" + +//Opens the options dialog, optionally at the specified page v0.1.2.1+ +//wParam=0 +//lParam=(LPARAM)(OPENOPTIONSDIALOG*)&ood; +//Returns 0 on success, nonzero on failure +//The behaviour if the options dialog is already open is that it will just be +//activated, the page won't be changed. This may change in the future. +typedef struct { + int cbSize; + const char *pszGroup; //set to NULL if it's a root item + const char *pszPage; //set to NULL to just open the options at no + //specific page + const char *pszTab; //set to NULL to just open the options at no + //specific tab +} OPENOPTIONSDIALOG; +#define MS_OPT_OPENOPTIONS "Opt/OpenOptions" + +//Opens the options dialog, with only specified page v0.8.0.x+ +#define MS_OPT_OPENOPTIONSPAGE "Opt/OpenOptionsPage" + +#define SETTING_SHOWEXPERT_DEFAULT 1 + +#endif //M_OPTIONS_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h b/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h new file mode 100644 index 0000000000..8cbd5a4ba1 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h @@ -0,0 +1,85 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_PLUGINS_H__ +#define M_PLUGINS_H__ + +/* + Undocumented: Do NOT use. + Version: 0.3.4.1+ (2004/10/04) +*/ +#define DBPE_DONE 1 +#define DBPE_CONT 0 +#define DBPE_HALT (-1) +typedef struct PLUGIN_DB_ENUM { + int cbSize; + // 0 = continue, 1 = found, -1 = stop now + int (*pfnEnumCallback) ( char * pluginname, /*DATABASELINK*/ void * link, LPARAM lParam); + LPARAM lParam; +} PLUGIN_DB_ENUM; +#define MS_PLUGINS_ENUMDBPLUGINS "Plugins/DbEnumerate" + + +//#define DEFMOD_PROTOCOLICQ 1 //removed from v0.3 alpha +//#define DEFMOD_PROTOCOLMSN 2 //removed from v0.1.2.0+ +#define DEFMOD_UIFINDADD 3 +#define DEFMOD_UIUSERINFO 4 +#define DEFMOD_SRMESSAGE 5 +#define DEFMOD_SRURL 6 +#define DEFMOD_SREMAIL 7 +#define DEFMOD_SRAUTH 8 +#define DEFMOD_SRFILE 9 +#define DEFMOD_UIHELP 10 +#define DEFMOD_UIHISTORY 11 +//#define DEFMOD_RNDCHECKUPD 12 //removed from v0.3.1 alpha +//#define DEFMOD_RNDICQIMPORT 13 //removed from v0.3 alpha +#define DEFMOD_RNDAUTOAWAY 14 +#define DEFMOD_RNDUSERONLINE 15 +//#define DEFMOD_RNDCRYPT 16 // v0.1.0.1-v0.1.2.0 +#define DEFMOD_SRAWAY 17 // v0.1.0.1+ +#define DEFMOD_RNDIGNORE 18 // v0.1.0.1+ +#define DEFMOD_UIVISIBILITY 19 // v0.1.1.0+, options page only +#define DEFMOD_UICLUI 20 // v0.1.1.0+ +//#define DEFMOD_UIPLUGINOPTS 21 // removed from 0.4.0.1 +//#define DEFMOD_PROTOCOLNETLIB 22 // removed from 0.8.0.5 +#define DEFMOD_RNDIDLE 23 // v0.3.4a+ +#define DEFMOD_CLISTALL 24 // v0.3.4a+ (2004/09/28) +#define DEFMOD_DB 25 // v0.3.4.3+ (2004/10/11) +#define DEFMOD_FONTSERVICE 26 // v0.7.0+ (2006/11/17) +#define DEFMOD_UPDATENOTIFY 27 +#define DEFMOD_SSL 28 // v0.8.0+ +#define DEFMOD_HIGHEST 28 + +//plugins/getdisabledefaultarray +//gets an array of the modules that the plugins report they want to replace +//wParam=lParam=0 +//returns a pointer to an array of INT_PTR, with elements 1 or 0 indexed by the +//DEFMOD_ constants. 1 to signify that the default module shouldn't be loaded. +//this is primarily for use by the core's module initialiser, but could also +//be used by modules that are doing naughty things that are very +//feature-dependent +#define MS_PLUGINS_GETDISABLEDEFAULTARRAY "Plugins/GetDisableDefaultArray" + +#endif // M_PLUGINS_H__ + + diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_popup.h b/plugins/!NotAdopted/WinPopup/sdk/m_popup.h new file mode 100644 index 0000000000..419f2bd396 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_popup.h @@ -0,0 +1,424 @@ +/* +=============================================================================== + PopUp plugin +Plugin Name: PopUp +Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net) + Victor Pavlychko aka zazoo (nullbie@gmail.com) +=============================================================================== +The purpose of this plugin is to give developers a common "platform/interface" +to show PopUps. It is born from the source code of NewStatusNotify, another +plugin I've made. + +Remember that users *must* have this plugin enabled, or they won't get any +popup. Write this in the requirements, do whatever you wish ;-)... but tell +them! +=============================================================================== +*/ + +#ifndef M_POPUP_H +#define M_POPUP_H + +/* +NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I +have put a "Enable/Disable" item. You can add your own "enable/disable" items +by adding these lines before you call MS_CLIST_ADDMAINMENUITEM: +mi.pszPopUpName = Translate("PopUps"); +mi.position = 0; //You don't need it and it's better if you put it to zero. +*/ + +#define MAX_CONTACTNAME 2048 +#define MAX_SECONDLINE 2048 + +// This is the basic data you'll need to fill and pass to the service function. +typedef struct +{ + HANDLE lchContact; // Handle to the contact, can be NULL (main contact). + HICON lchIcon; // Handle to a icon to be shown. Cannot be NULL. + union + { + char lptzContactName[MAX_CONTACTNAME]; // This is the contact name or the first line in the plugin. Cannot be NULL. + char lpzContactName[MAX_CONTACTNAME]; + }; + union + { + char lptzText[MAX_SECONDLINE]; // This is the second line text. Users can choose to hide it. Cannot be NULL. + char lpzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; // COLORREF to be used for the background. Can be NULL, default will be used. + COLORREF colorText; // COLORREF to be used for the text. Can be NULL, default will be used. + WNDPROC PluginWindowProc; // Read below. Can be NULL; default will be used. + void * PluginData; // Read below. Can be NULL. +} POPUPDATA, * LPPOPUPDATA; + +// Extended popup data +typedef struct +{ + HANDLE lchContact; + HICON lchIcon; + union + { + char lptzContactName[MAX_CONTACTNAME]; + char lpzContactName[MAX_CONTACTNAME]; + }; + union + { + char lptzText[MAX_SECONDLINE]; + char lpzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; + COLORREF colorText; + WNDPROC PluginWindowProc; + void * PluginData; + int iSeconds; // Custom delay time in seconds. -1 means "forever", 0 means "default time". + char cZero[16]; // Some unused bytes which may come useful in the future. +} POPUPDATAEX, *LPPOPUPDATAEX; + +// Unicode version of POPUPDATAEX +typedef struct +{ + HANDLE lchContact; + HICON lchIcon; + union + { + WCHAR lptzContactName[MAX_CONTACTNAME]; + WCHAR lpwzContactName[MAX_CONTACTNAME]; + }; + union + { + WCHAR lptzText[MAX_SECONDLINE]; + WCHAR lpwzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; + COLORREF colorText; + WNDPROC PluginWindowProc; + void * PluginData; + int iSeconds; + char cZero[16]; +} POPUPDATAW, *LPPOPUPDATAW; + +#if defined(_UNICODE) || defined(UNICODE) + typedef POPUPDATAW POPUPDATAT; + typedef LPPOPUPDATAW LPPOPUPDATAT; +#else + typedef POPUPDATAEX POPUPDATAT; + typedef LPPOPUPDATAEX LPPOPUPDATAT; +#endif + +/* PopUp/AddPopup +Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer. + +wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress +lParam = 0 + +Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values. +NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled. +Otherwise, it can return anything else... + +Popup Plus 2.0.4.0+ +You may pass additional creation flags via lParam: + APF_RETURN_HWND ....... function returns handle to newly created popup window (however this calls are a bit slower) + APF_CUSTOM_POPUP ...... new popup is created in hidden state and doesn't obey to popup queue rules. + you may control it via UM_* messages and custom window procedure +*/ +#define APF_RETURN_HWND 0x1 +#define APF_CUSTOM_POPUP 0x2 + +#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp" +static INT_PTR __inline PUAddPopUp(POPUPDATA* ppdp) { + return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0); +} + +#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx" +static INT_PTR __inline PUAddPopUpEx(POPUPDATAEX* ppdp) { + return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0); +} + +#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW" +static INT_PTR __inline PUAddPopUpW(POPUPDATAW* ppdp) { + return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW + #define PUAddPopUpT PUAddPopUpW +#else + #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPEX + #define PUAddPopUpT PUAddPopUpEx +#endif + + +/* PopUp/GetContact +Returns the handle to the contact associated to the specified PopUpWindow. + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = 0; + +Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure. +*/ +#define MS_POPUP_GETCONTACT "PopUp/GetContact" +static HANDLE __inline PUGetContact(HWND hPopUpWindow) { + return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0); +} + +/* PopUp/GetPluginData +Returns custom plugin date associated with popup + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress; + +Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure. + +IMPORTANT NOTE: it doesn't seem to work if you do: +CallService(..., (LPARAM)aPointerToAStruct); +and then use that struct. +Do this, instead: +aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct); +and it will work. Just look at the example I've written above (PopUpDlgProc). + +*/ +#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData" +static void __inline * PUGetPluginData(HWND hPopUpWindow) { + long * uselessPointer = NULL; + return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer); +} + +/* PopUp/IsSecondLineShown +Checks if second line is enable + +wParam = 0 +lParam = 0 + +Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line. +*/ +#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown" +static BOOL __inline PUIsSecondLineShown() { + return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0); +} + +/* PopUp/Query + +Requests an action or an answer from PopUp module. + +wParam = (WPARAM)wpQuery + +returns 0 on success, -1 on error, 1 on stupid calls ;-) +*/ + +#define PUQS_ENABLEPOPUPS 1 // returns 0 if state was changed, 1 if state wasn't changed +#define PUQS_DISABLEPOPUPS 2 // " " +#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled. + +#define MS_POPUP_QUERY "PopUp/Query" + +/* UM_FREEPLUGINDATA +Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL) + +wParam = 0 +lParam = 0 +*/ +#define UM_FREEPLUGINDATA (WM_USER + 0x0200) + +/* UM_DESTROYPOPUP +Send this message when you want to destroy the popup, or use the function below. + +wParam = 0 +lParam = 0 +*/ +#define UM_DESTROYPOPUP (WM_USER + 0x0201) +static int __inline PUDeletePopUp(HWND hWndPopUp) { + return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0); +} + +/* UM_INITPOPUP +This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable. +Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life. +Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-) + +wParam = (WPARAM)(HWND)hPopUpWindow (this is useless, you get message inside your popup window) +lParam = 0 +*/ +#define UM_INITPOPUP (WM_USER + 0x0202) + +/* PopUp/Changetext +Changes the text displayed in the second line of the popup. + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(char*)lpzNewText + +returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call +PUIsSecondLineShown() before changing the text...) +*/ +#define MS_POPUP_CHANGETEXT "PopUp/Changetext" +static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) { + return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText); +} + +#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW" +static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) { + return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXTW + #define PUChangeTextT PUChangeTextW +#else + #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXT + #define PUChangeTextT PUChangeText +#endif + +/* PopUp/Change +Changes the entire popup + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(POPUPDATAEX*)newData +*/ +#define MS_POPUP_CHANGE "PopUp/Change" +static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) { + return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData); +} + +#define MS_POPUP_CHANGEW "PopUp/ChangeW" +static int __inline PUChangeW(HWND hWndPopUp, POPUPDATAW *newData) { + return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_CHANGET MS_POPUP_CHANGEW + #define PUChangeT PUChangeW +#else + #define MS_POPUP_CHANGET MS_POPUP_CHANGE + #define PUChangeT PUChange +#endif + +/* UM_CHANGEPOPUP +This message is triggered by Change/ChangeText services. You also may post it directly :) + +wParam = Modification type +lParam = value of type defined by wParam +*/ + +#define CPT_TEXT 1 // lParam = (char *)text +#define CPT_TEXTW 2 // lParam = (WCHAR *)text +#define CPT_TITLE 3 // lParam = (char *)title +#define CPT_TITLEW 4 // lParam = (WCHAR *)title +#define CPT_DATA 5 // lParam = (POPUPDATA *)data +#define CPT_DATAEX 6 // lParam = (POPUPDATAEX *)data +#define CPT_DATAW 7 // lParam = (POPUPDATAW *)data + +#define UM_CHANGEPOPUP (WM_USER + 0x0203) + +#if defined(_UNICODE) || defined(UNICODE) + #define CPT_TEXTT CPT_TEXTW + #define CPT_TITLET CPT_TITLEW + #define CPT_DATAT CPT_DATAW +#else + #define CPT_TEXTT CPT_TEXT + #define CPT_TITLET CPT_TITLE + #define CPT_DATAT CPT_DATA +#endif + +/* PopUp/ShowMessage +This is mainly for developers. +Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal +window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not. + +wParam = (char *)lpzMessage +lParam = 0; + +Returns: 0 if the popup was shown, -1 in case of failure. +*/ +#define SM_WARNING 0x01 //Triangle icon. +#define SM_NOTIFY 0x02 //Exclamation mark icon. +#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage" +#define MS_POPUP_SHOWMESSAGEW "PopUp/ShowMessageW" + +static int __inline PUShowMessage(char *lpzText, BYTE kind) { + return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind); +} + +static int __inline PUShowMessageW(wchar_t *lpwzText, BYTE kind) { + return (int)CallService(MS_POPUP_SHOWMESSAGEW, (WPARAM)lpwzText,(LPARAM)kind); +} + +#ifdef _UNICODE +#define PUShowMessageT PUShowMessageW +#else +#define PUShowMessageT PUShowMessage +#endif + +//------------- Class API ----------------// + +typedef struct { + int cbSize; + int flags; + char *pszName; + union { + char *pszDescription; + wchar_t *pwszDescription; + TCHAR *ptszDescription; + }; + + HICON hIcon; + + COLORREF colorBack; + COLORREF colorText; + + WNDPROC PluginWindowProc; + + int iSeconds; +} POPUPCLASS; + +#define PCF_UNICODE 0x0001 + +#ifdef _UNICODE +#define PCF_TCHAR PCF_UNICODE +#else +#define PCF_TCHAR 0 +#endif + +// wParam = 0 +// lParam = (POPUPCLASS *)&pc +#define MS_POPUP_REGISTERCLASS "PopUp/RegisterClass" + +typedef struct { + int cbSize; + char *pszClassName; + union { + const char *pszTitle; + const wchar_t *pwszTitle; + const TCHAR *ptszTitle; + }; + union { + const char *pszText; + const wchar_t *pwszText; + const TCHAR *ptszText; + }; + void *PluginData; + HANDLE hContact; +} POPUPDATACLASS; + +// wParam = 0 +// lParam = (POPUPDATACLASS *)&pdc +#define MS_POPUP_ADDPOPUPCLASS "PopUp/AddPopupClass" + +static INT_PTR __inline ShowClassPopup(char *name, char *title, char *text) { + POPUPDATACLASS d = {sizeof(d), name}; + d.pszTitle = title; + d.pszText = text; + return CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&d); +} + +static INT_PTR __inline ShowClassPopupW(char *name, wchar_t *title, wchar_t *text) { + POPUPDATACLASS d = {sizeof(d), name}; + d.pwszTitle = title; + d.pwszText = text; + return CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&d); +} + +#ifdef _UNICODE +#define ShowClassPopupT ShowClassPopupW +#else +#define ShowClassPopupT ShowClassPopup +#endif + +#endif // __m_popup_h__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h b/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h new file mode 100644 index 0000000000..d2032db977 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h @@ -0,0 +1,487 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//this module was created in v0.1.1.0 + +#ifndef M_PROTOCOLS_H__ +#define M_PROTOCOLS_H__ 1 + +#include "statusmodes.h" + +//call a specific protocol service. See the PS_ constants in m_protosvc.h +#if MIRANDA_VER < 0x800 +__inline static INT_PTR CallProtoService(const char *szModule,const char *szService,WPARAM wParam,LPARAM lParam) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", szModule, szService); + str[MAXMODULELABELLENGTH-1] = 0; + return CallService(str,wParam,lParam); +} +#endif + +//send a general request through the protocol chain for a contact +//wParam=0 +//lParam=(LPARAM)(CCSDATA*)&ccs +//returns the value as documented in the PS_ definition (m_protosvc.h) + +typedef struct { + HANDLE hContact; + const char *szProtoService; //a PS_ constant + WPARAM wParam; + LPARAM lParam; +} CCSDATA; + +#define MS_PROTO_CALLCONTACTSERVICE "Proto/CallContactService" + +#if MIRANDA_VER < 0x800 +__inline static INT_PTR CallContactService(HANDLE hContact,const char *szProtoService,WPARAM wParam,LPARAM lParam) +{ + CCSDATA ccs; + ccs.hContact=hContact; + ccs.szProtoService=szProtoService; + ccs.wParam=wParam; + ccs.lParam=lParam; + return CallService(MS_PROTO_CALLCONTACTSERVICE,0,(LPARAM)&ccs); +} +#endif + +//a general network 'ack' +//wParam=0 +//lParam=(LPARAM)(ACKDATA*)&ack +//Note that just because definitions are here doesn't mean they will be sent. +//Read the documentation for the function you are calling to see what replies +//you will receive. +typedef struct { + int cbSize; + const char *szModule; //the name of the protocol module which initiated this ack + HANDLE hContact; + int type; //an ACKTYPE_ constant + int result; //an ACKRESULT_ constant + HANDLE hProcess; //a caller-defined process code + LPARAM lParam; //caller-defined extra info +} ACKDATA; +#define ACKTYPE_MESSAGE 0 +#define ACKTYPE_URL 1 +#define ACKTYPE_FILE 2 +#define ACKTYPE_CHAT 3 +#define ACKTYPE_AWAYMSG 4 +#define ACKTYPE_AUTHREQ 5 +#define ACKTYPE_ADDED 6 +#define ACKTYPE_GETINFO 7 +#define ACKTYPE_SETINFO 8 +#define ACKTYPE_LOGIN 9 +#define ACKTYPE_SEARCH 10 +#define ACKTYPE_NEWUSER 11 +#define ACKTYPE_STATUS 12 +#define ACKTYPE_CONTACTS 13 //send/recv of contacts +#define ACKTYPE_AVATAR 14 //send/recv of avatars from a protocol +#define ACKTYPE_EMAIL 15 //notify if the unread emails changed + +#define ACKRESULT_SUCCESS 0 +#define ACKRESULT_FAILED 1 + +//'in progress' result codes: +#define ACKRESULT_CONNECTING 100 +#define ACKRESULT_CONNECTED 101 +#define ACKRESULT_INITIALISING 102 +#define ACKRESULT_SENTREQUEST 103 //waiting for reply... +#define ACKRESULT_DATA 104 //blob of file data sent/recved, or search result +#define ACKRESULT_NEXTFILE 105 //file transfer went to next file +#define ACKRESULT_FILERESUME 106 //a file is about to be received, see PS_FILERESUME +#define ACKRESULT_DENIED 107 //a file send has been denied +#define ACKRESULT_STATUS 108 //an ack or a series of acks to do with a task have a status change +#define ACKRESULT_LISTENING 109 //waiting for connection +#define ACKRESULT_CONNECTPROXY 110 //connecting to file proxy +#define ACKRESULT_SEARCHRESULT 111 //result of extended search + +#define ME_PROTO_ACK "Proto/Ack" + +// v0.3.2+: When result is ACKRESULT_FAILED or ACKRESULT_DENIED, lParam can point to +// a human readable string with an explanation. For example: "The message was too +// long to be delivered". If no error message is specified, lParam must be NULL. +// Right now only explanations from ACKTYPE_MESSAGE is shown. + +//when type==ACKTYPE_FILE && (result==ACKRESULT_DATA || result==ACKRESULT_FILERESUME), +//lParam points to this + +#if MIRANDA_VER >= 0x0900 + #define FNAMECHAR TCHAR +#else + #define FNAMECHAR char +#endif + +#define PFTS_RECEIVING 0 +#define PFTS_SENDING 1 +#define PFTS_UNICODE 2 +#define PFTS_UTF 4 + +#if defined( _UNICODE ) + #define PFTS_TCHAR PFTS_UNICODE +#else + #define PFTS_TCHAR 0 +#endif + +typedef struct tagPROTOFILETRANSFERSTATUS_V1 +{ + size_t cbSize; + HANDLE hContact; + int sending; + char **files; + int totalFiles; + int currentFileNumber; + unsigned long totalBytes; + unsigned long totalProgress; + char *workingDir; + char *currentFile; + unsigned long currentFileSize; + unsigned long currentFileProgress; + unsigned long currentFileTime; //as seconds since 1970 +} +PROTOFILETRANSFERSTATUS_V1; + +#if MIRANDA_VER < 0x0900 + +typedef PROTOFILETRANSFERSTATUS_V1 PROTOFILETRANSFERSTATUS; + +#else + +typedef struct tagPROTOFILETRANSFERSTATUS +{ + size_t cbSize; + HANDLE hContact; + DWORD flags; // one of PFTS_* constants + + union { + char **pszFiles; + TCHAR **ptszFiles; + WCHAR **pwszFiles; + }; + + int totalFiles; + int currentFileNumber; + unsigned __int64 totalBytes; + unsigned __int64 totalProgress; + + union { + char *szWorkingDir; + TCHAR *tszWorkingDir; + WCHAR *wszWorkingDir; + }; + + union { + char *szCurrentFile; + TCHAR *tszCurrentFile; + WCHAR *wszCurrentFile; + }; + + unsigned __int64 currentFileSize; + unsigned __int64 currentFileProgress; + unsigned __int64 currentFileTime; //as seconds since 1970 +} +PROTOFILETRANSFERSTATUS; + +#endif + +//Enumerate the currently running protocols +//wParam=(WPARAM)(int*)&numberOfProtocols +//lParam=(LPARAM)(PROTOCOLDESCRIPTOR***)&ppProtocolDescriptors +//Returns 0 on success, nonzero on failure +//Neither wParam nor lParam may be NULL +//The list returned by this service is the protocol modules currently installed +//and running. It is not the complete list of all protocols that have ever been +//installed. +//IMPORTANT NOTE #1: the list returned is not static, it may be changed in the +//program's lifetime. Do not use this list in the global context, copy protocols +//names otherwise. +//IMPORTANT NOTE #2: in version 0.8 this service is mapped to the MS_PROTO_ENUMACCOUNTS +//service to provide the compatibility with old plugins (first three members of +//PROTOACCOUNT are equal to the old PROTOCOLDESCRIPTOR format). If you declare the +//MIRANDA_VER macro with value greater or equal to 0x800, use MS_PROTO_ENUMPROTOS +//service instead to obtain the list of running protocols instead of accounts. +//Note that a protocol module need not be an interface to an Internet server, +//they can be encryption and loads of other things, too. +//And yes, before you ask, that is triple indirection. Deal with it. +//Access members using ppProtocolDescriptors[index]->element + +#define PROTOCOLDESCRIPTOR_V3_SIZE (sizeof(size_t)+sizeof(INT_PTR)+sizeof(char*)) + + // initializes an empty account +typedef struct tagPROTO_INTERFACE* ( *pfnInitProto )( const char* szModuleName, const TCHAR* szUserName ); + +// deallocates an account instance +typedef int ( *pfnUninitProto )( struct tagPROTO_INTERFACE* ); + +// removes an account from the database +typedef int ( *pfnDestroyProto )( struct tagPROTO_INTERFACE* ); + +typedef struct { + size_t cbSize; + char *szName; // unique name of the module + int type; // module type, see PROTOTYPE_ constants + + // 0.8.0+ additions + #if MIRANDA_VER >= 0x800 + pfnInitProto fnInit; // initializes an empty account + pfnUninitProto fnUninit; // deallocates an account instance + pfnDestroyProto fnDestroy; // removes an account + #endif +} + PROTOCOLDESCRIPTOR; + +// v0.3.3+: +// +// For recv, it will go from lower to higher, so in this case: +// check ignore, decrypt (encryption), translate +// +// For send, it will go translate, encrypt, ignore(??), send +// +// The DB will store higher numbers here, LOWER in the protocol chain, and lower numbers +// here HIGHER in the protocol chain +// +#define PROTOTYPE_IGNORE 50 // added during v0.3.3 +#define PROTOTYPE_PROTOCOL 1000 +#define PROTOTYPE_ENCRYPTION 2000 +#define PROTOTYPE_FILTER 3000 +#define PROTOTYPE_TRANSLATION 4000 +#define PROTOTYPE_OTHER 10000 //avoid using this if at all possible +#define PROTOTYPE_DISPROTO 20000 + +#if MIRANDA_VER >= 0x800 + #define MS_PROTO_ENUMPROTOS "Proto/EnumProtos" + #define MS_PROTO_ENUMPROTOCOLS "Proto/EnumAccounts" +#else + #define MS_PROTO_ENUMPROTOCOLS "Proto/EnumProtocols" +#endif + +//determines if a protocol module is loaded or not +//wParam=0 +//lParam=(LPARAM)(const char*)szName +//Returns a pointer to the PROTOCOLDESCRIPTOR if the protocol is loaded, or +//NULL if it isn't. +#define MS_PROTO_ISPROTOCOLLOADED "Proto/IsProtocolLoaded" + +//gets the network-level protocol associated with a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//Returns a char* pointing to the asciiz name of the protocol or NULL if the +//contact has no protocol. There is no need to free() it or anything. +//This is the name of the module that actually accesses the network for that +//contact. +#define MS_PROTO_GETCONTACTBASEPROTO "Proto/GetContactBaseProto" + +//determines whether the specified contact has the given protocol in its chain +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//Returns -1 if it is base protocol, positive number if it is filter and 0 if it doesn't +#define MS_PROTO_ISPROTOONCONTACT "Proto/IsProtoOnContact" + +#define PROTOTYPE_SELFTYPING_OFF 0 +#define PROTOTYPE_SELFTYPING_ON 1 +//This service is for notifying protocols that the user is typing a message v0.3.3+ +//in a message dialog. +//This is typically sent by a message dialog when a user in the clist is typing. +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)typing state +//NOTE: Only protocols should generally call this service +#define MS_PROTO_SELFISTYPING "Proto/SelfIsTyping" + +#define PROTOTYPE_CONTACTTYPING_OFF 0 +#define PROTOTYPE_CONTACTTYPING_INFINITE 2147483647 +//This service is for notifying message dialogs/other plugins of a user typing. v0.3.3+ +//This is typically sent by a protocol when a user in the clist is typing. +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)time (secs) +//NOTE: The time in seconds is used to tell a message dialog (or other plugin) +//how long to display its notification. If time is 0, then notification +//of typing ends. +//NOTE: Only protocols should generally call this service +#define MS_PROTO_CONTACTISTYPING "Proto/ContactIsTyping" + +//This hook notifies when a user is typing. If a message dialog supports sending v0.3.3+ +//typing notifications it should hook this event and fire the +//ProtoService PSS_USERISTYPING to the contacts protocol *after* verifying +//that the hContact is not NULL and the the user wishes to send notifications +//to this user (checked visibility, individual typing blocking, etc). +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)typing state +#define ME_PROTO_CONTACTISTYPING "Proto/ContactIsTypingEvent" + +// -------------- accounts support --------------------- 0.8.0+ + +typedef struct tagACCOUNT +{ + int cbSize; // sizeof this structure + char* szModuleName; // unique physical account name (matches database module name) + int type; // always equal to PROTOTYPE_PROTOCOL + TCHAR* tszAccountName; // user-defined account name + char* szProtoName; // physical protocol name + int bIsEnabled; // is account enabled? + int bIsVisible; // is account visible? + int iOrder; // account order in various menus & lists + BOOL bOldProto; // old-styled account (one instance per dll) + struct tagPROTO_INTERFACE* ppro; // pointer to the underlying object + + HWND hwndAccMgrUI; + BOOL bAccMgrUIChanged; + BOOL bDynDisabled; // dynamic disable flag, is never written to db +} + PROTOACCOUNT; + +//account enumeration service +//wParam=(WPARAM)(int*)piNumAccounts +//lParam=(LPARAM)(PROTOACCOUNT**)paAccounts +#define MS_PROTO_ENUMACCOUNTS "Proto/EnumAccounts" + +__inline static INT_PTR ProtoEnumAccounts( int* accNumber, PROTOACCOUNT*** accArray ) +{ return CallService( MS_PROTO_ENUMACCOUNTS, ( WPARAM )accNumber, (LPARAM)accArray ); +} + +//retrieves an account's interface by its physical name (database module) +//wParam=0 +//lParam=(LPARAM)(char*)szAccountName +//return value = PROTOACCOUNT* or NULL +#define MS_PROTO_GETACCOUNT "Proto/GetAccount" + +__inline static PROTOACCOUNT* ProtoGetAccount( const char* accName ) +{ return (PROTOACCOUNT*)CallService( MS_PROTO_GETACCOUNT, 0, (LPARAM)accName ); +} + +//this event is fired when the accounts list gets changed +//wParam = event type (1 - added, 2 - changed, 3 - deleted, 4 - upgraded, 5 - enabled/disabled) +//lParam = (LPARAM)(PROTOACCOUNT*) - account being changed + +#define PRAC_ADDED 1 +#define PRAC_CHANGED 2 +#define PRAC_REMOVED 3 +#define PRAC_UPGRADED 4 +#define PRAC_CHECKED 5 + + +#define ME_PROTO_ACCLISTCHANGED "Proto/AccListChanged" + +//displays the Account Manager +//wParam=0 +//lParam=0 +#define MS_PROTO_SHOWACCMGR "Protos/ShowAccountManager" + +//determines if an account is enabled or not +//wParam = 0 +//lParam = (LPARAM)(PROTOACCOUNT*) +//Returns 1 if an account is valid and enabled, 0 otherwise +#define MS_PROTO_ISACCOUNTENABLED "Proto/IsAccountEnabled" + +__inline static int IsAccountEnabled( const PROTOACCOUNT* pa ) +{ +#if MIRANDA_VER < 0x0900 + return pa && (( pa->bIsEnabled && !pa->bDynDisabled ) || pa->bOldProto ); +#else + return (int)CallService( MS_PROTO_ISACCOUNTENABLED, 0, (LPARAM)pa ); +#endif +} + +//determines if an account is locked or not +//wParam = 0 +//lParam = (LPARAM)(char*)szAccountName +//Returns 1 if an account is locked and not supposed to change status, 0 otherwise +#define MS_PROTO_ISACCOUNTLOCKED "Proto/IsAccountLocked" + + +//gets the account associated with a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//Returns a char* pointing to the asciiz name of the protocol or NULL if the +//contact has no protocol. There is no need to mir_free() it or anything. +//This is the name of the module that actually accesses the network for that +//contact. +#define MS_PROTO_GETCONTACTBASEACCOUNT "Proto/GetContactBaseAccount" + +/* -------------- avatar support --------------------- + +First a protocol must report it supports PF4_AVATARS via PS_GETCAPS, secondly +it will return the following acks for certain events, the protocol must use +ProtoBroadcastAck(), listeners must hook ME_PROTO_ACK, note that lParam = ACKDATA* + +*/ + +/* + + The following ACKs MUST be sent in order of .result via ProtoBroadcastAck() + + .szModule = protocol module + .hContact = contact the avatar is for, or 0 if its for the user + .type = ACKTYPE_AVATAR + .result = ACKRESULT_CONNECTING, ACKRESULT_CONNECTED, ACKRESULT_SENTREQUEST, ACKRESULT_DATA + .hProcess = protocol specific + .lParam = 0 + + Once the transfer is complete the following ACKs MUST be sent by the protocol + + .result = ACKRESULT_SUCCESS or ACKRESULT_FAILED + .hProcess = (HANDLE) &PROTO_AVATAR_INFORMATION + .lParam = 0; + + Anytime before or during the ack or series of acks ACKRESULT_STATUS maybe sent, this might + be sent a long while before anything else happens (or after anything happening) For avatars + it allows callers to identify status information to do with the avatar, including the time + before background transport has been created, so that you know an avatar will be exchanged + sometime in the future. + + When ACKRESULT_STATUS, hProcess is the result code - the value of this is protocol dependent, + See protocol documentation to do with avatars for what codes are defined and what they mean. + +*/ + +#define PA_FORMAT_UNKNOWN 0 // the protocol can not determine much about the "bitmap" +#define PA_FORMAT_PNG 1 // the image is PNG +#define PA_FORMAT_JPEG 2 +#define PA_FORMAT_ICON 3 +#define PA_FORMAT_BMP 4 +#define PA_FORMAT_GIF 5 +#define PA_FORMAT_SWF 6 +#define PA_FORMAT_XML 7 + +typedef struct { + int cbSize; // sizeof() + HANDLE hContact; // this might have to be set by the caller too + int format; // PA_FORMAT_* + char filename[MAX_PATH]; // full path to filename which contains the avatar +} PROTO_AVATAR_INFORMATION; + +#define GAIF_FORCE 1 // force an update of the avatar if there is none + +#define GAIR_SUCCESS 0 // information about the avatar has been returned +#define GAIR_WAITFOR 1 // you must hook ME_PROTO_ACK and wait for replies about avatar status +#define GAIR_NOAVATAR 2 // sorry, this contact has no avatars + +/* + wParam : GAIF_* + lParam : (LPARAM) &PROTO_AVATAR_INFORMATION + Affect : Make a request to the protocol to return information about a hContact's avatar (or main user) + it can return information, tell you there is none, or if forced start requesting an avatar. + Note: + Version: 0.3.4+ (2004/09/13) +*/ +#define PS_GETAVATARINFO "/GetAvatarInformation" + + +#endif // M_PROTOCOLS_H diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h b/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h new file mode 100644 index 0000000000..bae8146373 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h @@ -0,0 +1,136 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ +//this module was created in v0.1.1.0 + +//this header file is for the use of protocol modules only. Other users should +//use the functions exposed in m_protocols.h and m_protosvc.h + +#ifndef M_PROTOMOD_H__ +#define M_PROTOMOD_H__ 1 + +#include + +#include "m_protocols.h" + +//notify the protocol manager that you're around +//wParam=0 +//lParam=(PROTOCOLDESCRIPTOR*)&descriptor +//returns 0 on success, nonzero on failure +//This service must be called in your module's Load() routine. +//descriptor.type can be a value other than the PROTOTYPE_ constants specified +//above to provide more precise positioning information for the contact +//protocol lists. It is strongly recommended that you give values relative to +//the constants, however, by adding or subtracting small integers (<=100). +//PROTOTYPE_PROTOCOL modules must not do this. The value must be exact. +//See MS_PROTO_ENUMPROTOCOLS for more notes. +#define MS_PROTO_REGISTERMODULE "Proto/RegisterModule" + +//adds the specified protocol module to the chain for a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//returns 0 on success, nonzero on failure +//The module is added in the correct position according to the type given when +//it was registered. +#define MS_PROTO_ADDTOCONTACT "Proto/AddToContact" + +//removes the specified protocol module from the chain for a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//returns 0 on success, nonzero on failure +#define MS_PROTO_REMOVEFROMCONTACT "Proto/RemoveFromContact" + +//Create a protocol service +//Protocol services are called with wParam and lParam as standard if they are +//to be called with CallProtoService() (as PS_ services are) +//If they are called with CallContactService() (PSS_ and PSR_ services) then +//they are called with lParam=(CCSDATA*)&ccs and wParam an opaque internal +//reference that should be passed unchanged to MS_PROTO_CHAIN*. +__inline static HANDLE CreateProtoServiceFunction(const char *szModule,const char *szService,MIRANDASERVICE serviceProc) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", szModule, szService); + str[MAXMODULELABELLENGTH-1] = 0; + return CreateServiceFunction(str,serviceProc); +} + +//Call the next service in the chain for this send operation +//wParam=wParam +//lParam=lParam +//The return value should be returned immediately +//wParam and lParam should be passed as the parameters that your service was +//called with. wParam must remain untouched but lParam is a CCSDATA structure +//that can be copied and modified if needed. +//Typically, the last line of any chaining protocol function is +//return CallService(MS_PROTO_CHAINSEND,wParam,lParam); +#define MS_PROTO_CHAINSEND "Proto/ChainSend" + +//Call the next service in the chain for this receive operation +//wParam=wParam +//lParam=lParam +//The return value should be returned immediately +//wParam and lParam should be passed as the parameters that your service was +//called with. wParam must remain untouched but lParam is a CCSDATA structure +//that can be copied and modified if needed. +//When being initiated by the network-access protocol module, wParam should be +//zero. +//Thread safety: ms_proto_chainrecv is completely thread safe since 0.1.2.0 +//Calls to it are translated to the main thread and passed on from there. The +//function will not return until all callees have returned, irrepective of +//differences between threads the functions are in. +#define MS_PROTO_CHAINRECV "Proto/ChainRecv" + +//Broadcast a ME_PROTO_ACK event +//wParam=0 +//lParam=(LPARAM)(ACKDATA*)&ack +//returns the return value of the notifyeventhooks() call +//Thread safety: me_proto_ack is completely thread safe since 0.1.2.0 +//See the notes in core/modules.h under NotifyEventHooks() +#define MS_PROTO_BROADCASTACK "Proto/BroadcastAck" +__inline static INT_PTR ProtoBroadcastAck(const char *szModule,HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam) +{ + ACKDATA ack={0}; + ack.cbSize=sizeof(ACKDATA); + ack.szModule=szModule; ack.hContact=hContact; + ack.type=type; ack.result=result; + ack.hProcess=hProcess; ack.lParam=lParam; + return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack); +} + +/* -- Added during 0.3.4 (2004/09/27) development! ----- +*/ + +/* + wParam: (HANDLE)hContact + lParam: 0 + Affect: Given a hContact, return the protocol that is registered for it, or NULL if no such protocol exists, + the returned string does not have to be freed and is valid even for multiple threads. + Note: Prior to 2004/09/28 this service WAS NOT THREAD SAFE and was slower + Note: Prior to 2004/09/28 this service would return NULL for a hContact if the protocol module + associated with the hContact was not currently loaded, no such check is performed now. + Version: 0.3.4 (2004/09/28) +*/ +#define MS_PROTODIR_PROTOFROMCONTACT MS_PROTO_GETCONTACTBASEPROTO + +#endif // M_PROTOMOD_H__ + + diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h b/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h new file mode 100644 index 0000000000..c314bda3aa --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h @@ -0,0 +1,775 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +//this module was created in v0.1.1.0 + +//none of these services should be used on their own (ie using CallService, +//CreateServiceFunction(), etc), hence the PS_ prefix. Instead use the services +//exposed in m_protocols.h + +#ifndef M_PROTOSVC_H__ +#define M_PROTOSVC_H__ 1 + +#include "m_protocols.h" + +/*************************** NON-CONTACT SERVICES ************************/ +//these should be called with CallProtoService() + +//Get the capability flags of the module. +//wParam=flagNum +//lParam=0 +//Returns a bitfield corresponding to wParam. See the #defines below +//Should return 0 for unknown values of flagNum +//Non-network-access modules should return flags to represent the things they +//actually actively use, not the values that it is known to pass through +//correctly +#define PFLAGNUM_1 1 +#define PF1_IMSEND 0x00000001 //supports IM sending +#define PF1_IMRECV 0x00000002 //supports IM receiving +#define PF1_IM (PF1_IMSEND|PF1_IMRECV) +#define PF1_URLSEND 0x00000004 //supports separate URL sending +#define PF1_URLRECV 0x00000008 //supports separate URL receiving +#define PF1_URL (PF1_URLSEND|PF1_URLRECV) +#define PF1_FILESEND 0x00000010 //supports file sending +#define PF1_FILERECV 0x00000020 //supports file receiving +#define PF1_FILE (PF1_FILESEND|PF1_FILERECV) +#define PF1_MODEMSGSEND 0x00000040 //supports broadcasting away messages +#define PF1_MODEMSGRECV 0x00000080 //supports reading others' away messages +#define PF1_MODEMSG (PF1_MODEMSGSEND|PF1_MODEMSGRECV) +#define PF1_SERVERCLIST 0x00000100 //contact lists are stored on the server, not locally. See notes below +#define PF1_AUTHREQ 0x00000200 //will get authorisation requests for some or all contacts +#define PF1_ADDED 0x00000400 //will get 'you were added' notifications +#define PF1_VISLIST 0x00000800 //has an invisible list +#define PF1_INVISLIST 0x00001000 //has a visible list for when in invisible mode +#define PF1_INDIVSTATUS 0x00002000 //supports setting different status modes to each contact +#define PF1_EXTENSIBLE 0x00004000 //the protocol is extensible and supports plugin-defined messages +#define PF1_PEER2PEER 0x00008000 //supports direct (not server mediated) communication between clients +#define PF1_NEWUSER 0x00010000 //supports creation of new user IDs +#define PF1_CHAT 0x00020000 //has a realtime chat capability +#define PF1_INDIVMODEMSG 0x00040000 //supports replying to a mode message request with different text depending on the contact requesting +#define PF1_BASICSEARCH 0x00080000 //supports a basic user searching facility +#define PF1_EXTSEARCH 0x00100000 //supports one or more protocol-specific extended search schemes +#define PF1_CANRENAMEFILE 0x00200000 //supports renaming of incoming files as they are transferred +#define PF1_FILERESUME 0x00400000 //can resume broken file transfers, see PS_FILERESUME below +#define PF1_ADDSEARCHRES 0x00800000 //can add search results to the contact list +#define PF1_CONTACTSEND 0x01000000 //can send contacts to other users +#define PF1_CONTACTRECV 0x02000000 //can receive contacts from other users +#define PF1_CONTACT (PF1_CONTACTSEND|PF1_CONTACTRECV) +#define PF1_CHANGEINFO 0x04000000 //can change our user information stored on server +#define PF1_SEARCHBYEMAIL 0x08000000 //supports a search by e-mail feature +#define PF1_USERIDISEMAIL 0x10000000 //set if the uniquely identifying field of the network is the e-mail address +#define PF1_SEARCHBYNAME 0x20000000 //supports searching by nick/first/last names +#define PF1_EXTSEARCHUI 0x40000000 //has a dialog box to allow searching all the possible fields +#define PF1_NUMERICUSERID 0x80000000 //the unique user IDs for this protocol are numeric + +#define PFLAGNUM_2 2 //the status modes that the protocol supports +#define PF2_ONLINE 0x00000001 //an unadorned online mode +#define PF2_INVISIBLE 0x00000002 +#define PF2_SHORTAWAY 0x00000004 //Away on ICQ, BRB on MSN +#define PF2_LONGAWAY 0x00000008 //NA on ICQ, Away on MSN +#define PF2_LIGHTDND 0x00000010 //Occupied on ICQ, Busy on MSN +#define PF2_HEAVYDND 0x00000020 //DND on ICQ +#define PF2_FREECHAT 0x00000040 +#define PF2_OUTTOLUNCH 0x00000080 +#define PF2_ONTHEPHONE 0x00000100 +#define PF2_IDLE 0x00000200 //added during 0.3.4 (2004/09/13) + +//the status modes that the protocol supports +//away-style messages for. Uses the PF2_ flags. +// PFLAGNUM_3 is implemented by protocol services that support away messages +// there may be no support and 0 will be returned, if there is +// support it will consist of a set of PF2_* bits +#define PFLAGNUM_3 3 + +// given a status will return what bit flags to test for +static __inline unsigned long Proto_Status2Flag(int status) +{ + switch(status) { + case ID_STATUS_ONLINE: return PF2_ONLINE; + case ID_STATUS_OFFLINE: return 0; + case ID_STATUS_INVISIBLE: return PF2_INVISIBLE; + case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH; + case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE; + case ID_STATUS_AWAY: return PF2_SHORTAWAY; + case ID_STATUS_NA: return PF2_LONGAWAY; + case ID_STATUS_OCCUPIED: return PF2_LIGHTDND; + case ID_STATUS_DND: return PF2_HEAVYDND; + case ID_STATUS_FREECHAT: return PF2_FREECHAT; + case ID_STATUS_IDLE: return PF2_IDLE; + } + return 0; +} + +#define PFLAGNUM_4 4 //misc options +#define PF4_FORCEAUTH 0x00000001 // forces auth requests to be sent when adding users +#define PF4_FORCEADDED 0x00000002 // forces "you were added" requests to be sent +#define PF4_NOCUSTOMAUTH 0x00000004 // protocol doesn't support custom auth text (doesn't show auth text box) +#define PF4_SUPPORTTYPING 0x00000008 // protocol supports user is typing messages v0.3.3+ +#define PF4_SUPPORTIDLE 0x00000010 // protocol understands idle, added during v0.3.4+ (2004/09/13) +#define PF4_AVATARS 0x00000020 // protocol has avatar support, added during v0.3.4 (2004/09/13) +#define PF4_OFFLINEFILES 0x00000040 // protocols supports sending files to offline users (v0.5.2) +#define PF4_IMSENDUTF 0x00000080 // protocol is able to process messages in utf-8 (v.0.7.0+) +#define PF4_IMSENDOFFLINE 0x00000100 // protocol supports sending offline messages (v0.8.0+) +#define PF4_INFOSETTINGSVC 0x00000200 // protocol supports user info translation services (v0.8.0+) +#define PF4_NOAUTHDENYREASON 0x00000400 // protocol doesn't support authorization deny reason (v0.9.0+) + +#define PFLAG_UNIQUEIDTEXT 100 //returns a static buffer of text describing the unique field by which this protocol identifies users (already translated), or NULL + +#define PFLAG_MAXCONTACTSPERPACKET 200 //v0.1.2.2+: returns the maximum number of contacts which can be sent in a single PSS_CONTACTS, lParam=(LPARAM)hContact. + +#define PFLAG_UNIQUEIDSETTING 300 // returns the setting name of where the unique id is stored + +#define PFLAG_MAXLENOFMESSAGE 400 // v0.3.2+: return the maximum length of an instant message, lParam=(LPARAM)hContact + +/* + + A protocol might not support this cap, it allows a protocol to say that PFLAGNUM_2 is for + statuses contacts supports, and that PFLAGNUM_5 is for statuses a protocol can SET TO ITSELF, + if this is not replied to, then PFLAGNUM_2 is alone in telling you which statuses a protocol + can set to and what statuses a contact can set to as well. + + E.g. A protocol might report 'wireless' users but a login of the protocol from Miranda can + not set itself to 'wireless' so PFLAGNUM_2 would return PF2_ONTHEPHONE and PFLAGNUM_5 would + return PF2_ONTHEPHONE as well, this means "I will get contacts who are on the phone but you can + not set on the phone" and so on. + + Do note that the reply here is a NEGATION of bitflags reported for PFLAGNUM_2, e.g. returning + PF2_ONTHEPHONE for PFLAGNUM_2 and returning the same for PFLAGNUM_5 says that you DO NOT SUPPORT + PF2_ONTHEPHONE for the user to PS_SETSTATUS to, but you will expect other contacts to have + that status, e.g. you can get onthephone for users but can't go online with onthephone. + + The same PF2_* status flags are used in the reply. + +Added during 0.3.4 (2004/09/14) +*/ +#define PFLAGNUM_5 5 + +/* Deleting contacts from protocols that store the contact list on the server: +If a contact is deleted while the protocol is online, it is expected that the +protocol will have hooked me_db_contact_deleted and take the appropriate +action by itself. +If a contact is deleted while the protocol is offline, the contact list will +display a message to the user about the problem, and set the byte setting +"CList"/"Delete" to 1. Each time such a protocol changes status from offline +or connecting to online the contact list will check for contacts with this +flag set and delete them at that time. Your hook for me_db_contact_deleted +will pick this up and everything will be good. +*/ +#define PS_GETCAPS "/GetCaps" + +//Get a human-readable name for the protocol +//wParam=cchName +//lParam=(LPARAM)(char*)szName +//Returns 0 on success, nonzero on failure +//cchName is the number of characters in the buffer szName +//This should be translated before being returned +//Some example strings are: +//"ICQ", "AIM", "RSA-1024 Encryption" +#define PS_GETNAME "/GetName" + +//Loads one of the protocol-specific icons +//wParam=whichIcon +//lParam=0 +//Returns the HICON, or NULL on failure +//The returned HICON must be DestroyIcon()ed. +//The UI should overlay the online icon with a further UI-specified icon to +//represent the exact status mode. +#define PLI_PROTOCOL 1 //An icon representing the protocol (eg the multicoloured flower for ICQ) +#define PLI_ONLINE 2 //Online state icon for that protocol (eg green flower for ICQ) +#define PLI_OFFLINE 3 //Offline state icon for that protocol (eg red flower for ICQ) +#define PLIF_LARGE 0 //OR with one of the above to get the large (32x32 by default) icon +#define PLIF_SMALL 0x10000 //OR with one of the above to get the small (16x16 by default) icon +#define PLIF_ICOLIB 0x20000 //the returned HICON is managed by IcoLib, DO NOT DestroyIcon() it +#define PLIF_ICOLIBHANDLE 0x40000 //the function will return IcoLib handle not HICON +#define PS_LOADICON "/LoadIcon" + +//Change the protocol's status mode +//wParam=newMode, from ui/contactlist/statusmodes.h +//lParam=0 +//returns 0 on success, nonzero on failure +//Will send an ack with: +//type=ACKTYPE_STATUS, result=ACKRESULT_SUCCESS, hProcess=(HANDLE)previousMode, lParam=newMode +//when the change completes. This ack is sent for all changes, not just ones +//caused by calling this function. +//Note that newMode can be ID_STATUS_CONNECTING<=newMode