int SendQueue::ackMessage(TWindowData *dat, WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA *) lParam; DBEVENTINFO dbei = { 0}; HANDLE hNewEvent; int iFound = SendQueue::NR_SENDJOBS, iNextFailed; TContainerData *m_pContainer = 0; if (dat) m_pContainer = dat->pContainer; iFound = (int)(LOWORD(wParam)); //i = (int)(HIWORD(wParam)); if (m_jobs[iFound].iStatus == SQ_ERROR) { // received ack for a job which is already in error state... if (dat) { // window still open if (dat->iCurrentQueueError == iFound) { dat->iCurrentQueueError = -1; showErrorControls(dat, FALSE); } } /* * we must discard this job, because there is no message window open to handle the * error properly. But we display a tray notification to inform the user about the problem. */ else goto inform_and_discard; } // failed acks are only handled when the window is still open. with no window open, they will be *silently* discarded if (ack->result == ACKRESULT_FAILED) { if (dat) { /* * "hard" errors are handled differently in multisend. There is no option to retry - once failed, they * are discarded and the user is notified with a small log message. */ if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendError"); TCHAR *szAckMsg = mir_a2t((char *)ack->lParam); mir_sntprintf(m_jobs[iFound].szErrorMsg, safe_sizeof(m_jobs[iFound].szErrorMsg), CTranslator::get(CTranslator::GEN_MSG_DELIVERYFAILURE), szAckMsg); m_jobs[iFound].iStatus = SQ_ERROR; mir_free(szAckMsg); KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); if (!(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iFound); return 0; } else { inform_and_discard: _DebugPopup(m_jobs[iFound].hOwner, CTranslator::get(CTranslator::GEN_SQ_DELIVERYFAILEDLATE)); clearJob(iFound); return 0; } } dbei.cbSize = sizeof(dbei); dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_SENT; dbei.szModule = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) m_jobs[iFound].hOwner, 0); dbei.timestamp = time(NULL); dbei.cbBlob = lstrlenA(m_jobs[iFound].sendBuffer) + 1; if (dat) dat->cache->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); else { CContactCache *c = CContactCache::getContactCache(m_jobs[iFound].hOwner); if(c) c->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); } if (m_jobs[iFound].dwFlags & PREF_UNICODE) dbei.cbBlob *= sizeof(TCHAR) + 1; if (m_jobs[iFound].dwFlags & PREF_RTL) dbei.flags |= DBEF_RTL; if (m_jobs[iFound].dwFlags & PREF_UTF) dbei.flags |= DBEF_UTF; dbei.pBlob = (PBYTE) m_jobs[iFound].sendBuffer; hNewEvent = (HANDLE) CallService(MS_DB_EVENT_ADD, (WPARAM) m_jobs[iFound].hOwner, (LPARAM) & dbei); if (m_pContainer) { if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendMsg"); } if (dat && (m_jobs[iFound].hOwner == dat->hContact)) { if (dat->hDbEventFirst == NULL) { dat->hDbEventFirst = hNewEvent; SendMessage(dat->hwnd, DM_REMAKELOG, 0, 0); } } m_jobs[iFound].hSendId = NULL; m_jobs[iFound].iAcksNeeded--; if (m_jobs[iFound].iAcksNeeded == 0) { // everything sent //if (m_jobs[iFound].hOwner != 0 && dat) // EnableSending(dat, TRUE); clearJob(iFound); if (dat) { KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); dat->iOpenJobs--; } m_currentIndex--; } if (dat) { checkQueue(dat); if ((iNextFailed = findNextFailed(dat)) >= 0 && !(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iNextFailed); //MAD: close on send mode else { if (M->GetByte("AutoClose", 0)) { if(M->GetByte("adv_AutoClose_2", 0)) SendMessage(dat->hwnd, WM_CLOSE, 0, 1); else SendMessage(dat->pContainer->hwnd, WM_CLOSE, 0, 0); } } //MAD_ } return 0; }
int SendQueue::ackMessage(TWindowData *dat, WPARAM wParam, LPARAM lParam) { ACKDATA *ack = (ACKDATA *)lParam; TContainerData *m_pContainer = 0; if (dat) m_pContainer = dat->pContainer; int iFound = (int)(LOWORD(wParam)); SendJob &job = m_jobs[iFound]; if (job.iStatus == SQ_ERROR) { // received ack for a job which is already in error state... if (dat) { // window still open if (dat->iCurrentQueueError == iFound) { dat->iCurrentQueueError = -1; showErrorControls(dat, FALSE); } } // we must discard this job, because there is no message window open to handle the // error properly. But we display a tray notification to inform the user about the problem. else goto inform_and_discard; } // failed acks are only handled when the window is still open. with no window open, they will be *silently* discarded if (ack->result == ACKRESULT_FAILED) { if (dat) { // "hard" errors are handled differently in multisend. There is no option to retry - once failed, they // are discarded and the user is notified with a small log message. if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendError"); TCHAR *szAckMsg = mir_a2t((char *)ack->lParam); mir_sntprintf(job.szErrorMsg, TranslateT("Delivery failure: %s"), szAckMsg); job.iStatus = SQ_ERROR; mir_free(szAckMsg); KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); if (!(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iFound); return 0; } inform_and_discard: _DebugPopup(job.hContact, TranslateT("A message delivery has failed after the contacts chat window was closed. You may want to resend the last message")); clearJob(iFound); return 0; } DBEVENTINFO dbei = { sizeof(dbei) }; dbei.eventType = EVENTTYPE_MESSAGE; dbei.flags = DBEF_SENT; dbei.szModule = GetContactProto(job.hContact); dbei.timestamp = time(NULL); dbei.cbBlob = (int)mir_strlen(job.szSendBuffer) + 1; if (dat) dat->cache->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); else { CContactCache *cc = CContactCache::getContactCache(job.hContact); if (cc) cc->updateStats(TSessionStats::BYTES_SENT, dbei.cbBlob - 1); } if (job.dwFlags & PREF_RTL) dbei.flags |= DBEF_RTL; dbei.flags |= DBEF_UTF; dbei.pBlob = (PBYTE)job.szSendBuffer; MessageWindowEvent evt = { sizeof(evt), (INT_PTR)job.hSendId, job.hContact, &dbei }; NotifyEventHooks(PluginConfig.m_event_WriteEvent, 0, (LPARAM)&evt); job.szSendBuffer = (char*)dbei.pBlob; MEVENT hNewEvent = db_event_add(job.hContact, &dbei); if (m_pContainer) if (!nen_options.iNoSounds && !(m_pContainer->dwFlags & CNT_NOSOUND)) SkinPlaySound("SendMsg"); M.BroadcastMessage(DM_APPENDMCEVENT, job.hContact, LPARAM(hNewEvent)); job.hSendId = NULL; job.iAcksNeeded--; if (job.iAcksNeeded == 0) { // everything sent clearJob(iFound); if (dat) { KillTimer(dat->hwnd, TIMERID_MSGSEND + iFound); dat->iOpenJobs--; } m_currentIndex--; } if (dat) { checkQueue(dat); int iNextFailed = findNextFailed(dat); if (iNextFailed >= 0 && !(dat->dwFlags & MWF_ERRORSTATE)) handleError(dat, iNextFailed); else { if (M.GetByte("AutoClose", 0)) { if (M.GetByte("adv_AutoClose_2", 0)) SendMessage(dat->hwnd, WM_CLOSE, 0, 1); else SendMessage(dat->pContainer->hwnd, WM_CLOSE, 0, 0); } } } return 0; }