INT_PTR CListTray_GetGlobalStatus(WPARAM, LPARAM) { g_szConnectingProto = NULL; int curstatus = 0; int connectingCount = 0; for (int i = 0; i < pcli->hClcProtoCount; i++) { ClcProtoStatus &p = pcli->clcProto[i]; if (!pcli->pfnGetProtocolVisibility(p.szProto)) continue; if (IsStatusConnecting(p.dwStatus)) { connectingCount++; if (connectingCount == 1) g_szConnectingProto = p.szProto; } else curstatus = GetStatusOrder(curstatus, p.dwStatus); } if (connectingCount == 0) g_bMultiConnectionMode = FALSE; else if (connectingCount > 1) g_bMultiConnectionMode = TRUE; else g_bMultiConnectionMode = FALSE; return curstatus ? curstatus : ID_STATUS_OFFLINE; }
int GetGoodAccNum(bool *bDiffers, bool *bConn) { PROTOACCOUNT **acc; int AccNum, i; Proto_EnumAccounts(&AccNum, &acc); if (bConn) *bConn = FALSE; WORD s = 0; BYTE d = 0; for (i = AccNum, AccNum = 0; i--;) { if (!acc[i]->bIsVirtual && acc[i]->bIsVisible && !acc[i]->bDynDisabled && acc[i]->ppro) { AccNum++; if (!d) { s = acc[i]->ppro->m_iStatus; d = 1; } else if (s != acc[i]->ppro->m_iStatus) d = 2; if (bConn) if (IsStatusConnecting(acc[i]->ppro->m_iStatus)) *bConn = TRUE; } } *bDiffers = d == 2; return AccNum; }
TCHAR* fnGetStatusModeDescription(int mode, int flags) { static TCHAR szMode[64]; TCHAR* descr; int noPrefixReqd = 0; switch (mode) { case ID_STATUS_OFFLINE: descr = LPGENT("Offline"); noPrefixReqd = 1; break; case ID_STATUS_CONNECTING: descr = LPGENT("Connecting"); noPrefixReqd = 1; break; case ID_STATUS_ONLINE: descr = LPGENT("Online"); noPrefixReqd = 1; break; case ID_STATUS_AWAY: descr = LPGENT("Away"); break; case ID_STATUS_DND: descr = LPGENT("Do not disturb"); break; case ID_STATUS_NA: descr = LPGENT("Not available"); break; case ID_STATUS_OCCUPIED: descr = LPGENT("Occupied"); break; case ID_STATUS_FREECHAT: descr = LPGENT("Free for chat"); break; case ID_STATUS_INVISIBLE: descr = LPGENT("Invisible"); break; case ID_STATUS_OUTTOLUNCH: descr = LPGENT("Out to lunch"); break; case ID_STATUS_ONTHEPHONE: descr = LPGENT("On the phone"); break; case ID_STATUS_IDLE: descr = LPGENT("Idle"); break; default: if (IsStatusConnecting(mode)) { const TCHAR* connFmt = LPGENT("Connecting (attempt %d)"); mir_sntprintf(szMode, (flags & GSMDF_UNTRANSLATED) ? connFmt : TranslateTS(connFmt), mode - ID_STATUS_CONNECTING + 1); return szMode; } return NULL; } return (flags & GSMDF_UNTRANSLATED) ? descr : TranslateTS(descr); }
void CVkProto::ExecuteRequest(AsyncHttpRequest *pReq) { CMStringA str; do { pReq->bNeedsRestart = false; pReq->szUrl = pReq->m_szUrl.GetBuffer(); if (!pReq->m_szParam.IsEmpty()) { if (pReq->requestType == REQUEST_GET) { str.Format("%s?%s", pReq->m_szUrl, pReq->m_szParam); pReq->szUrl = str.GetBuffer(); } else { pReq->pData = mir_strdup(pReq->m_szParam); pReq->dataLength = pReq->m_szParam.GetLength(); } } if (pReq->m_bApiReq) { pReq->flags |= NLHRF_PERSISTENT; pReq->nlc = m_hAPIConnection; } debugLogA("CVkProto::ExecuteRequest \n====\n%s\n====\n", pReq->szUrl); NETLIBHTTPREQUEST *reply = (NETLIBHTTPREQUEST*)CallService(MS_NETLIB_HTTPTRANSACTION, (WPARAM)m_hNetlibUser, (LPARAM)pReq); if (reply != NULL) { if (pReq->m_pFunc != NULL) (this->*(pReq->m_pFunc))(reply, pReq); // may be set pReq->bNeedsRestart if (pReq->m_bApiReq) m_hAPIConnection = reply->nlc; CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT, 0, (LPARAM)reply); } else if (pReq->bIsMainConn) { if (IsStatusConnecting(m_iStatus)) ConnectionFailed(LOGINERR_NONETWORK); else if (pReq->m_iRetry && !m_bTerminated) { pReq->bNeedsRestart = true; Sleep(1000); //Pause for fix err pReq->m_iRetry--; debugLogA("CVkProto::ExecuteRequest restarting (retry = %d)", MAX_RETRIES - pReq->m_iRetry); } else { debugLogA("CVkProto::ExecuteRequest ShutdownSession"); ShutdownSession(); } } debugLogA("CVkProto::ExecuteRequest pReq->bNeedsRestart = %d", (int)pReq->bNeedsRestart); if (!reply && pReq->m_bApiReq) m_hAPIConnection = NULL; } while (pReq->bNeedsRestart && !m_bTerminated); delete pReq; }
int CVkProto::SetStatus(int iNewStatus) { debugLogA("CVkProto::SetStatus iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d m_hWorkerThread = %d", iNewStatus, m_iStatus, m_iDesiredStatus, m_hWorkerThread == NULL ? 0 : 1); if (m_iDesiredStatus == iNewStatus || iNewStatus == ID_STATUS_IDLE) return 0; int oldStatus = m_iStatus; m_iDesiredStatus = iNewStatus; if (iNewStatus == ID_STATUS_OFFLINE) { if (IsOnline()) { SetServerStatus(ID_STATUS_OFFLINE); debugLogA("CVkProto::SetStatus ShutdownSession"); ShutdownSession(); } m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); debugLogA("CVkProto::SetStatus (1) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); } else if (m_hWorkerThread == NULL && !IsStatusConnecting(m_iStatus)) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); debugLogA("CVkProto::SetStatus (2) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); m_hWorkerThread = ForkThreadEx(&CVkProto::WorkerThread, 0, NULL); } else if (IsOnline()) { debugLogA("CVkProto::SetStatus (3) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); SetServerStatus(iNewStatus); } else { debugLogA("CVkProto::SetStatus (4) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); if (!IsStatusConnecting(m_iStatus)) m_iDesiredStatus = m_iStatus; debugLogA("CVkProto::SetStatus (5) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); } debugLogA("CVkProto::SetStatus (ret) iNewStatus = %d, m_iStatus = %d, m_iDesiredStatus = %d oldStatus = %d", iNewStatus, m_iStatus, m_iDesiredStatus, oldStatus); return 0; }
void CSkypeProto::OnLoginSuccess() { if (!IsStatusConnecting(m_iStatus)) return; m_bThreadsTerminated = false; ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_SUCCESS, NULL, 0); li.api.szToken = getStringA("TokenSecret"); li.endpoint.szServer = ((ptrA(getStringA("Server")) == NULL) ? mir_strdup(SKYPE_ENDPOINTS_HOST) : getStringA("Server")); SendRequest(new CreateEndpointRequest(li), &CSkypeProto::OnEndpointCreated); }
void CSkypeProto::OnSubscriptionsCreated(const NETLIBHTTPREQUEST *response) { if (!IsStatusConnecting(m_iStatus)) return; if (response == NULL) { debugLogA(__FUNCTION__ ": failed to create subscription"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } SendPresence(true); }
INT_PTR RemoveTempContacts(WPARAM, LPARAM lParam) { for (MCONTACT hContact = db_find_first(); hContact;) { MCONTACT hNext = db_find_next(hContact); ptrT szGroup(db_get_tsa(hContact, "CList", "Group")); if (db_get_b(hContact, "CList", "NotOnList", 0) || (szGroup != NULL && (_tcsstr(szGroup, _T("Not In List")) || _tcsstr(szGroup, TranslateT("Not In List"))))) { char *szProto = GetContactProto(hContact); if (szProto != NULL) { // Check if protocol uses server side lists DWORD caps = CallProtoService(szProto, PS_GETCAPS, PFLAGNUM_1, 0); if (caps & PF1_SERVERCLIST) { int status = CallProtoService(szProto, PS_GETSTATUS, 0, 0); if (status == ID_STATUS_OFFLINE || IsStatusConnecting(status)) // Set a flag so we remember to delete the contact when the protocol goes online the next time db_set_b(hContact, "CList", "Delete", 1); else CallService(MS_DB_CONTACT_DELETE, hContact, 0); } } } hContact = hNext; } int hGroup = 1; TCHAR *group_name; do { group_name = Clist_GroupGetName(hGroup, 0); if (group_name != NULL && _tcsstr(group_name, TranslateT("Not In List"))) { BYTE ConfirmDelete = db_get_b(NULL, "CList", "ConfirmDelete", SETTING_CONFIRMDELETE_DEFAULT); if (ConfirmDelete) db_set_b(NULL, "CList", "ConfirmDelete", 0); Clist_GroupDelete(hGroup); if (ConfirmDelete) db_set_b(NULL, "CList", "ConfirmDelete", ConfirmDelete); break; } hGroup++; } while (group_name); if (!lParam) MessageBox(NULL, TranslateT("Complete"), TranslateT(pluginName), MB_ICONINFORMATION); return 0; }
void CSkypeProto::OnCapabilitiesSended(const NETLIBHTTPREQUEST *response) { if (!IsStatusConnecting(m_iStatus)) return; if (response == NULL || response->pData == NULL) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } SendRequest(new SetStatusRequest(MirandaToSkypeStatus(m_iDesiredStatus), li), &CSkypeProto::OnStatusChanged); LIST<char> skypenames(1); for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { if (!isChatRoom(hContact)) skypenames.insert(getStringA(hContact, SKYPE_SETTINGS_ID)); } SendRequest(new CreateContactsSubscriptionRequest(skypenames, li)); FreeList(skypenames); skypenames.destroy(); m_hPollingEvent.Set(); SendRequest(new LoadChatsRequest(li), &CSkypeProto::OnLoadChats); SendRequest(new CreateTrouterRequest(), &CSkypeProto::OnCreateTrouter); PushRequest(new GetContactListRequest(li, NULL), &CSkypeProto::LoadContactList); PushRequest(new GetAvatarRequest(ptrA(getStringA("AvatarUrl"))), &CSkypeProto::OnReceiveAvatar, NULL); if (getBool("AutoSync", true)) PushRequest(new SyncHistoryFirstRequest(100, li), &CSkypeProto::OnSyncHistory); JSONNode root = JSONNode::parse(response->pData); if (root) setString("SelfEndpointName", UrlToSkypename(root["selfLink"].as_string().c_str())); PushRequest(new GetProfileRequest(li), &CSkypeProto::LoadProfile); }
int cliTrayCalcChanged(const char *szChangedProto, int, int) { if (!szChangedProto) return -1; if (!pcli->trayIconCount) return -1; if (!pcli->pfnGetProtocolVisibility(szChangedProto)) return -1; bool bDiffers, bConn; GetGoodAccNum(&bDiffers, &bConn); // if the icon number to be changed, reinitialize module from scratch BYTE Mode = db_get_b(NULL, "CList", (!bDiffers) ? "tiModeS" : "tiModeV", TRAY_ICON_MODE_GLOBAL); if (Mode != OldMode) { OldMode = Mode; pcli->pfnTrayIconIconsChanged(); } HICON hIcon = NULL; int i = 0, iStatus; char *szProto; switch (Mode) { case TRAY_ICON_MODE_GLOBAL: hIcon = pcli->pfnGetIconFromStatusMode(NULL, NULL, CListTray_GetGlobalStatus(0, 0)); pcli->pfnTrayIconMakeTooltip(NULL, NULL); break; case TRAY_ICON_MODE_ACC: // В этом режиме показывается иконка совершенно определённого аккаунта, и не всегда это szChangedProto. szProto = db_get_sa(NULL, "CList", bDiffers ? "tiAccV" : "tiAccS"); if (szProto == NULL) break; iStatus = CallProtoService(szProto, PS_GETSTATUS, 0, 0); if (g_StatusBarData.bConnectingIcon && IsStatusConnecting(iStatus)) hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szProto, 0); else hIcon = pcli->pfnGetIconFromStatusMode(NULL, szProto, CallProtoService(szProto, PS_GETSTATUS, 0, 0)); pcli->pfnTrayIconMakeTooltip(NULL, szProto); break; case TRAY_ICON_MODE_CYCLE: iStatus = CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0); if (g_StatusBarData.bConnectingIcon && IsStatusConnecting(iStatus)) hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto, 0); else if (!bConn) hIcon = pcli->pfnGetIconFromStatusMode(NULL, szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0)); pcli->pfnTrayIconMakeTooltip(NULL, NULL); break; case TRAY_ICON_MODE_ALL: // Какой индекс у аккаунта, который будем апдейтить? for (; i < pcli->trayIconCount; i++) if (!mir_strcmp(pcli->trayIcon[i].szProto, szChangedProto)) break; iStatus = CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0); if (g_StatusBarData.bConnectingIcon && IsStatusConnecting(iStatus)) hIcon = (HICON)CLUI_GetConnectingIconService((WPARAM)szChangedProto, 0); else hIcon = pcli->pfnGetIconFromStatusMode(NULL, szChangedProto, CallProtoService(szChangedProto, PS_GETSTATUS, 0, 0)); pcli->pfnTrayIconMakeTooltip(NULL, pcli->trayIcon[i].szProto); break; } trayIconInfo_t &p = pcli->trayIcon[i]; DestroyIcon(p.hBaseIcon); p.hBaseIcon = hIcon; replaceStrT(p.ptszToolTip, pcli->szTip); NOTIFYICONDATA nid = { sizeof(NOTIFYICONDATA) }; nid.hWnd = pcli->hwndContactList; nid.uID = p.id; nid.hIcon = p.hBaseIcon; nid.uFlags = NIF_ICON | NIF_TIP; // if Tipper is missing or turned off for tray, use system tooltips if (!ServiceExists("mToolTip/ShowTip") || !db_get_b(NULL, "Tipper", "TrayTip", 1)) mir_tstrncpy(nid.szTip, pcli->szTip, _countof(nid.szTip)); Shell_NotifyIcon(NIM_MODIFY, &nid); return -1; }
int WhatsAppProto::SetStatus(int new_status) { if (m_iDesiredStatus == new_status) return 0; int oldStatus = m_iStatus; debugLogA("===== Beginning SetStatus process"); // Routing statuses not supported by WhatsApp switch (new_status) { case ID_STATUS_INVISIBLE: case ID_STATUS_OFFLINE: m_iDesiredStatus = new_status; break; case ID_STATUS_IDLE: default: m_iDesiredStatus = ID_STATUS_INVISIBLE; if (getByte(WHATSAPP_KEY_MAP_STATUSES, DEFAULT_MAP_STATUSES)) break; case ID_STATUS_ONLINE: case ID_STATUS_FREECHAT: m_iDesiredStatus = ID_STATUS_ONLINE; break; } if (m_iDesiredStatus == ID_STATUS_OFFLINE) { if (m_pSocket != NULL) { SetEvent(update_loop_lock_); m_pSocket->forceShutdown(); debugLogA("Forced shutdown"); } m_iStatus = m_iDesiredStatus = ID_STATUS_OFFLINE; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); } else if (m_pSocket == NULL && !IsStatusConnecting(m_iStatus)) { m_iStatus = ID_STATUS_CONNECTING; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); ResetEvent(update_loop_lock_); ForkThread(&WhatsAppProto::sentinelLoop, 0); ForkThread(&WhatsAppProto::stayConnectedLoop, 0); } else if (m_pConnection != NULL) { if (m_iDesiredStatus == ID_STATUS_ONLINE) { m_pConnection->sendAvailableForChat(); m_iStatus = ID_STATUS_ONLINE; ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); } else if (m_iStatus == ID_STATUS_ONLINE && m_iDesiredStatus == ID_STATUS_INVISIBLE) { m_pConnection->sendClose(); m_iStatus = ID_STATUS_INVISIBLE; SetAllContactStatuses(ID_STATUS_OFFLINE, true); ProtoBroadcastAck(0, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); } } else ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, m_iStatus); return 0; }
void CSkypeProto::OnLoginOAuth(const NETLIBHTTPREQUEST *response) { if (!IsStatusConnecting(m_iStatus)) return; if (response == NULL || response->pData == NULL) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } JSONNode json = JSONNode::parse(response->pData); if (!json) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } if (response->resultCode != 200) { int error = 0; if (json["status"]) { const JSONNode &status = json["status"]; if (status["code"]) { switch(status["code"].as_int()) { case 40002: { ShowNotification(_T("Skype"), TranslateT("Authentication failed. Invalid username."), NULL, 1); error = LOGINERR_BADUSERID; break; } case 40120: { ShowNotification(_T("Skype"), TranslateT("Authentication failed. Bad username or password."), NULL, 1); error = LOGINERR_WRONGPASSWORD; break; } case 40121: { ShowNotification(_T("Skype"), TranslateT("Too many failed authentication attempts with given username or IP."), NULL, 1); error = LOGIN_ERROR_TOOMANY_REQUESTS; break; } default: { ShowNotification(_T("Skype"), status["text"] ? status["text"].as_mstring() : TranslateT("Authentication failed. Unknown error."), NULL, 1); error = LOGIN_ERROR_UNKNOWN; } } } } ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, error); SetStatus(ID_STATUS_OFFLINE); return; } if (!json["skypetoken"] || !json["expiresIn"]) { ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } std::string token = json["skypetoken"].as_string(); setString("TokenSecret", token.c_str()); int expiresIn = json["expiresIn"].as_int(); setDword("TokenExpiresIn", time(NULL) + expiresIn); OnLoginSuccess(); }
void CSkypeProto::OnEndpointCreated(const NETLIBHTTPREQUEST *response) { if (!IsStatusConnecting(m_iStatus)) return; m_iStatus++; if (response == NULL) { debugLogA(__FUNCTION__ ": failed to get create endpoint"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } for (int i = 0; i < response->headersCount; i++) { if (!mir_strcmpi(response->headers[i].szName, "Set-RegistrationToken")) { CMStringA szValue = response->headers[i].szValue, szCookieName, szCookieVal; int iStart = 0; while (true) { CMStringA szToken = szValue.Tokenize(";", iStart).Trim(); if (iStart == -1) break; int iStart2 = 0; szCookieName = szToken.Tokenize("=", iStart2); szCookieVal = szToken.Mid(iStart2); setString(szCookieName, szCookieVal); } } else if (!mir_strcmpi(response->headers[i].szName, "Location")) { CMStringA szValue = response->headers[i].szValue; li.endpoint.szServer = GetServerFromUrl(szValue).Detach(); setString("Server", li.endpoint.szServer); } } if (m_iStatus++ > SKYPE_MAX_CONNECT_RETRIES) { debugLogA(__FUNCTION__ ": failed to create endpoint (too many connect retries)"); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, NULL, LOGIN_ERROR_UNKNOWN); SetStatus(ID_STATUS_OFFLINE); return; } if (response->resultCode != 201) { if (response->resultCode == 401) { delSetting("TokenExpiresIn"); SendRequest(new LoginOAuthRequest(li.szSkypename, ptrA(getStringA(SKYPE_SETTINGS_PASSWORD))), &CSkypeProto::OnLoginOAuth); return; } else //it should be rewritten { SendRequest(new CreateEndpointRequest(li), &CSkypeProto::OnEndpointCreated); return; } } li.endpoint.szToken = getStringA("registrationToken"); li.endpoint.szId = getStringA("endpointId"); SendRequest(new CreateSubscriptionsRequest(li), &CSkypeProto::OnSubscriptionsCreated); }
MIR_APP_DLL(HICON) Skin_LoadProtoIcon(const char *szProto, int status, bool big) { char iconName[MAX_PATH]; INT_PTR caps2; if (szProto == NULL) caps2 = -1; else if ((caps2 = CallProtoServiceInt(NULL, szProto, PS_GETCAPS, PFLAGNUM_2, 0)) == CALLSERVICE_NOTFOUND) caps2 = 0; if (IsStatusConnecting(status)) { mir_snprintf(iconName, "%s%d", mainIconsFmt, 7); return IcoLib_GetIcon(iconName, big); } int statusIndx = -1; for (int i = 0; i < _countof(statusIcons); i++) if (statusIcons[i].id == status) { statusIndx = i; break; } if (statusIndx == -1) return NULL; if (!szProto) { // Only return a protocol specific icon if there is only one protocol // Otherwise return the global icon. This affects the global status menu mainly. if (accounts.getCount() == 1) { // format: core_status_%proto%statusindex mir_snprintf(iconName, "%s%s%d", statusIconsFmt, szProto, statusIndx); HICON hIcon = IcoLib_GetIcon(iconName, big); if (hIcon) return hIcon; } // format: core_status_%s%d mir_snprintf(iconName, "%s%s%d", statusIconsFmt, GLOBAL_PROTO_NAME, statusIndx); return IcoLib_GetIcon(iconName, big); } // format: core_status_%s%d mir_snprintf(iconName, "%s%s%d", statusIconsFmt, szProto, statusIndx); HICON hIcon = IcoLib_GetIcon(iconName, big); if (hIcon == NULL && (caps2 == 0 || (caps2 & statusIcons[statusIndx].pf2))) { PROTOACCOUNT *pa = Proto_GetAccount(szProto); if (pa) { TCHAR szPath[MAX_PATH], szFullPath[MAX_PATH], *str; GetModuleFileName(NULL, szPath, _countof(szPath)); // Queried protocol isn't in list, adding TCHAR tszSection[MAX_PATH]; mir_sntprintf(tszSection, _T(PROTOCOLS_PREFIX)_T("/%s"), pa->tszAccountName); SKINICONDESC sid = { 0 }; sid.section.t = tszSection; sid.flags = SIDF_ALL_TCHAR; str = _tcsrchr(szPath, '\\'); if (str != NULL) *str = 0; mir_sntprintf(szFullPath, _T("%s\\Icons\\proto_%S.dll"), szPath, pa->szProtoName); if (GetFileAttributes(szFullPath) != INVALID_FILE_ATTRIBUTES) sid.defaultFile.t = szFullPath; else { mir_sntprintf(szFullPath, _T("%s\\Plugins\\%S.dll"), szPath, szProto); if (int(ExtractIconEx(szFullPath, statusIcons[statusIndx].resource_id, NULL, &hIcon, 1)) > 0) { DestroyIcon(hIcon); sid.defaultFile.t = szFullPath; hIcon = NULL; } if (sid.defaultFile.a == NULL) { if (str != NULL) *str = '\\'; sid.defaultFile.t = szPath; } } // Add global icons to list int lowidx, highidx; if (caps2 == 0) lowidx = statusIndx, highidx = statusIndx + 1; else lowidx = 0, highidx = _countof(statusIcons); for (int i = lowidx; i < highidx; i++) { if (caps2 == 0 || (caps2 & statusIcons[i].pf2)) { // format: core_%s%d mir_snprintf(iconName, "%s%s%d", statusIconsFmt, szProto, i); sid.pszName = iconName; sid.description.t = cli.pfnGetStatusModeDescription(statusIcons[i].id, 0); sid.iDefaultIndex = statusIcons[i].resource_id; IcoLib_AddIcon(&sid, 0); } } } // format: core_status_%s%d mir_snprintf(iconName, "%s%s%d", statusIconsFmt, szProto, statusIndx); hIcon = IcoLib_GetIcon(iconName, big); if (hIcon) return hIcon; } if (hIcon == NULL) { mir_snprintf(iconName, "%s%s%d", statusIconsFmt, GLOBAL_PROTO_NAME, statusIndx); hIcon = IcoLib_GetIcon(iconName, big); } return hIcon; }