summaryrefslogtreecommitdiff
path: root/plugins/BossKeyPlus/src/BossKey.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/BossKeyPlus/src/BossKey.cpp')
-rw-r--r--plugins/BossKeyPlus/src/BossKey.cpp923
1 files changed, 923 insertions, 0 deletions
diff --git a/plugins/BossKeyPlus/src/BossKey.cpp b/plugins/BossKeyPlus/src/BossKey.cpp
new file mode 100644
index 0000000000..b61d3f3624
--- /dev/null
+++ b/plugins/BossKeyPlus/src/BossKey.cpp
@@ -0,0 +1,923 @@
+/*
+ BossKey - Hide Miranda from your boss :)
+ Copyright (C) 2002-2003 Goblineye Entertainment, (C) 2007-2010 Billy_Bons
+
+ 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 "BossKey.h"
+#include "m_updater.h"
+#include "m_msg_buttonsbar.h"
+
+// multiple instances support:
+// when hotkey is hit, handler notifies all listen windows
+//#pragma data_seg("Shared") // Shared data segment
+// these must be shared, since they're called by the hook (The hook is global and called from the context of each process)
+//HHOOK g_hKeyHook = NULL; // shared
+// this isn't referenced by hook, but should be shared to keep a reference count of multiple instances
+//WORD g_wRefCount = 0; // reference count. when this is 0 on init, the hook is created. when this is 0 on destruction, the hook is destroyed.
+//#pragma data_seg() // end of shared data segment
+
+// unique to this DLL, not to be shared
+HINSTANCE g_hInstance;
+CLIST_INTERFACE *pcli;
+HANDLE g_hmGenMenuInit, g_hIcon, g_hMenuItem, g_hHideService, g_hIsHiddenService;
+HWINEVENTHOOK g_hWinHook;
+HWND g_hListenWindow, hDlg, g_hDlgPass, hOldForegroundWindow;
+HWND_ITEM *g_pMirWnds; // a pretty simple linked list
+HMODULE hWTS, hDwmApi;
+DWORD g_dwMirandaPID;
+WORD g_wMask, g_wMaskAdv;
+bool g_bWindowHidden, g_fKeyPressed, g_fPassRequested, g_TrayIcon;
+char g_password[MAXPASSLEN + 1];
+HKL oldLangID, oldLayout;
+int protoCount;
+PROTOCOLDESCRIPTOR **proto;
+unsigned *oldStatus;
+TCHAR **oldStatusMsg;
+BYTE g_bOldSetting;
+int hLangpack;
+
+PWTSRegisterSessionNotification wtsRegisterSessionNotification ;
+PWTSUnRegisterSessionNotification wtsUnRegisterSessionNotification;
+PFNDwmIsCompositionEnabled dwmIsCompositionEnabled;
+
+void LanguageChanged(HWND hDlg);
+
+static PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_NAME,
+ __VERSION_DWORD,
+ __DESC,
+ __AUTHORS,
+ __EMAIL,
+ __COPYRIGHTS,
+ __FL,
+ UNICODE_AWARE,
+ //4fac353d-0a36-44a4-9064-6759c53ae782
+ {0x4fac353d, 0x0a36, 0x44a4, { 0x90, 0x64, 0x67, 0x59, 0xc5, 0x3a, 0xe7, 0x82 }}
+};
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ g_hInstance = hinstDLL;
+ return(true);
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+
+static const MUUID interfaces[] = { MIID_BOSSKEY, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+static BOOL IsAeroMode()
+{
+ BOOL result;
+ return dwmIsCompositionEnabled && (dwmIsCompositionEnabled(&result) == S_OK) && result;
+}
+
+INT_PTR CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ static DWORD dwOldIcon = 0;
+ HICON hIcon = 0;
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ g_hDlgPass = hDlg;
+ hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DLGPASSWD));
+ dwOldIcon = SetClassLongPtr(hDlg, GCLP_HICON, (LONG)hIcon); // set alt+tab icon
+ SendDlgItemMessage(hDlg,IDC_EDIT1,EM_LIMITTEXT,MAXPASSLEN,0);
+
+ if (IsAeroMode())
+ {
+ SetWindowLongPtr(hDlg, GWL_STYLE, GetWindowLongPtr(hDlg, GWL_STYLE) | WS_DLGFRAME | WS_SYSMENU);
+
+ RECT rect;
+ GetClientRect(hDlg, &rect);
+ SetWindowPos(hDlg, 0, 0, 0, rect.right, rect.bottom +
+ GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME),
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER);
+ }
+ SendMessage(GetDlgItem(hDlg, IDC_HEADERBAR), WM_SETICON, 0, (LPARAM)hIcon);
+ SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), _T("Miranda IM is locked.\nEnter password to unlock it."));
+
+ TranslateDialogDefault(hDlg);
+ oldLangID = 0;
+ SetTimer(hDlg,1,200,NULL);
+
+ oldLayout = GetKeyboardLayout(0);
+ if (MAKELCID((WORD)oldLayout & 0xffffffff, SORT_DEFAULT) != (LCID)0x00000409)
+ ActivateKeyboardLayout((HKL)0x00000409, 0);
+ LanguageChanged(hDlg);
+ return TRUE;
+ }
+
+ case WM_CTLCOLORSTATIC:
+ {
+ if (GetWindowLongPtr((HWND)lParam, GWLP_ID) == IDC_LANG)
+ {
+ SetTextColor((HDC)wParam, GetSysColor(COLOR_HIGHLIGHTTEXT));
+ SetBkMode((HDC)wParam, TRANSPARENT);
+ return (INT_PTR)GetSysColorBrush(COLOR_HIGHLIGHT);
+ }
+ return FALSE;
+ }
+
+ case WM_COMMAND:
+ {
+ UINT uid = LOWORD(wParam);
+ if(uid == IDOK){
+ char password[MAXPASSLEN + 1] = {0};
+ int passlen = GetDlgItemTextA(hDlg,IDC_EDIT1,password,MAXPASSLEN+1);
+
+ if (passlen == 0)
+ {
+ SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Miranda IM is locked.\nEnter password to unlock it."));
+ SendMessage(GetDlgItem(hDlg, IDC_HEADERBAR), WM_NCPAINT, 0, 0);
+ }
+ else if (lstrcmpA(password, g_password))
+ {
+ SetWindowText(GetDlgItem(hDlg, IDC_HEADERBAR), TranslateT("Password is not correct!\nPlease, enter correct password."));
+ SendMessage(GetDlgItem(hDlg, IDC_HEADERBAR), WM_NCPAINT, 0, 0);
+ SetDlgItemTextA(hDlg, IDC_EDIT1, "");
+ }
+ else EndDialog(hDlg,IDOK);
+
+ }else if (uid == IDCANCEL)
+ EndDialog(hDlg,IDCANCEL);
+ }
+
+ case WM_TIMER:
+ {
+ LanguageChanged(hDlg);
+ return FALSE;
+ }
+ case WM_DESTROY:
+ {
+ KillTimer(hDlg, 1);
+ if (GetKeyboardLayout(0) != oldLayout)
+ ActivateKeyboardLayout(oldLayout, 0);
+ SetClassLongPtr(hDlg, GCLP_HICON, (long)dwOldIcon);
+ DestroyIcon(hIcon);
+ return FALSE;
+ }
+
+ }return FALSE;
+}
+
+static void LanguageChanged(HWND hDlg)
+{
+ HKL LangID = GetKeyboardLayout(0);
+ char Lang[3] = {0};
+ if (LangID != oldLangID)
+ {
+ oldLangID = LangID;
+ GetLocaleInfoA(MAKELCID(((WORD)LangID & 0xffffffff), SORT_DEFAULT), LOCALE_SABBREVLANGNAME, Lang, 2);
+ Lang[0] = toupper(Lang[0]);
+ Lang[1] = tolower(Lang[1]);
+ SetDlgItemTextA(hDlg, IDC_LANG, Lang);
+ }
+}
+
+BOOL CALLBACK EnumWindowsProc(HWND hWnd,LPARAM lParam)
+{
+ DWORD dwWndPID;
+ GetWindowThreadProcessId(hWnd,&dwWndPID);
+
+ if ((g_dwMirandaPID == dwWndPID) && hWnd != g_hDlgPass /* && (GetWindowLongPtr(hWnd,GWLP_HWNDPARENT) == NULL)*/ && (IsWindowVisible(hWnd)))
+ {
+ char szTemp[32];
+ GetClassNameA(hWnd,szTemp,32);
+
+ if (lstrcmpA(szTemp,"MirandaThumbsWnd") == 0) // hide floating contacts
+ {
+ CallService("FloatingContacts/MainHideAllThumbs",0,0);
+ g_bOldSetting |= OLD_FLTCONT;
+ }
+ else
+ if (lstrcmpA(szTemp,"PopupWnd2") == 0 || lstrcmpA(szTemp,"YAPPWinClass") == 0) // destroy opened popups
+ SendMessage(hWnd, UM_DESTROYPOPUP,0,0);
+// else
+// if (lstrcmpA(szTemp,"#32770") == 0)
+// SendMessage(hWnd, WM_CLOSE,0,0);
+ else
+ {
+ HWND_ITEM *node = new HWND_ITEM;
+ node->hWnd = hWnd;
+ // add to list
+ node->next = g_pMirWnds;
+ g_pMirWnds = node;
+ ShowWindow(hWnd,SW_HIDE);
+ }
+ }
+ return(true);
+}
+
+TCHAR* GetDefStatusMsg(unsigned uStatus, const char* szProto)
+{
+ TCHAR *ret = (TCHAR *)CallService ( MS_AWAYMSG_GETSTATUSMSGT, (WPARAM)uStatus, (LPARAM)szProto );
+ if ( (int)ret == CALLSERVICE_NOTFOUND )
+ {
+ char* tmp = ( char* )CallService( MS_AWAYMSG_GETSTATUSMSG, (WPARAM)uStatus, (LPARAM)szProto );
+ ret = mir_a2t( tmp );
+ mir_free( tmp );
+ }
+ return ret;
+}
+
+void SetStatus(const char* szProto, unsigned status, TCHAR *tszAwayMsg)
+{
+ if ( tszAwayMsg && CallProtoService( szProto, PS_GETCAPS, PFLAGNUM_1, 0 ) & PF1_MODEMSGSEND )
+ {
+ if ( CallProtoService( szProto, PS_SETAWAYMSGT, status, (LPARAM) tszAwayMsg ) == CALLSERVICE_NOTFOUND )
+ {
+ char *szAwayMsg = mir_t2a(tszAwayMsg);
+ CallProtoService( szProto, PS_SETAWAYMSG, status, (LPARAM) szAwayMsg );
+ mir_free(szAwayMsg);
+ }
+ }
+ CallProtoService( szProto, PS_SETSTATUS, status, 0 );
+}
+
+static int ChangeAllProtoStatuses(unsigned statusMode, TCHAR *msg)
+{
+ for (int i=0; i < protoCount; i++)
+ {
+ unsigned status = CallProtoService(proto[i]->szName,PS_GETSTATUS,0,0);
+ if (
+ (proto[i]->type == PROTOTYPE_PROTOCOL)
+ &&
+ (g_wMask & OPT_ONLINEONLY) ? // check "Change only if current status is Online" option
+ ((status == ID_STATUS_ONLINE) || (status == ID_STATUS_FREECHAT)) // process only "online" and "free for chat"
+ :
+ ((status > ID_STATUS_OFFLINE) && (status < ID_STATUS_IDLE) && (status != ID_STATUS_INVISIBLE)) // process all existing statuses except for "invisible" & "offline"
+ )
+ {
+ if (g_wMask & OPT_SETONLINEBACK){ // need to save old statuses & status messages
+ oldStatus[i] = status;
+
+ char svc[256];
+ mir_snprintf(svc, 256, "%s%s", proto[i]->szName, PS_GETMYAWAYMSG);
+ if (ServiceExists (svc))
+ {
+ if (ServiceExists (MS_AWAYMSG_GETSTATUSMSGT)) // if core can support unicode status message
+ oldStatusMsg[i] = (TCHAR *)CallService (svc, 0, SGMA_TCHAR);
+ else
+ {
+ char *tmp = (char *)CallService (svc, 0, 0);
+ oldStatusMsg[i] = mir_a2t(tmp);
+ mir_free(tmp);
+ }
+ }
+ else
+ oldStatusMsg[i] = GetDefStatusMsg(status, proto[i]->szName);
+ }
+ SetStatus(proto[i]->szName, statusMode, msg);
+ }
+ }
+ return 0;
+}
+
+static int BackAllProtoStatuses(void)
+{
+ for (int i=0; i < protoCount; i++)
+ {
+ if ( oldStatus[i] )
+ {
+ SetStatus(proto[i]->szName, oldStatus[i], oldStatusMsg[i]);
+ if (oldStatusMsg[i])
+ {
+ mir_free(oldStatusMsg[i]);
+ oldStatusMsg[i] = 0;
+ }
+ oldStatus[i] = 0;
+ }
+ }
+ return 0;
+}
+
+static void CreateTrayIcon(bool create)
+{
+ NOTIFYICONDATA nim;
+ DBVARIANT dbVar;
+ if (!DBGetContactSettingTString(NULL,MOD_NAME,"ToolTipText",&dbVar))
+ {
+ mir_sntprintf(nim.szTip, 64, _T("%s"), dbVar.ptszVal);
+ DBFreeVariant(&dbVar);
+ }
+ else
+ lstrcpy(nim.szTip, _T("Miranda IM"));
+
+ nim.cbSize = sizeof(nim);
+ nim.hWnd = g_hListenWindow;
+ nim.uID = 100;
+ nim.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+ nim.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"hidemim" );
+ nim.uCallbackMessage = WM_USER + 24;
+ Shell_NotifyIcon(create ? NIM_ADD : NIM_DELETE, &nim);
+ g_TrayIcon = create;
+}
+
+static void RestoreOldSettings(void)
+{
+ if (g_bOldSetting & OLD_POPUP)
+ CallService(MS_POPUP_QUERY, PUQS_ENABLEPOPUPS, 0);
+
+ if (g_bOldSetting & OLD_SOUND)
+ DBWriteContactSettingByte(NULL,"Skin","UseSound", 1);
+
+ if (g_bOldSetting & OLD_FLTCONT) // show Floating contacts if needed
+ {
+ if(ServiceExists("FloatingContacts/MainHideAllThumbs"))
+ CallService("FloatingContacts/MainHideAllThumbs",0,0);
+ else
+ DBWriteContactSettingByte(NULL,"FloatingContacts","HideAll", 0);
+ }
+ g_bOldSetting = 0;
+}
+
+LRESULT CALLBACK ListenWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_WTSSESSION_CHANGE:
+ {
+ if (wParam == WTS_SESSION_LOCK && g_wMaskAdv & OPT_HIDEIFLOCK && !g_bWindowHidden) // Windows locked
+ PostMessage(hWnd,WM_USER + 40, 0, 0);
+ return 0;
+ }break;
+
+ case WM_USER + 24:
+ {
+ if (lParam == WM_LBUTTONDBLCLK)
+ PostMessage(hWnd,WM_USER + 52, 0, 0);
+ return 0;
+ }break;
+
+ case WM_USER+40: // hide
+ {
+ if (g_bWindowHidden || g_fOptionsOpen) // already hidden or in options, no hiding
+ break;
+
+ if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER))
+ BossKeyEvent(g_bWindowHidden, 0);
+
+ DWORD dwWndPID; // remember foreground window
+ HWND hForegroundWnd = GetForegroundWindow();
+ GetWindowThreadProcessId(hForegroundWnd,&dwWndPID);
+ if (g_dwMirandaPID == dwWndPID)
+ hOldForegroundWindow = hForegroundWnd;
+
+ EnumWindows(EnumWindowsProc, 0);
+
+ if (g_wMask & OPT_CHANGESTATUS) // is this even needed?
+ {
+ BYTE bReqMode = DBGetContactSettingByte(NULL,MOD_NAME,"stattype",2);
+ unsigned uMode = (STATUS_ARR_TO_ID[bReqMode]);
+ DBVARIANT dbVar;
+ if (g_wMask & OPT_USEDEFMSG || DBGetContactSettingTString(NULL,MOD_NAME,"statmsg",&dbVar))
+ {
+ TCHAR *ptszDefMsg = GetDefStatusMsg(uMode, 0);
+ ChangeAllProtoStatuses(uMode, ptszDefMsg);
+ if(ptszDefMsg)
+ mir_free(ptszDefMsg);
+ }
+ else
+ {
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ {
+ FORMATINFO fi;
+ TCHAR *ptszParsed;
+
+ ZeroMemory(&fi, sizeof(fi));
+ fi.cbSize = sizeof(fi);
+ fi.flags = FIF_TCHAR;
+ fi.tszFormat = dbVar.ptszVal;
+ ptszParsed = (TCHAR*)CallService(MS_VARS_FORMATSTRING, (WPARAM)&fi, 0);
+ ChangeAllProtoStatuses(uMode, ptszParsed);
+ if (ptszParsed)
+ CallService(MS_VARS_FREEMEMORY, (WPARAM)ptszParsed, 0);
+ }else
+ ChangeAllProtoStatuses(uMode, dbVar.ptszVal);
+ DBFreeVariant(&dbVar);
+ }
+ }
+
+ pcli->pfnTrayIconDestroy (pcli->hwndContactList);
+ pcli->pfnUninitTray();
+
+ if (g_wMask & OPT_TRAYICON)
+ CreateTrayIcon(true);
+
+ // disable popups
+ if (CallService(MS_POPUP_QUERY, PUQS_GETSTATUS, 0) == 1)
+ {
+ // save current
+ g_bOldSetting |= OLD_POPUP;
+ CallService(MS_POPUP_QUERY, PUQS_DISABLEPOPUPS, 0);
+ }
+
+ // disable sounds
+ if ((g_wMask & OPT_DISABLESNDS) && DBGetContactSettingByte(NULL,"Skin","UseSound",1))
+ {
+ // save current
+ g_bOldSetting |= OLD_SOUND;
+ DBWriteContactSettingByte(NULL,"Skin","UseSound",0);
+ }
+
+ g_bWindowHidden = true;
+
+ g_bOldSetting |= OLD_WASHIDDEN;
+ DBWriteContactSettingByte(NULL, MOD_NAME, "OldSetting", g_bOldSetting);
+ return(0);
+ } break;
+ case WM_USER+52: // back
+ {
+ if (!g_bWindowHidden || g_fPassRequested)
+ break;
+
+ if (g_wMask & OPT_REQPASS){ //password request
+ DBVARIANT dbVar = {0};
+ if (!DBGetContactSettingString(NULL,MOD_NAME,"password",&dbVar))
+ {
+ g_fPassRequested = true;
+
+ strncpy(g_password, dbVar.pszVal, MAXPASSLEN);
+ DBFreeVariant(&dbVar);
+ CallService( MS_DB_CRYPT_DECODESTRING, MAXPASSLEN+1, ( LPARAM )g_password );
+
+ int res = DialogBox(g_hInstance,(MAKEINTRESOURCE(IDD_PASSDIALOGNEW)),GetForegroundWindow(),(DLGPROC)DlgStdInProc);
+
+ g_fPassRequested = false;
+ if(res != IDOK) return 0;
+ }
+ }
+
+ if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER))
+ BossKeyEvent(g_bWindowHidden, 0);
+
+ if (g_wMask & OPT_CHANGESTATUS && g_wMask & OPT_SETONLINEBACK) // set back to some status
+ {
+ BackAllProtoStatuses();
+ }
+
+ HWND_ITEM *pCurWnd = g_pMirWnds;
+ while (pCurWnd != NULL)
+ {
+ HWND_ITEM *pNextWnd = pCurWnd->next;
+ char szTemp[32];
+ GetClassNameA(pCurWnd->hWnd,szTemp,32);
+
+ if (IsWindow(pCurWnd->hWnd) && lstrcmpA(szTemp,"SysShadow") != 0) // precaution
+ {
+ ShowWindow(pCurWnd->hWnd, SW_SHOW);
+ }
+
+ delete pCurWnd; // bye-bye
+ pCurWnd = pNextWnd; // traverse to next item
+ }
+ g_pMirWnds = NULL;
+
+ if (hOldForegroundWindow)
+ {
+ SetForegroundWindow(hOldForegroundWindow);
+ hOldForegroundWindow = NULL;
+ }
+
+ RestoreOldSettings();
+
+ if (g_TrayIcon) CreateTrayIcon(false);
+
+ pcli->pfnInitTray();
+ pcli->pfnTrayIconInit(pcli->hwndContactList); //this restores the icons without memory leaks :)
+
+ // force a redraw
+ // should prevent drawing problems
+ InvalidateRect(pcli->hwndContactList,NULL,true);
+ UpdateWindow(pcli->hwndContactList);
+
+ PostMessage(hWnd, WM_MOUSEMOVE, 0, (LPARAM)MAKELONG(2, 2)); // reset core's IDLE
+ g_bWindowHidden = false;
+
+ DBWriteContactSettingByte(NULL, MOD_NAME, "OldSetting", 0);
+ return(0);
+ } break;
+ default:break;
+ }
+ return(DefWindowProc(hWnd,uMsg,wParam,lParam));
+}
+
+static int MsgWinOpening(WPARAM wParam, LPARAM lParam) // hiding new message windows
+{
+ if (g_bWindowHidden)
+ EnumWindows(EnumWindowsProc,0);
+ return 0;
+}
+
+VOID CALLBACK WinEventProc(HWINEVENTHOOK g_hWinHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
+{
+ if (g_bWindowHidden && idObject == OBJID_WINDOW && (event == EVENT_OBJECT_CREATE || event == EVENT_OBJECT_SHOW) && (IsWindowVisible(hwnd)))
+ {
+ if(hwnd == pcli->hwndContactList)
+ ShowWindow(hwnd,SW_HIDE);
+ else
+ EnumWindows(EnumWindowsProc,0);
+ }
+}
+
+INT_PTR BossKeyHideMiranda(WPARAM wParam, LPARAM lParam) // for service :)
+{
+ PostMessage(g_hListenWindow, WM_USER + ((g_bWindowHidden) ? (52) : (40)), 0, 0);
+ return 0;
+}
+
+static TCHAR *HokeyVkToName(WORD vkKey)
+{
+ static TCHAR buf[32] = {0};
+ DWORD code = MapVirtualKey(vkKey, 0) << 16;
+
+ switch (vkKey)
+ {
+ case 0:
+ case VK_CONTROL:
+ case VK_SHIFT:
+ case VK_MENU:
+ case VK_LWIN:
+ case VK_RWIN:
+ case VK_PAUSE:
+ case VK_CANCEL:
+ case VK_CAPITAL:
+ return _T("");
+
+ case VK_DIVIDE:
+ case VK_INSERT:
+ case VK_HOME:
+ case VK_PRIOR:
+ case VK_DELETE:
+ case VK_END:
+ case VK_NEXT:
+ case VK_LEFT:
+ case VK_RIGHT:
+ case VK_UP:
+ case VK_DOWN:
+ case VK_NUMLOCK:
+ code |= (1UL << 24);
+ }
+
+ GetKeyNameText(code, buf, SIZEOF(buf));
+ return buf;
+}
+
+static TCHAR *GetBossKeyText(void)
+{
+ WORD wHotKey = DBGetContactSettingWord(NULL,"SkinHotKeys","Hide/Show Miranda",HOTKEYCODE(HOTKEYF_CONTROL, VK_F12));
+
+ BYTE key = LOBYTE(wHotKey);
+ BYTE shift = HIBYTE(wHotKey);
+ static TCHAR buf[128] = {0};
+
+ mir_sntprintf(buf, SIZEOF(buf), _T("%s%s%s%s%s"),
+ (shift & HOTKEYF_CONTROL) ? _T("Ctrl + ") : _T(""),
+ (shift & HOTKEYF_SHIFT) ? _T("Shift + ") : _T(""),
+ (shift & HOTKEYF_ALT) ? _T("Alt + ") : _T(""),
+ (shift & HOTKEYF_EXT) ? _T("Win + ") : _T(""),
+ HokeyVkToName(key));
+
+ return buf;
+}
+
+static int IcoLibInit (void) // Icolib support
+{
+ SKINICONDESC sid = {0};
+ TCHAR tszFile[MAX_PATH];
+ GetModuleFileName(g_hInstance, tszFile, MAX_PATH);
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.flags = SIDF_ALL_TCHAR;
+ sid.ptszDefaultFile = tszFile;
+ sid.cx = sid.cy = 16;
+ sid.ptszSection = _T("BossKey");
+
+ sid.pszName = "hidemim";
+ sid.ptszDescription = _T("Hide Miranda IM");
+ sid.iDefaultIndex = -IDI_DLGPASSWD;
+ g_hIcon = Skin_AddIcon(&sid);
+
+ return 0;
+}
+
+static int GenMenuInit(WPARAM wParam, LPARAM lParam) // Modify menu item text before to show the main menu
+{
+ if (g_hMenuItem)
+ {
+ CLISTMENUITEM mi = {0};
+ TCHAR buf[128] = {0};
+ mir_sntprintf(buf, SIZEOF(buf), _T("%s [%s]"), TranslateT("Hide"), GetBossKeyText());
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_FLAGS | CMIF_TCHAR | CMIM_NAME;
+ mi.ptszName = buf;
+
+ CallService(MS_CLIST_MODIFYMENUITEM,(WPARAM)g_hMenuItem,(LPARAM)&mi);
+ }
+ return 0;
+}
+
+void BossKeyMenuItemInit(void) // Add menu item
+{
+ CLISTMENUITEM mi = {0};
+
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIF_TCHAR;
+ mi.position = 2000100000;
+ mi.pszPopupName = 0;
+ mi.hIcon = ( HICON )CallService( MS_SKIN2_GETICON, 0, (LPARAM)"hidemim" );
+ mi.ptszName = _T("Hide");
+ mi.pszService = MS_BOSSKEY_HIDE;
+
+ g_hMenuItem = Menu_AddMainMenuItem(&mi);
+
+ g_hmGenMenuInit = HookEvent(ME_CLIST_PREBUILDMAINMENU, GenMenuInit);
+}
+
+void BossKeyMenuItemUnInit(void) // Remove menu item
+{
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)g_hMenuItem, 0);
+ g_hMenuItem = 0;
+ if(g_hmGenMenuInit)
+ UnhookEvent(g_hmGenMenuInit);
+ g_hmGenMenuInit = 0;
+}
+
+void RegisterCoreHotKeys (void)
+{
+ HOTKEYDESC hotkey = {0};
+ hotkey.cbSize = sizeof(HOTKEYDESC);
+ hotkey.pszName = "Hide/Show Miranda";
+ hotkey.pszDescription = LPGEN("Hide/Show Miranda");
+ hotkey.pszSection = "BossKey";
+ hotkey.pszService = MS_BOSSKEY_HIDE;
+ hotkey.DefHotKey = HOTKEYCODE(HOTKEYF_CONTROL, VK_F12);
+
+ Hotkey_Register(&hotkey);
+}
+
+static int ModernToolbarInit(WPARAM, LPARAM) // Modern toolbar support
+{
+ TTBButton button = {0};
+ button.cbSize = sizeof(button);
+ button.pszService = MS_BOSSKEY_HIDE;
+ button.pszTooltipUp = button.pszTooltipDn = button.name = LPGEN("Hide Miranda IM");
+ button.dwFlags = TTBBF_DISABLED|TTBBF_SHOWTOOLTIP;
+ button.hIconHandleUp = button.hIconHandleDn = g_hIcon;
+ TopToolbar_AddButton(&button);
+ return 0;
+}
+
+// Tabsrmm toolbar support
+static int TabsrmmButtonPressed(WPARAM wParam, LPARAM lParam)
+{
+ CustomButtonClickData *cbcd=(CustomButtonClickData *)lParam;
+
+ if (!strcmp(cbcd->pszModule, MOD_NAME))
+ BossKeyHideMiranda(0, 0);
+
+ return 0;
+}
+
+static int TabsrmmButtonsInit(WPARAM wParam, LPARAM lParam)
+{
+ BBButton bbd = {0};
+
+ bbd.cbSize = sizeof(BBButton);
+ bbd.pszModuleName = MOD_NAME;
+ bbd.dwDefPos = 5000;
+ bbd.ptszTooltip = _T("Hide Miranda IM");
+ bbd.bbbFlags = BBBF_ISRSIDEBUTTON | BBBF_CANBEHIDDEN;
+ bbd.hIcon = g_hIcon;
+ CallService (MS_BB_ADDBUTTON, 0, (LPARAM)&bbd);
+
+ return 0;
+}
+
+static TCHAR *VariablesBossKey(ARGUMENTSINFO *ai) {
+ if (ai->cbSize < sizeof(ARGUMENTSINFO)) return NULL;
+ if (ai->argc != 1) return NULL;
+
+ ai->flags |= AIF_DONTPARSE;
+
+ return GetBossKeyText();
+}
+
+static int EnumProtos(WPARAM wParam, LPARAM lParam)
+{
+ CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&protoCount,(LPARAM)&proto);
+
+ delete[] oldStatus;
+ delete[] oldStatusMsg;
+
+ oldStatus = new unsigned[protoCount];
+ oldStatusMsg = new TCHAR* [protoCount];
+ for (int i = 0; i < protoCount; i++)
+ {
+ oldStatus[i] = 0;
+ oldStatusMsg[i] = 0;
+ }
+ return 0;
+}
+
+int MirandaLoaded(WPARAM wParam,LPARAM lParam)
+{
+ g_wMask = DBGetContactSettingWord(NULL,MOD_NAME,"optsmask",DEFAULTSETTING);
+
+ RegisterCoreHotKeys();
+
+ g_hWinHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_SHOW,
+ NULL, WinEventProc, GetCurrentProcessId(), 0, 0);
+
+ HookEvent(ME_OPT_INITIALISE,OptsDlgInit);
+ HookEvent(ME_MSG_WINDOWEVENT,MsgWinOpening);
+ HookEvent(ME_PROTO_ACCLISTCHANGED, EnumProtos);
+ HookEvent(ME_MSG_TOOLBARLOADED, TabsrmmButtonsInit);
+ HookEvent(ME_MSG_BUTTONPRESSED, TabsrmmButtonPressed);
+
+ pcli = (CLIST_INTERFACE *)CallService(MS_CLIST_RETRIEVE_INTERFACE, 0, (LPARAM)g_hInstance);
+#if defined _DEBUG
+ if (pcli == 0)
+ {
+ MessageBox(NULL,_T("Can't get CLIST_INTERFACE!"),_T("BossKey+"),MB_ICONERROR);
+ return 1;
+ }else
+#endif
+ GetWindowThreadProcessId(pcli->hwndContactList,&g_dwMirandaPID);
+
+ // let's create our secret window
+ // this is a cheap, cheap hack...
+ // needed because of the hook, that gives problems
+ // if the calls aren't made from this context, they won't work
+ // using the window is a workaround to make this process do its work :)
+ // see notes
+ WNDCLASS winclass = {0};
+
+ winclass.lpfnWndProc = ListenWndProc;
+ winclass.hInstance = g_hInstance;
+ //winclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
+ //winclass.hCursor = LoadCursor(NULL,IDC_ARROW);
+ winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+ winclass.lpszClassName = BOSSKEY_LISTEN_INFO;
+
+ if (RegisterClass(&winclass))
+ {
+ hWTS = LoadLibrary(_T("wtsapi32.dll"));
+
+ g_hListenWindow = CreateWindow(BOSSKEY_LISTEN_INFO,BOSSKEY_LISTEN_INFO,WS_POPUP,0,0,5,5,pcli->hwndContactList,NULL,g_hInstance,NULL);
+
+ if (hWTS)
+ {
+ wtsRegisterSessionNotification = (PWTSRegisterSessionNotification)GetProcAddress(hWTS, "WTSRegisterSessionNotification");
+ if (wtsRegisterSessionNotification)
+ {
+ wtsUnRegisterSessionNotification = (PWTSUnRegisterSessionNotification)GetProcAddress(hWTS, "WTSUnRegisterSessionNotification");
+ wtsRegisterSessionNotification(g_hListenWindow, 0);
+ }
+ }
+ }
+
+ if (IsWinVerVistaPlus())
+ {
+ hDwmApi = LoadLibrary(_T("dwmapi.dll"));
+ if (hDwmApi)
+ {
+ dwmIsCompositionEnabled = (PFNDwmIsCompositionEnabled)GetProcAddress(hDwmApi,"DwmIsCompositionEnabled");
+ }
+ }
+ if (g_wMaskAdv & OPT_MENUITEM)
+ BossKeyMenuItemInit();
+
+// Updater support
+ if(ServiceExists(MS_UPDATE_REGISTERFL))
+ CallService(MS_UPDATE_REGISTERFL, (WPARAM)__PLUGIN_ID, (LPARAM)&pluginInfo);
+
+ if (ServiceExists(MS_TRIGGER_REGISTERTRIGGER))
+ RegisterTrigger();
+
+// Register token for variables plugin
+ if (ServiceExists(MS_VARS_REGISTERTOKEN))
+ {
+ TOKENREGISTER tr = {0};
+ tr.cbSize = sizeof(TOKENREGISTER);
+ tr.memType = TR_MEM_OWNER;
+ tr.flags = TRF_FIELD | TRF_TCHAR | TRF_PARSEFUNC;
+
+ tr.tszTokenString = _T("bosskeyname");
+ tr.parseFunctionT = VariablesBossKey;
+ tr.szHelpText = LPGEN("BossKey\tget the BossKey name");
+ CallService(MS_VARS_REGISTERTOKEN, 0, (LPARAM) &tr);
+ }
+
+ EnumProtos(0, 0);
+ InitIdleTimer();
+
+ if (g_bOldSetting && !(g_wMaskAdv & OPT_RESTORE)) // Restore settings if Miranda was crushed or killed in hidden mode and "Restore hiding on startup after failure" option is disabled
+ RestoreOldSettings();
+
+ if (g_wMaskAdv & OPT_HIDEONSTART ||
+ (g_wMaskAdv & OPT_RESTORE && g_bOldSetting))
+ BossKeyHideMiranda(0, 0);
+
+ return(0);
+}
+
+
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ mir_getLP(&pluginInfo);
+
+ g_wMaskAdv = DBGetContactSettingWord(NULL,MOD_NAME,"optsmaskadv",0);
+ g_bOldSetting = DBGetContactSettingByte(NULL, MOD_NAME, "OldSetting", 0);
+
+ if ((g_bOldSetting & OLD_POPUP) && !(g_wMaskAdv & OPT_RESTORE)) // Restore popup settings if Miranda was crushed or killed in hidden mode and "Restore hiding on startup after failure" option is disabled
+ {
+ if (DBGetContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 1) == 0)
+ DBWriteContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 1);
+ if (DBGetContactSettingByte(NULL, "YAPP", "Enabled", 1) == 0)
+ DBWriteContactSettingByte(NULL, "YAPP", "Enabled", 1);
+ }
+ if (g_wMaskAdv & OPT_HIDEONSTART && DBGetContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 0)) // hack for disabling popup on startup if "Hide Miranda on startup" is enabled
+ {
+ g_bOldSetting |= OLD_POPUP;
+ DBWriteContactSettingByte(NULL, "PopUp", "ModuleIsEnabled", 0);
+ }
+
+ IcoLibInit();
+
+ g_hHideService = CreateServiceFunction(MS_BOSSKEY_HIDE,BossKeyHideMiranda); // Create service
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,MirandaLoaded);
+ HookEvent(ME_TTB_MODULELOADED, ModernToolbarInit);
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ UninitIdleTimer();
+
+ if(g_hmGenMenuInit)
+ UnhookEvent(g_hmGenMenuInit);
+
+ if (g_hWinHook != 0)
+ UnhookWinEvent(g_hWinHook);
+
+ DestroyServiceFunction(g_hHideService);
+ if (g_hIsHiddenService)
+ DestroyServiceFunction(g_hIsHiddenService);
+
+ if (g_hListenWindow)
+ {
+ if (wtsUnRegisterSessionNotification)
+ wtsUnRegisterSessionNotification(g_hListenWindow);
+ DestroyWindow(g_hListenWindow);
+ }
+
+ if (hWTS)
+ FreeLibrary(hWTS);
+ if (hDwmApi)
+ FreeLibrary(hDwmApi);
+
+ // free all sessions
+ HWND_ITEM *pTemp = g_pMirWnds;
+ while (pTemp != NULL)
+ {
+ HWND_ITEM *pNext = pTemp->next;
+ delete pTemp;
+ pTemp = pNext;
+ }
+ g_pMirWnds = NULL; // safety
+
+ // free memory
+ delete[] oldStatus;
+ delete[] oldStatusMsg;
+
+ return(0);
+}