STDMETHODIMP CExtImpl::OnRead(IExchExtCallback* peecb) { HWND hwnd; peecb->GetWindow(&hwnd); if (!hwnd) hwnd = GetTopWindow(NULL); switch (_context) { case EECONTEXT_SENDNOTEMESSAGE: { BOOL fAddButtons = TRUE; int nNumButtons; int nIndex; TBBUTTON tbbNew[5]; TBBUTTON tbbCheck; // Check to make sure the buttons aren't already on the toolbar nNumButtons = SendMessage(_hwndSendToolbar, TB_BUTTONCOUNT, 0, 0); for (nIndex=0; nIndex<nNumButtons; nIndex++) { SendMessage(_hwndSendToolbar, TB_GETBUTTON, (WPARAM) nIndex, (LPARAM) &tbbCheck); // If a button exists with the same bitmap ID and command ID // as the Encrypt button, odds are good that the button is // already on the toolbar if ((tbbCheck.iBitmap == (int)_itbmEncrypt) && (tbbCheck.idCommand == (int)_cmdidEncrypt)) { fAddButtons = FALSE; nIndex = nNumButtons; } } if (fAddButtons) { tbbNew[0].iBitmap = 0; tbbNew[0].idCommand = 0; tbbNew[0].fsState = 0; tbbNew[0].fsStyle = TBSTYLE_SEP; tbbNew[0].dwData = 0; tbbNew[0].iString = -1; tbbNew[1].iBitmap = _itbmEncrypt; tbbNew[1].idCommand = _cmdidEncrypt; tbbNew[1].fsState = TBSTATE_ENABLED; tbbNew[1].fsStyle = TBSTYLE_CHECK; tbbNew[1].dwData = 0; tbbNew[1].iString = -1; tbbNew[2].iBitmap = _itbmSign; tbbNew[2].idCommand = _cmdidSign; tbbNew[2].fsState = TBSTATE_ENABLED; tbbNew[2].fsStyle = TBSTYLE_CHECK; tbbNew[2].dwData = 0; tbbNew[2].iString = -1; tbbNew[3].iBitmap = 0; tbbNew[3].idCommand = 0; tbbNew[3].fsState = 0; tbbNew[3].fsStyle = TBSTYLE_SEP; tbbNew[3].dwData = 0; tbbNew[3].iString = -1; tbbNew[4].iBitmap = _itbmPgpKeys; tbbNew[4].idCommand = _cmdidPgpKeys; tbbNew[4].fsState = TBSTATE_ENABLED; tbbNew[4].fsStyle = TBSTYLE_BUTTON; tbbNew[4].dwData = 0; tbbNew[4].iString = -1; SendMessage(_hwndSendToolbar, TB_ADDBUTTONS, 5, (LPARAM) tbbNew); } } break; case EECONTEXT_SENDPOSTMESSAGE: break; case EECONTEXT_READNOTEMESSAGE: { BOOL fAddButtons = TRUE; int nNumButtons; int nIndex; TBBUTTON tbbNew[5]; TBBUTTON tbbCheck; BOOL FYEO; // Check to make sure the buttons aren't already on the toolbar nNumButtons = SendMessage(_hwndReadToolbar, TB_BUTTONCOUNT, 0, 0); for (nIndex=0; nIndex<nNumButtons; nIndex++) { SendMessage(_hwndReadToolbar, TB_GETBUTTON, (WPARAM) nIndex, (LPARAM) &tbbCheck); // If a button exists with the same bitmap ID and command ID // as the Decrypt button, odds are good that the button is // already on the toolbar if ((tbbCheck.iBitmap == (int)_itbmDecrypt) && (tbbCheck.idCommand == (int)_cmdidDecrypt)) { fAddButtons = FALSE; nIndex = nNumButtons; } } if (fAddButtons) { tbbNew[0].iBitmap = 0; tbbNew[0].idCommand = 0; tbbNew[0].fsState = 0; tbbNew[0].fsStyle = TBSTYLE_SEP; tbbNew[0].dwData = 0; tbbNew[0].iString = -1; tbbNew[1].iBitmap = _itbmDecrypt; tbbNew[1].idCommand = _cmdidDecrypt; tbbNew[1].fsState = TBSTATE_ENABLED; tbbNew[1].fsStyle = TBSTYLE_BUTTON; tbbNew[1].dwData = 0; tbbNew[1].iString = -1; tbbNew[2].iBitmap = 0; tbbNew[2].idCommand = 0; tbbNew[2].fsState = 0; tbbNew[2].fsStyle = TBSTYLE_SEP; tbbNew[2].dwData = 0; tbbNew[2].iString = -1; tbbNew[3].iBitmap = _itbmPgpKeys; tbbNew[3].idCommand = _cmdidPgpKeys; tbbNew[3].fsState = TBSTATE_ENABLED; tbbNew[3].fsStyle = TBSTYLE_BUTTON; tbbNew[3].dwData = 0; tbbNew[3].iString = -1; SendMessage(_hwndReadToolbar, TB_ADDBUTTONS, 4, (LPARAM) tbbNew); } IMAPISession* psess; HRESULT hr = peecb->GetSession(&psess, NULL); if (FAILED(hr)) { UIDisplayStringID(hwnd, IDS_E_NOSESSION); return S_FALSE; } if (AutoDecrypt(_memoryMgr)) { IMessage *pmsg = 0; STATSTG StreamStats; DWORD dwInSize; UINT nOutSize; char *pInput; char *pOutput = NULL; BOOL bGotHTML = FALSE; PGPError nError = kPGPError_NoErr; char szFile[256]; char szName[256]; UIGetString(szName, sizeof(szName), IDS_LOGNAME); UIGetString(szFile, sizeof(szFile), IDS_DLL); CWaitCursor wait; // Mark busy hr = peecb->GetObject(NULL, (IMAPIProp**)&pmsg); if (FAILED(hr)) { return S_FALSE; } IStream *pstrmBody = 0; hr = pmsg->OpenProperty(PR_BODY_HTML, &IID_IStream, STGM_READWRITE, MAPI_MODIFY, (IUnknown**)&pstrmBody); if (FAILED(hr)) { hr = pmsg->OpenProperty(PR_BODY, &IID_IStream, STGM_READWRITE, MAPI_MODIFY, (IUnknown**)&pstrmBody); } else bGotHTML = TRUE; if (FAILED(hr)) { pmsg->Release(); psess->Release(); return S_FALSE; } pstrmBody->Stat(&StreamStats, STATFLAG_NONAME); dwInSize = StreamStats.cbSize.LowPart; pInput = (char *) calloc(dwInSize+1, sizeof(char)); if (!pInput) { UIDisplayStringID(hwnd, IDS_E_NOMEMORY); pstrmBody->Release(); pmsg->Release(); psess->Release(); return S_FALSE; } pstrmBody->Read(pInput, dwInSize, &dwInSize); pInput[dwInSize] = 0; if (AutoDecrypt(_memoryMgr)) { nError = DecryptVerifyBuffer(UIGetInstance(), hwnd, _pgpContext, _tlsContext, szName, szFile, pInput, dwInSize, FALSE, (VOID ** )&pOutput, &nOutSize, &FYEO); if (IsntPGPError(nError) && (nOutSize > 0) && (pOutput != NULL)) { LARGE_INTEGER li = {0,0}; ULARGE_INTEGER uli = {nOutSize, 0}; BOOL fPartied; char *szBuffer = NULL; // Alter only the block of encrypted/signed text // if this is not HTML if((FYEO)||(GetSecureViewerPref(_pgpContext))) { TempestViewer((void *)_pgpContext,hwnd, pOutput,nOutSize,FYEO); } else { szBuffer = (char *) calloc(dwInSize+nOutSize+1, sizeof(char)); strcpy(szBuffer, pOutput); if (strlen(szBuffer) > 0) { uli.LowPart = strlen(szBuffer); pstrmBody->Seek(li, STREAM_SEEK_SET, NULL); pstrmBody->Write(szBuffer, strlen(szBuffer), NULL); pstrmBody->SetSize(uli); pstrmBody->Commit(STGC_DEFAULT); pstrmBody->Release(); RTFSync(pmsg, RTF_SYNC_BODY_CHANGED, &fPartied); } free(szBuffer); } PGPFreeData(pOutput); } else pstrmBody->Release(); } else pstrmBody->Release(); free(pInput); pmsg->Release(); } psess->Release(); } break; case EECONTEXT_READPOSTMESSAGE: break; default: // This way, the function defends itself against unknown future // variants, as FindREOnNote is less robust than it might be. return S_FALSE; } return S_FALSE; }
/** * Opens an admin session and the outgoing queue. If either one * produces an error this function will return. If the queue is empty, * it will wait for a notification when new data is present in the * outgoing queue table. * * @param[in] szSMTP The SMTP server to send to. * @param[in] ulPort The SMTP port to sent to. * @param[in] szPath URI of Zarafa server to connect to, must be file:// or https:// with valid ssl certificates. * @return HRESULT */ HRESULT ProcessQueue(char* szSMTP, int ulPort, char *szPath) { HRESULT hr = hrSuccess; IMAPISession *lpAdminSession = NULL; IECSpooler *lpSpooler = NULL; IMAPITable *lpTable = NULL; IMAPIAdviseSink *lpAdviseSink = NULL; ULONG ulConnection = 0; SizedSPropTagArray(5, sOutgoingCols) = { 5, { PR_EC_MAILBOX_OWNER_ACCOUNT_W, PR_STORE_ENTRYID, PR_ENTRYID, PR_EC_OUTGOING_FLAGS, PR_DEFERRED_SEND_TIME, } }; SSortOrderSet sSort = { 1, 0, 0, { { PR_EC_HIERARCHYID, TABLE_SORT_ASCEND } } }; hr = HrOpenECAdminSession(g_lpLogger, &lpAdminSession, "zarafa-spooler:system", PROJECT_SVN_REV_STR, szPath, EC_PROFILE_FLAGS_NO_PUBLIC_STORE, g_lpConfig->GetSetting("sslkey_file", "", NULL), g_lpConfig->GetSetting("sslkey_pass", "", NULL)); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to open admin session. Error 0x%08X", hr); goto exit; } if (disconnects == 0) g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "Connection to Zarafa server succeeded"); else g_lpLogger->Log(EC_LOGLEVEL_INFO, "Connection to Zarafa server succeeded after %d retries", disconnects); disconnects = 0; // first call succeeded, assume all is well. hr = GetAdminSpooler(lpAdminSession, &lpSpooler); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "ProcessQueue: GetAdminSpooler failed %x", hr); goto exit; } // Mark reload as done since we reloaded the outgoing table nReload = false; // Request the master outgoing table hr = lpSpooler->GetMasterOutgoingTable(0, &lpTable); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Master outgoing queue not available"); goto exit; } hr = lpTable->SetColumns((LPSPropTagArray)&sOutgoingCols, 0); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to setColumns() on OutgoingQueue"); goto exit; } // Sort by ascending hierarchyid: first in, first out queue hr = lpTable->SortTable(&sSort, 0); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to SortTable() on OutgoingQueue"); goto exit; } hr = HrAllocAdviseSink(AdviseCallback, NULL, &lpAdviseSink); if (hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Unable to allocate memory for advise sink"); goto exit; } // notify on new mail in the outgoing table hr = lpTable->Advise(fnevTableModified, lpAdviseSink, &ulConnection); while(!bQuit && !nReload) { bMessagesWaiting = false; lpTable->SeekRow(BOOKMARK_BEGINNING, 0, NULL); // also checks not to send a message again which is already sending hr = ProcessAllEntries(lpAdminSession, lpSpooler, lpTable, szSMTP, ulPort, szPath); if(hr != hrSuccess) { g_lpLogger->Log(EC_LOGLEVEL_WARNING, "ProcessQueue: ProcessAllEntries failed %x", hr); goto exit; } // Exit signal, break the operation if(bQuit) break; if(nReload) break; pthread_mutex_lock(&hMutexMessagesWaiting); if(!bMessagesWaiting) { struct timespec timeout; struct timeval now; // Wait for max 60 sec, then run queue anyway gettimeofday(&now,NULL); timeout.tv_sec = now.tv_sec + 60; timeout.tv_nsec = now.tv_usec * 1000; while (!bMessagesWaiting) { if (pthread_cond_timedwait(&hCondMessagesWaiting, &hMutexMessagesWaiting, &timeout) == ETIMEDOUT || bMessagesWaiting || bQuit || nReload) break; // not timed out, no messages waiting, not quit requested, no table reload required: // we were triggered for a cleanup call. CleanFinishedMessages(lpAdminSession, lpSpooler); } } pthread_mutex_unlock(&hMutexMessagesWaiting); // remove any entries that were done during the wait CleanFinishedMessages(lpAdminSession, lpSpooler); } exit: // when we exit, we must make sure all forks started are cleaned if (bQuit) { ULONG ulCount = 0; ULONG ulThreads = 0; while (ulCount < 60) { if ((ulCount % 5) == 0) { ulThreads = mapSendData.size(); g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Still waiting for %d thread%c to exit.", ulThreads, ulThreads!=1?'s':' '); } CleanFinishedMessages(lpAdminSession, lpSpooler); if (mapSendData.size() == 0) break; Sleep(1000); ulCount++; } if (ulCount == 60) g_lpLogger->Log(EC_LOGLEVEL_DEBUG, "%d threads did not yet exit, closing anyway.", (int)mapSendData.size()); } else if (nReload) { g_lpLogger->Log(EC_LOGLEVEL_WARNING, "Table reload requested, breaking server connection"); } if (lpTable && ulConnection) lpTable->Unadvise(ulConnection); if (lpAdviseSink) lpAdviseSink->Release(); if (lpTable) lpTable->Release(); if (lpSpooler) lpSpooler->Release(); if (lpAdminSession) lpAdminSession->Release(); return hr; }
bool MAPIStorageAdviser::AdviseAll() { IMAPISession* pSession = InitIMAPISession(); IMAPITable* pStoresTable = GetStoresTable(pSession); SizedSPropTagArray(2, tblColumns) = {2, {PR_DISPLAY_NAME, PR_ENTRYID}}; pStoresTable->SetColumns((LPSPropTagArray)&tblColumns, 0); for(;;) { SRowSet * pRowSet = NULL; pStoresTable->QueryRows(1, 0, &pRowSet); if(pRowSet->cRows != 1) break; ASSERT(pRowSet->aRow[0].cValues == tblColumns.cValues); SPropValue* pVal = pRowSet->aRow[0].lpProps; ASSERT(pVal[0].ulPropTag == PR_DISPLAY_NAME); ASSERT(pVal[1].ulPropTag == PR_ENTRYID); LPWSTR lpStoreName = pRowSet->aRow[0].lpProps[0].Value.lpszW; // Open Store LPBYTE pEntry = (LPBYTE)pRowSet->aRow[0].lpProps[1].Value.bin.lpb; ULONG ulStoreBytes = pRowSet->aRow[0].lpProps[1].Value.bin.cb; IMsgStore* pStore = _GetStoreFromEntryID(pSession, ulStoreBytes, pEntry); if (pStore == NULL) { continue; } if (AddSink(pStore) == true) { }else{ } pStore->Release(); FreeProws(pRowSet); } pStoresTable->Release(); pSession->Release(); return true; }