#include "StdAfx.h" #include "sametime.h" #include "version.h" // plugin stuff PLUGININFOEX pluginInfo = { sizeof(PLUGININFOEX), __PLUGIN_NAME, PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM), __DESCRIPTION, __AUTHOR, __AUTHOREMAIL, __COPYRIGHT, __AUTHORWEB, UNICODE_AWARE, { 0xf1b0ba1b, 0xc91, 0x4313, { 0x85, 0xeb, 0x22, 0x50, 0x69, 0xd4, 0x4d, 0x1 } } // {F1B0BA1B-0C91-4313-85EB-225069D44D01} }; HINSTANCE hInst; LIST g_Instances(1, PtrKeySortT); int hLangpack; // sametime.cpp: Defines the entry point for the DLL application. extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { hInst = hinstDLL; return TRUE; } extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) { return &pluginInfo; } extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_PROTOCOL, MIID_LAST}; // protocol related services /** Copy the name of the protocole into lParam * @param wParam : max size of the name * @param lParam : reference to a char *, which will hold the name */ INT_PTR CSametimeProto::GetName(WPARAM wParam, LPARAM lParam) { strncpy((char*)lParam, m_szModuleName, wParam); return 0; } /* * Returns the current status */ INT_PTR CSametimeProto::GetStatus(WPARAM wParam, LPARAM lParam) { return m_iStatus; } /** Loads the icon corresponding to the status * Called by the CList when the status changes. * @param wParam : one of the following values : \n PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE * @return an \c HICON in which the icon has been loaded. */ INT_PTR CSametimeProto::SametimeLoadIcon(WPARAM wParam, LPARAM lParam) { UINT id; switch (wParam & 0xFFFF) { case PLI_PROTOCOL: id = IDI_ICON_PROTO; break; default: return NULL; } return (INT_PTR) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON), GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0); } //icolib stuff static IconItem iconList[] = { { LPGEN("Protocol icon"), "protoicon", IDI_ICON_PROTO, 0 }, { LPGEN("Start conference"), "leaveconference", IDI_ICON_INVITE, 0 }, { LPGEN("Leave conference"), "startconference", IDI_ICON_LEAVE, 0 }, { LPGEN("Announce"), "announce", IDI_ICON_ANNOUNCE, 0 }, { LPGEN("Notification"), "notify", IDI_ICON_NOTIFY, 0 }, { LPGEN("Error"), "error", IDI_ICON_ERROR, 0 } }; void SametimeInitIcons(void) { Icon_Register(hInst, "Protocols/Sametime", iconList, SIZEOF(iconList), "SAMETIME"); } HANDLE GetIconHandle(int iconId) { for (int i = 0; i < SIZEOF(iconList); i++) if (iconList[i].defIconID == iconId) return iconList[i].hIcolib; return NULL; } HICON LoadIconEx(const char* name, BOOL big) { char szSettingName[100]; mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", "SAMETIME", name); return Skin_GetIcon(szSettingName, big); } void ReleaseIconEx(const char* name, BOOL big) { char szSettingName[100]; mir_snprintf(szSettingName, sizeof(szSettingName), "%s_%s", "SAMETIME", name); Skin_ReleaseIcon(szSettingName, big); } // Copied from MSN plugin - sent acks need to be from different thread void __cdecl sttFakeAckInfoSuccessThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttFakeAckInfoSuccessThread() start")); Sleep(100); proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE)1, 0); proto->debugLog(_T("sttFakeAckInfoSuccessThread() end")); mir_free(tParam); } void __cdecl sttFakeAckMessageSuccessThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttFakeAckMessageSuccessThread() start")); Sleep(100); proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)tParam->lParam, 0); proto->debugLog(_T("sttFakeAckMessageSuccessThread() end")); mir_free(tParam); } void __cdecl sttFakeAckMessageFailedThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttFakeAckMessageFailedThread() start")); Sleep(100); proto->ProtoBroadcastAck(tParam->hContact, ACKTYPE_MESSAGE, ACKRESULT_FAILED, NULL, tParam->lParam); ///TODO tParam->lParam: add error message proto->debugLog(_T("sttFakeAckMessageFailedThread() end")); mir_free(tParam); } void __cdecl sttRecvAwayThread(void *param) { TFakeAckParams* tParam = (TFakeAckParams*)param; CSametimeProto* proto = tParam->proto; proto->debugLog(_T("sttRecvAwayThread() start")); Sleep(100); proto->UserRecvAwayMessage(tParam->hContact); proto->debugLog(_T("sttRecvAwayThread() end")); free(tParam); } int CSametimeProto::OnWindowEvent(WPARAM, LPARAM lParam) { MessageWindowEventData* mwed = (MessageWindowEventData*)lParam; if (db_get_b(mwed->hContact, m_szModuleName, "ChatRoom", 0)) return 0; if (mwed && (mwed->uType == MSG_WINDOW_EVT_CLOSING || mwed->uType == MSG_WINDOW_EVT_CLOSE)) CloseIm(mwed->hContact); return 0; } int CSametimeProto::OnIdleChanged(WPARAM, LPARAM lParam) { if (!(lParam & IDF_PRIVACY)) { is_idle = lParam & IDF_ISIDLE ? true : false; SetIdle(is_idle); } return 0; } int CSametimeProto::OnModulesLoaded(WPARAM, LPARAM) { // register with chat module GCREGISTER gcr = { sizeof(gcr) }; gcr.pszModule = m_szModuleName; gcr.ptszDispName = m_tszUserName; gcr.iMaxText = MAX_MESSAGE_SIZE; CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr); return 0; } int CSametimeProto::OnPreShutdown(WPARAM, LPARAM) { if (m_iStatus != ID_STATUS_OFFLINE) LogOut(); return 0; } int CSametimeProto::OnSametimeContactDeleted(WPARAM hContact, LPARAM) { ContactDeleted(hContact); ChatDeleted(hContact); return 0; } void CSametimeProto::SetAllOffline() { debugLog(_T("SetAllOffline() start")); for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { if (db_get_b(hContact, m_szModuleName, "ChatRoom", 0)) { CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact, 0); continue; } db_set_w(hContact, m_szModuleName, "Status", ID_STATUS_OFFLINE); db_set_dw(hContact, m_szModuleName, "IdleTS", 0); } } void CSametimeProto::BroadcastNewStatus(int iNewStatus) { if (m_iStatus == iNewStatus) return; debugLog(_T("BroadcastNewStatus() m_iStatus=[%d], iNewStatus=[%d]"), m_iStatus, iNewStatus); previous_status = m_iStatus; m_iStatus = iNewStatus; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)previous_status, m_iStatus); } static CSametimeProto* sametime_proto_init(const char* pszProtoName, const TCHAR* tszUserName) { CSametimeProto* proto = new CSametimeProto(pszProtoName, tszUserName); g_Instances.insert(proto); return proto; } static int sametime_proto_uninit(PROTO_INTERFACE* ppro) { CSametimeProto* proto = (CSametimeProto*)ppro; g_Instances.remove(proto); delete proto; return 0; } extern "C" int __declspec(dllexport) Load(void) { PROTOCOLDESCRIPTOR pd = { sizeof(pd) }; pd.type = PROTOTYPE_PROTOCOL; pd.szName = "Sametime"; pd.fnInit = (pfnInitProto)sametime_proto_init; pd.fnUninit = (pfnUninitProto)sametime_proto_uninit; CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd); return 0; } extern "C" int __declspec(dllexport) Unload() { g_Instances.destroy(); return 0; }