summaryrefslogtreecommitdiff
path: root/plugins/Exchange/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Exchange/src')
-rw-r--r--plugins/Exchange/src/MirandaExchange.cpp1011
-rw-r--r--plugins/Exchange/src/MirandaExchange.h241
-rw-r--r--plugins/Exchange/src/StdAfx.cpp8
-rw-r--r--plugins/Exchange/src/StdAfx.h24
-rw-r--r--plugins/Exchange/src/commonheaders.h71
-rw-r--r--plugins/Exchange/src/dlg_handlers.cpp514
-rw-r--r--plugins/Exchange/src/dlg_handlers.h32
-rw-r--r--plugins/Exchange/src/emails.cpp424
-rw-r--r--plugins/Exchange/src/emails.h96
-rw-r--r--plugins/Exchange/src/exchange.cpp99
-rw-r--r--plugins/Exchange/src/hooked_events.cpp176
-rw-r--r--plugins/Exchange/src/hooked_events.h49
-rw-r--r--plugins/Exchange/src/resource.h29
-rw-r--r--plugins/Exchange/src/services.cpp50
-rw-r--r--plugins/Exchange/src/services.h35
-rw-r--r--plugins/Exchange/src/utils.cpp276
-rw-r--r--plugins/Exchange/src/utils.h52
-rw-r--r--plugins/Exchange/src/version.h45
18 files changed, 3232 insertions, 0 deletions
diff --git a/plugins/Exchange/src/MirandaExchange.cpp b/plugins/Exchange/src/MirandaExchange.cpp
new file mode 100644
index 0000000000..b0fad31eb1
--- /dev/null
+++ b/plugins/Exchange/src/MirandaExchange.cpp
@@ -0,0 +1,1011 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+/********************************************************************
+ created: 2006/04/11
+ created: 11:4:2006 17:28
+ filename: MirandaExchange.cpp
+ file base: MirandaExchange
+ file ext: cpp
+ author: Attila Vajda
+
+ purpose: Miranda Exchange Plugin
+*********************************************************************/
+
+#include "stdafx.h"
+#include "MirandaExchange.h"
+#include "commonheaders.h"
+#include "utils.h"
+
+#include <time.h>
+
+#ifndef NO_EXCHANGE_TEST
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT HrMAPIFindDefaultMsgStore( // RETURNS: return code
+ IN LPMAPISESSION lplhSession, // session pointer
+ OUT ULONG *lpcbeid, // count of bytes in entry ID
+ OUT LPENTRYID *lppeid) // entry ID of default store
+{
+ HRESULT hr = NOERROR;
+ HRESULT hrT = NOERROR;
+ SCODE sc = 0;
+ LPMAPITABLE lpTable = NULL;
+ LPSRowSet lpRows = NULL;
+ LPENTRYID lpeid = NULL;
+ ULONG cbeid = 0;
+ ULONG cRows = 0;
+ ULONG i = 0;
+
+ SizedSPropTagArray(2, rgPropTagArray)={2,{PR_DEFAULT_STORE,PR_ENTRYID}};
+
+ // Get the list of available message stores from MAPI
+ hrT = MAPICALL(lplhSession)->GetMsgStoresTable( 0, &lpTable);
+
+ if(!FAILED(hrT))
+ {
+ // Get the row count for the message recipient table
+ hrT = MAPICALL(lpTable)->GetRowCount(0, &cRows);
+ if(!FAILED(hrT))
+ {
+ // Set the columns to return
+ hrT = MAPICALL(lpTable)->SetColumns((LPSPropTagArray)&rgPropTagArray, 0);
+ if(!FAILED(hrT))
+ {
+ // Go to the beginning of the recipient table for the envelope
+ hrT = MAPICALL(lpTable)->SeekRow( BOOKMARK_BEGINNING, 0, NULL);
+ if(!FAILED(hrT))
+ {
+ // Read all the rows of the table
+ hrT = MAPICALL(lpTable)->QueryRows( cRows, 0, &lpRows);
+ if(SUCCEEDED(hrT) && (lpRows != NULL) && (lpRows->cRows == 0))
+ {
+ FreeProws(lpRows);
+ lpRows = NULL;
+ hrT = MAPI_E_NOT_FOUND;
+ }
+ }
+ }
+ }
+ }
+
+ if( !FAILED(hrT) )
+ {
+ bool bGetOut = false;
+ for(i = 0; (i < cRows) && (!bGetOut); i++)
+ {
+ if(lpRows->aRow[i].lpProps[0].Value.b == TRUE)
+ {
+ cbeid = lpRows->aRow[i].lpProps[1].Value.bin.cb;
+
+ sc = MAPIAllocateBuffer(cbeid, (void **)&lpeid);
+
+ if(FAILED(sc))
+ {
+ cbeid = 0;
+ lpeid = NULL;
+ bGetOut = true;
+ }
+ else
+ {
+ // Copy entry ID of message store
+ CopyMemory(lpeid,lpRows->aRow[i].lpProps[1].Value.bin.lpb,cbeid);
+ bGetOut = true;
+ }
+ }
+ }
+ }
+
+ if(lpRows != NULL)
+ {
+ FreeProws(lpRows);
+ }
+
+ UlRelease(lpTable);
+ *lpcbeid = cbeid;
+ *lppeid = lpeid;
+ return hr;
+}
+
+
+CKeeper::CKeeper( LPTSTR szSender, LPTSTR szSubject, LPSTR szEntryID)
+{
+ m_szSender = NULL ;
+ m_szSubject = NULL ;
+ m_szEntryID = NULL ;
+ m_nSizeSender = 0 ;
+ m_nSizeSubject = 0 ;
+ m_nSizeEntryID = 0 ;
+
+ if (NULL != szSender )
+ {
+ m_nSizeSender = _tcslen ( szSender ) +1;
+ m_szSender = new TCHAR[ m_nSizeSender ];
+ memset ( m_szSender, 0, m_nSizeSender * sizeof(TCHAR) );
+ _tcscpy( m_szSender, szSender);
+ }
+
+ if ( NULL != szSubject )
+ {
+ m_nSizeSubject = _tcslen( szSubject ) +1;
+ m_szSubject = new TCHAR[m_nSizeSubject];
+ memset ( m_szSubject, 0, m_nSizeSubject * sizeof(TCHAR) );
+ _tcscpy( m_szSubject, szSubject );
+ }
+
+ if ( NULL != szEntryID )
+ {
+ m_nSizeEntryID = strlen( szEntryID ) +1;
+ m_szEntryID = new char[m_nSizeEntryID];
+ memset ( m_szEntryID, 0, m_nSizeEntryID * sizeof(char) );
+ strcpy( m_szEntryID, szEntryID );
+ }
+}
+
+CKeeper::~CKeeper()
+{
+ if ( m_nSizeSender>0 && NULL != m_szSender )
+ {
+ m_nSizeSender =0;
+ delete[] m_szSender;
+ m_szSender = NULL;
+ }
+
+ if ( m_nSizeSubject>0 && NULL != m_szSubject )
+ {
+ m_nSizeSender =0;
+ delete[] m_szSubject;
+ m_szSubject = NULL;
+ }
+
+ if ( m_nSizeEntryID>0 && NULL != m_szEntryID )
+ {
+ m_nSizeEntryID = 0;
+ delete[] m_szEntryID;
+ m_szEntryID = NULL;
+ }
+}
+
+CMirandaExchange::CMirandaExchange()
+{
+ UINT nSize = 0;
+ short nSizeOfTCHAR = sizeof( TCHAR );
+
+ m_szUsername = NULL ;
+ m_szPassword = NULL ;
+ m_szExchangeServer = NULL ;
+ m_lpMAPISession = NULL ;
+ m_lpInbox = NULL ;
+ m_lpMDB = NULL;
+ m_bLoginOK = false ;
+ m_bFolderInboxOK = false ;
+ m_nNumberOfHeaders = 0 ;
+}
+
+CMirandaExchange::~CMirandaExchange()
+{
+ if ( NULL != m_szUsername )
+ {
+ delete[] m_szUsername;
+ m_szUsername = NULL;
+ }
+
+ if ( NULL != m_szPassword )
+ {
+ delete[] m_szPassword;
+ m_szPassword = NULL;
+ }
+
+ if ( NULL != m_szExchangeServer )
+ {
+ delete[] m_szExchangeServer;
+ m_szExchangeServer = NULL;
+ }
+
+ if ( NULL != m_lpInbox )
+ {
+ UlRelease(m_lpInbox);
+ m_lpInbox = NULL;
+ }
+
+ if ( NULL != m_lpMDB )
+ {
+ UlRelease(m_lpMDB );
+ m_lpMDB = NULL;
+ }
+
+ if( NULL!= m_lpMAPISession )
+ {
+ m_lpMAPISession->Logoff(NULL,NULL,NULL);
+ UlRelease(m_lpMAPISession );
+ m_lpMAPISession = NULL;
+ }
+
+ if ( m_nNumberOfHeaders>0 && NULL != m_HeadersKeeper )
+ {
+ for( UINT i=0; i<m_nNumberOfHeaders; i++ )
+ {
+ if ( NULL != m_HeadersKeeper[i])
+ {
+ delete m_HeadersKeeper[i];
+ m_HeadersKeeper[i] = NULL;
+ }
+ }
+
+ m_nNumberOfHeaders =0 ;
+ }
+
+ //MAPIUninitialize();
+}
+
+
+HRESULT CallOpenEntry( LPMDB lpMDB, LPADRBOOK lpAB, LPMAPICONTAINER lpContainer, LPMAPISESSION lpMAPISession,
+ ULONG cbEntryID, LPENTRYID lpEntryID, ULONG ulFlags, ULONG* ulObjTypeRet, LPUNKNOWN* lppUnk)
+{
+ if (!lppUnk) return MAPI_E_INVALID_PARAMETER;
+ HRESULT hRes = S_OK;
+ ULONG ulObjType = NULL;
+ LPUNKNOWN lpUnk = NULL;
+ ULONG ulNoCacheFlags = NULL;
+
+ *lppUnk = NULL;
+
+ //ulFlags |= MAPI_NO_CACHE;
+ //in case we need to retry without MAPI_NO_CACHE - do not add MAPI_NO_CACHE to ulFlags after this point
+ //if (MAPI_NO_CACHE & ulFlags) ulNoCacheFlags = ulFlags & ~MAPI_NO_CACHE;
+ ulNoCacheFlags = ulFlags;
+
+ if (lpMDB)
+ {
+ //Log(_T("CallOpenEntry: Calling OpenEntry on MDB with ulFlags = 0x%X\n"),ulFlags);
+ lpMDB->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulFlags,
+ &ulObjType,
+ &lpUnk);
+ if (MAPI_E_UNKNOWN_FLAGS == hRes && ulNoCacheFlags)
+ {
+ hRes = S_OK;
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ (lpMDB->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulNoCacheFlags,
+ &ulObjType,
+ &lpUnk));
+ }
+ if (FAILED(hRes))
+ {
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ }
+ }
+ if (lpAB && !lpUnk)
+ {
+ hRes = S_OK;
+ //Log(_T("CallOpenEntry: Calling OpenEntry on AB with ulFlags = 0x%X\n"),ulFlags);
+ (lpAB->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulFlags,
+ &ulObjType,
+ &lpUnk));
+ if (MAPI_E_UNKNOWN_FLAGS == hRes && ulNoCacheFlags)
+ {
+ hRes = S_OK;
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ (lpAB->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulNoCacheFlags,
+ &ulObjType,
+ &lpUnk));
+ }
+ if (FAILED(hRes))
+ {
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ }
+ }
+
+ if (lpContainer && !lpUnk)
+ {
+ hRes = S_OK;
+ //Log(_T("CallOpenEntry: Calling OpenEntry on Container with ulFlags = 0x%X\n"),ulFlags);
+ (lpContainer->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulFlags,
+ &ulObjType,
+ &lpUnk));
+ if (MAPI_E_UNKNOWN_FLAGS == hRes && ulNoCacheFlags)
+ {
+ hRes = S_OK;
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ (lpContainer->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulNoCacheFlags,
+ &ulObjType,
+ &lpUnk));
+ }
+ if (FAILED(hRes))
+ {
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ }
+ }
+
+ if (lpMAPISession && !lpUnk)
+ {
+ hRes = S_OK;
+ //Log(_T("CallOpenEntry: Calling OpenEntry on Session with ulFlags = 0x%X\n"),ulFlags);
+ (lpMAPISession->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulFlags,
+ &ulObjType,
+ &lpUnk));
+ if (MAPI_E_UNKNOWN_FLAGS == hRes && ulNoCacheFlags)
+ {
+ hRes = S_OK;
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ (lpMAPISession->OpenEntry(
+ cbEntryID,
+ lpEntryID,
+ NULL,//no interface
+ ulNoCacheFlags,
+ &ulObjType,
+ &lpUnk));
+ }
+ if (FAILED(hRes))
+ {
+ if (lpUnk) (lpUnk)->Release();
+ lpUnk = NULL;
+ }
+ }
+
+ if (lpUnk)
+ {
+ //Log(_T("OnOpenEntryID: Got object (0x%08X) of type 0x%08X = %s\n"),lpUnk,ulObjType,ObjectTypeToString(ulObjType));
+ *lppUnk = lpUnk;
+ }
+ if (ulObjTypeRet) *ulObjTypeRet = ulObjType;
+ return hRes;
+}
+
+HRESULT CallOpenEntry( LPMDB lpMDB, LPADRBOOK lpAB, LPMAPICONTAINER lpContainer, LPMAPISESSION lpMAPISession,
+ LPSBinary lpSBinary, ULONG ulFlags, ULONG* ulObjTypeRet, LPUNKNOWN* lppUnk)
+{
+ return CallOpenEntry( lpMDB, lpAB, lpContainer, lpMAPISession, lpSBinary?lpSBinary->cb:0,
+ (LPENTRYID)(lpSBinary?lpSBinary->lpb:0), ulFlags, ulObjTypeRet, lppUnk);
+}
+
+HRESULT CMirandaExchange::InitializeAndLogin( LPCTSTR szUsername, LPCTSTR szPassword, LPCTSTR szExchangeServer )
+{
+ _popupUtil("Connecting to Exchange ...");
+ UINT nSize = 0;
+ short nSizeOfTCHAR = sizeof( TCHAR );
+
+ if ( ( m_szUsername == NULL ) && ( NULL != szUsername ) )
+ {
+ nSize = _tcslen(szUsername);
+ if (nSize>0)
+ {
+ nSize++;
+ m_szUsername = new TCHAR[ nSize ];
+ memset ( m_szUsername, 0, nSize * nSizeOfTCHAR );
+ _tcscpy( m_szUsername, szUsername );
+ }
+ }
+
+ if ( ( m_szPassword == NULL ) && ( NULL != szPassword ) )
+ {
+ nSize = _tcslen( szPassword );
+ if ( nSize>0 )
+ {
+ nSize++;
+ m_szPassword = new TCHAR[ nSize ];
+ memset ( m_szPassword, 0, nSize * nSizeOfTCHAR );
+ _tcscpy( m_szPassword, szPassword );
+ }
+ }
+
+ if ( ( m_szExchangeServer == NULL ) && ( NULL != szExchangeServer ) )
+ {
+ nSize = _tcslen(szExchangeServer);
+ if ( nSize>0 )
+ {
+ nSize++;
+ m_szExchangeServer = new TCHAR[ nSize ];
+ memset ( m_szExchangeServer, 0, nSize * nSizeOfTCHAR );
+ _tcscpy( m_szExchangeServer, szExchangeServer );
+ }
+ }
+
+ if ( !m_bLoginOK || m_lpInbox || NULL == m_lpMAPISession )
+ {
+ HRESULT hr = S_OK;
+ LPMDB lpMDB = NULL;
+ MAPIINIT_0 mapiInit = { MAPI_INIT_VERSION , MAPI_MULTITHREAD_NOTIFICATIONS };
+
+ if( !m_bNoInitAgain)
+ {
+ m_bNoInitAgain = true;
+ hr = MAPIInitialize( &mapiInit) ;
+ }
+
+ if( FAILED(hr) )
+ {
+ //Log("Failed to initialize MAPI\n");
+ }
+ else
+ {
+ TCHAR szPIDandName[128];
+ TCHAR szPID[20];
+
+ _tstrtime( szPID );
+ _tcscpy(szPIDandName,m_szUsername);
+ _tcscat(szPIDandName,szPID );
+
+ hr = CreateProfile( szPIDandName);
+ if ( HR_FAILED(hr ) )
+ {
+ //Log("Create profile failed: 0x%08X", hr);
+ return hr;
+ }
+
+ DWORD dwFlags = MAPI_EXPLICIT_PROFILE|MAPI_EXTENDED|MAPI_NEW_SESSION|MAPI_NO_MAIL ;
+
+ hr = MAPILogonEx( 0, szPIDandName, m_szPassword, dwFlags, &m_lpMAPISession );
+
+ if (FAILED(hr))
+ {
+ //Log( _T("MAPI Logon failed: 0x%08X"), hr );
+ return hr;
+ }
+
+ LPPROFADMIN pProfAdmin = NULL;
+ hr = MAPIAdminProfiles( 0, &pProfAdmin );
+
+ if ((FAILED(hr)) || (NULL == pProfAdmin))
+ {
+ //Log("Admin profile interface creation failed: 0x%08X", hr);
+ }
+ else
+ {
+ hr = pProfAdmin->DeleteProfile( szPIDandName, 0 );
+
+ if ( FAILED(hr) )
+ {
+ //Log( "Failed to delete the profile: 0x%08X", hr );
+ }
+ }
+
+ if (pProfAdmin)
+ {
+ pProfAdmin->Release();
+ }
+
+ ULONG cbDefStoreEid = 0;
+
+ CMAPIBuffer< LPENTRYID> pDefStoreEid = NULL;
+ hr = HrMAPIFindDefaultMsgStore(m_lpMAPISession, &cbDefStoreEid, &pDefStoreEid );
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ // Open default message store
+ LPMDB pDefMsgStore = NULL;
+ hr = m_lpMAPISession->OpenMsgStore(0, cbDefStoreEid, pDefStoreEid, NULL,
+ MAPI_BEST_ACCESS, &pDefMsgStore);
+
+ HRESULT hRes = S_OK;
+ ULONG cbInboxEID = NULL;
+ CMAPIBuffer< LPENTRYID> lpInboxEID = NULL;
+
+ if (NULL == pDefMsgStore )
+ {
+ return hr;
+ }
+
+ hRes = pDefMsgStore->GetReceiveFolder( _T("IPM"), NULL, &cbInboxEID, &lpInboxEID, NULL);
+ m_lpMDB = pDefMsgStore;
+ if (cbInboxEID && lpInboxEID)
+ {
+ hRes = CallOpenEntry( pDefMsgStore, NULL, NULL, NULL, cbInboxEID, lpInboxEID, MAPI_BEST_ACCESS, NULL, (LPUNKNOWN*)&m_lpInbox);
+
+ if ( m_lpInbox && hRes == S_OK)
+ {
+ m_bFolderInboxOK = true;
+ }
+ }
+ }
+ }
+
+ return S_OK;
+}
+
+HRESULT CMirandaExchange::CreateProfile( LPTSTR szProfileName )
+{
+ //TCHAR sz[200];_stprintf(sz, "Create Profile('%s', '%s', '%s')", szProfileName, m_szUsername, m_szExchangeServer);Log(sz);
+
+ HRESULT hr = S_OK;
+ CMAPIInterface<LPPROFADMIN> pProfAdmin = NULL;
+ CMAPIInterface<LPSERVICEADMIN> pMsgSvcAdmin = NULL;
+ CMAPIInterface<LPMAPITABLE> pMsgSvcTable = NULL;
+ LPSRowSet pRows = NULL;
+
+ enum {iSvcName, iSvcUID, cptaSvc};
+
+ SizedSPropTagArray(cptaSvc, sptCols) =
+ {
+ cptaSvc,
+ PR_SERVICE_NAME,
+ PR_SERVICE_UID
+ };
+
+ hr = MAPIAdminProfiles(0, &pProfAdmin);
+
+ if (!(FAILED(hr)) || (pProfAdmin))
+ {
+ hr = pProfAdmin->CreateProfile(szProfileName, NULL, NULL, 0);
+
+ if (!FAILED(hr))
+ {
+ hr = pProfAdmin->AdminServices( szProfileName, NULL, NULL, 0, &pMsgSvcAdmin);
+
+ if ( !(FAILED(hr)) || (pMsgSvcAdmin) )
+ {
+ hr = pMsgSvcAdmin->CreateMsgService((LPTSTR)"MSEMS", (LPTSTR)""/*"Microsoft Exchange Server"*/, NULL, 0);
+
+ if (!FAILED(hr))
+ {
+ hr = pMsgSvcAdmin->GetMsgServiceTable(0, &pMsgSvcTable);
+ if ( !(FAILED(hr)) || ( pMsgSvcTable) )
+ {
+ SRestriction sres;
+ sres.rt = RES_CONTENT;
+ sres.res.resContent.ulFuzzyLevel = FL_FULLSTRING;
+ sres.res.resContent.ulPropTag = PR_SERVICE_NAME_A;
+ SPropValue spv;
+ sres.res.resContent.lpProp = &spv;
+ spv.ulPropTag = PR_SERVICE_NAME_A;
+ spv.Value.lpszA = (LPSTR)"MSEMS";
+
+ hr = HrQueryAllRows(pMsgSvcTable,
+ (LPSPropTagArray) &sptCols,
+ &sres,
+ NULL,
+ 0,
+ &pRows);
+
+ if (!FAILED(hr))
+ {
+ UINT nSize = _tcslen(m_szUsername)+2;
+
+ TCHAR* szUniqName = new TCHAR[nSize];
+
+ memset( szUniqName, 0, nSize*sizeof(TCHAR) );
+ _tcscpy( szUniqName,_T("="));
+ _tcscat( szUniqName, m_szUsername);
+
+ // Set values for PR_PROFILE_UNRESOLVED_NAME and PR_PROFILE_UNRESOLVED_SERVER
+ SPropValue spval[2];
+ spval[0].ulPropTag = PR_PROFILE_UNRESOLVED_NAME;
+ spval[0].Value.lpszA = mir_t2a(szUniqName);
+ spval[1].ulPropTag = PR_PROFILE_UNRESOLVED_SERVER;
+ spval[1].Value.lpszA = mir_t2a(m_szExchangeServer);
+
+
+ // Configure msg service
+ /*hr =*/ pMsgSvcAdmin->ConfigureMsgService(
+ (LPMAPIUID) pRows->aRow->lpProps[iSvcUID].Value.bin.lpb,
+ 0, NULL, 2, spval);
+
+ if (NULL!=szUniqName)
+ {
+ delete[] szUniqName;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ pProfAdmin->DeleteProfile(szProfileName, 0);
+ }
+ }
+
+ if (pRows)
+ {
+ FreeProws(pRows);
+ }
+
+ return hr;
+}
+
+HRESULT CMirandaExchange::isMapiSessionOK( LPMAPISESSION lpSession )
+{
+ return S_OK;
+}
+
+HRESULT CMirandaExchange::CheckForNewMails( int &nNewMails)
+{
+ HRESULT hRes;
+ if ( m_nNumberOfHeaders>0 && NULL != m_HeadersKeeper )
+ {
+ for( UINT i=0; i<m_nNumberOfHeaders; i++ )
+ {
+ if ( NULL != m_HeadersKeeper[i])
+ {
+ delete m_HeadersKeeper[i];
+ m_HeadersKeeper[i] = NULL;
+ }
+ }
+
+ m_nNumberOfHeaders =0 ;
+ }
+
+ m_nNumberOfHeaders = 0;
+
+ try
+ {
+ if ( m_lpMAPISession != NULL && (isMapiSessionOK(m_lpMAPISession)== S_OK) && m_lpInbox != NULL && m_bFolderInboxOK )
+ {
+ hRes= CheckInFolder( m_lpInbox );
+ }
+ else
+ {
+ m_bLoginOK = 0;
+ hRes = InitializeAndLogin(NULL,NULL,NULL);
+
+ if (hRes == S_OK)
+ {
+ hRes = CheckInFolder( m_lpInbox );
+ }
+ }
+
+ if (hRes == S_OK)
+ {
+ nNewMails = m_nNumberOfHeaders;
+ }
+ }
+ catch (...)
+ {
+
+ }
+
+ return hRes;
+}
+
+HRESULT CMirandaExchange::LogOFF()
+{
+ try
+ {
+ if (NULL != m_lpInbox)
+ {
+ UlRelease(m_lpInbox);
+ m_lpInbox = NULL;
+ }
+
+ if (NULL != m_lpMDB)
+ {
+ UlRelease(m_lpMDB);
+ m_lpMDB = NULL;
+ }
+
+ if( NULL!= m_lpMAPISession )
+ {
+ m_lpMAPISession->Logoff( NULL, NULL, NULL );
+ m_lpMAPISession->Release();
+ m_lpMAPISession = NULL;
+ }
+
+ if ( m_nNumberOfHeaders>0 && NULL != m_HeadersKeeper )
+ {
+ for( UINT i=0; i<m_nNumberOfHeaders; i++ )
+ {
+ if ( NULL != m_HeadersKeeper[i])
+ {
+ delete m_HeadersKeeper[i];
+ m_HeadersKeeper[i] = NULL;
+ }
+ }
+
+ m_nNumberOfHeaders =0 ;
+ }
+ }
+ catch (...)
+ {
+
+ }
+
+ return S_OK;
+}
+
+HRESULT CMirandaExchange::MarkAsRead( LPTSTR szEntryID )
+{
+ LPMESSAGE lpMessage = NULL ;
+
+ SizedSPropTagArray(3,sptaFlags) =
+ {
+ 3,
+ { PR_ENTRYID ,
+ PR_MESSAGE_FLAGS,
+ PR_SENDER_NAME
+ }
+ };
+
+ LPBYTE lpData = NULL ;
+ ULONG ulC = 0 ;
+
+ HexToBin(szEntryID, ulC, lpData);
+
+ HRESULT hr = CallOpenEntry( m_lpMDB, NULL, NULL, m_lpMAPISession, ulC, (LPENTRYID) lpData, MAPI_BEST_ACCESS, NULL, (LPUNKNOWN*)&lpMessage);
+ if (NULL != lpData)
+ {
+ delete lpData;
+ }
+
+ if ( NULL != lpMessage)
+ {
+ hr = lpMessage->SetReadFlag( 0 );
+ hr = lpMessage->SaveChanges(FORCE_SAVE);
+
+ lpMessage->Release();
+ lpMessage = NULL;
+ }
+
+ return 0;
+}
+
+
+HRESULT CMirandaExchange::CheckInFolder( LPMAPIFOLDER lpFolder )
+{
+ HRESULT hr = NOERROR;
+
+ if ( lpFolder != NULL && m_bFolderInboxOK )
+ {
+
+ CMAPIInterface<LPMAPITABLE> lpTable = NULL ;
+ LPSRowSet lpRow = NULL ;
+ LPSPropValue lpRowProp = NULL ;
+ ULONG i = 0L ;
+ ULONG *lpcbeid = 0 ;
+
+ SizedSPropTagArray(5,sptaDETAILS) =
+ {
+ 5,
+ {
+ PR_ENTRYID,
+ PR_MESSAGE_FLAGS,
+ PR_SENDER_NAME,
+ PR_ORIGINAL_SENDER_EMAIL_ADDRESS,
+ PR_SUBJECT
+ }
+ };
+
+ CMAPIInterface<LPMAPITABLE> lpMessageTable;
+
+ hr = lpFolder->GetContentsTable( 0, &lpMessageTable );
+ if( HR_FAILED( hr ) )
+ {
+ return -1;
+ }
+
+ LPSRowSet lpRowsR = NULL;
+
+ //////////////////////////////////////////////////////////////////////////
+ SRestriction srRoot;
+ srRoot.rt = RES_BITMASK;
+ srRoot.res.resBitMask.relBMR = BMR_EQZ;
+ srRoot.res.resBitMask.ulPropTag = PR_MESSAGE_FLAGS;
+ srRoot.res.resBitMask.ulMask = MSGFLAG_READ;
+
+ SizedSSortOrderSet( 1, sso ) = { 1, 0, 0, { PR_MESSAGE_DELIVERY_TIME, TABLE_SORT_DESCEND } };
+
+ hr = HrQueryAllRows( lpMessageTable, (LPSPropTagArray) &sptaDETAILS,&srRoot,(LPSSortOrderSet) & sso,0L, &lpRowsR );
+
+ //////////////////////////////////////////////////////////////////////////
+
+ if( HR_FAILED( hr ) )
+ {
+ return -1;
+ }
+ else
+ {
+ TCHAR* szSenderName = NULL;
+ TCHAR* szSubject = NULL;
+ LPSTR szEntryID = NULL;
+
+ for( i = 0; ( i < lpRowsR->cRows) && ( m_nNumberOfHeaders < MAX_NUMBER_OF_HEADERS ); ++i )
+ {
+ if ( !(lpRowsR->aRow[ i ].lpProps[ 1 ].Value.l & MSGFLAG_READ) )
+ {
+
+ if( !FAILED(lpRowsR->aRow[i].lpProps[2].Value.err) )
+ {
+ szSenderName = lpRowsR->aRow[i].lpProps[2].Value.lpszW;
+ }
+
+ if ( NULL == szSenderName)
+ {
+ if( !FAILED(lpRowsR->aRow[i].lpProps[3].Value.err))
+ {
+ szSenderName = lpRowsR->aRow[i].lpProps[3].Value.lpszW;
+ }
+ }
+
+
+ if( !FAILED(lpRowsR->aRow[i].lpProps[4].Value.err) )
+ {
+ szSubject = lpRowsR->aRow[i].lpProps[4].Value.lpszW;
+ }
+
+ szEntryID = BinToHex( lpRowsR->aRow[i].lpProps[0].Value.bin.cb, lpRowsR->aRow[i].lpProps[0].Value.bin.lpb );
+ m_HeadersKeeper[m_nNumberOfHeaders] = new CKeeper( szSenderName, szSubject, szEntryID );
+ m_nNumberOfHeaders++;
+
+ delete[] szEntryID;
+
+ szEntryID = NULL;
+ szSubject = NULL;
+ szSenderName = NULL;
+ }
+ }
+
+ if (lpRowsR)
+ {
+ FreeProws(lpRowsR);
+ }
+ }
+
+ if (m_nNumberOfHeaders<MAX_NUMBER_OF_HEADERS)
+ {
+ const enum {IDISPNAME, IENTRYID, ICHILDCOUNT};
+
+ static SizedSPropTagArray ( 3, rgColProps) =
+ {
+ 3,
+ {
+ PR_DISPLAY_NAME_A,
+ PR_ENTRYID,
+ PR_FOLDER_CHILD_COUNT
+ }
+ };
+
+ ULONG ulObjType = 0L;
+
+ hr = MAPICALL( lpFolder)->GetHierarchyTable( MAPI_DEFERRED_ERRORS, &lpTable);
+ if (!FAILED(hr))
+ {
+ hr = HrQueryAllRows( lpTable, (LPSPropTagArray)&rgColProps, NULL, NULL, 0L, &lpRow);
+ if (!FAILED(hr))
+ {
+ for(i = 0; i < lpRow->cRows; i++)
+ {
+ lpRowProp = lpRow->aRow[i].lpProps;
+ CMAPIInterface<LPMAPIFOLDER> lpSubFolder = NULL;
+ hr = CallOpenEntry( m_lpMDB, NULL, NULL, NULL, lpRowProp[IENTRYID].Value.bin.cb, (LPENTRYID)lpRowProp[IENTRYID].Value.bin.lpb, MAPI_BEST_ACCESS, NULL, (LPUNKNOWN*)&lpSubFolder );
+ if( !FAILED(hr) )
+ {
+ hr = CheckInFolder( lpSubFolder );
+ //if (FAILED(hr) ){//Log("failed checkinfolder for %s\n",lpRowProp[IDISPNAME].Value.lpszA );}
+ }
+ }
+ }
+
+ if (NULL != lpRow)
+ {
+ FreeProws(lpRow);
+ lpRow = NULL;
+ }
+ }
+ }
+ }
+
+ return hr;
+}
+
+HRESULT CMirandaExchange::OpenTheMessage( LPTSTR szEntryID )
+{
+ //(Default)//// HKEY_CLASSES_ROOT\mailto\shell\open\command
+ HKEY hTheKey;
+ HRESULT hRes = E_FAIL;
+
+ TCHAR szRegValue[ 512 ];
+ DWORD dwLength = 512 ;
+ DWORD dwType = REG_SZ;
+
+ if( RegOpenKeyEx(HKEY_CLASSES_ROOT,
+ _T("mailto\\shell\\open\\command"),
+ 0,
+ KEY_ALL_ACCESS | KEY_EXECUTE | KEY_QUERY_VALUE ,
+ &hTheKey) == ERROR_SUCCESS
+ )
+ {
+ LONG lResult = RegQueryValueEx( hTheKey, NULL, NULL, (LPDWORD)&dwType, (LPBYTE)szRegValue, &dwLength);
+ RegCloseKey( hTheKey );
+
+ if( lResult != ERROR_SUCCESS )
+ {
+ hRes = E_FAIL;
+ }
+ else
+ {
+
+ TCHAR* szTheEnd = _tcsstr( szRegValue,_T(".EXE") );
+
+ if( NULL != szTheEnd )
+ {
+ szRegValue[ _tcslen(szRegValue) - _tcslen(szTheEnd) +5 ] = _T('\0');
+ _tcscat( szRegValue, _T(" /recycle") );
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+
+ DWORD dwCode = 0;
+
+ ZeroMemory ( &si, sizeof ( STARTUPINFO));
+
+ si.cb = sizeof ( STARTUPINFO);
+ si.dwFlags = STARTF_USESHOWWINDOW;
+ si.wShowWindow = SW_SHOWNORMAL;
+
+ if( CreateProcess ( NULL,
+ szRegValue,
+ NULL,
+ NULL,
+ 0,
+ NORMAL_PRIORITY_CLASS,
+ NULL,
+ NULL,
+ &si,
+ &pi
+ ))
+ {
+ hRes = S_OK;
+ }
+ }
+ }
+ }
+ else
+ {
+ hRes = E_FAIL;
+ }
+
+ return hRes;
+
+}
+#endif //NO_EXCHANGE_TEST \ No newline at end of file
diff --git a/plugins/Exchange/src/MirandaExchange.h b/plugins/Exchange/src/MirandaExchange.h
new file mode 100644
index 0000000000..47f76d2107
--- /dev/null
+++ b/plugins/Exchange/src/MirandaExchange.h
@@ -0,0 +1,241 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+/********************************************************************
+ created: 2006/04/11
+ created: 11:4:2006 17:27
+ filename: MirandaExchange.h
+ file base: MirandaExchange
+ file ext: h
+ author: Attila Vajda
+
+ purpose: Miranda Exchange Plugin
+*********************************************************************/
+
+//define if you want to test only the miranda part, and not the exchange one.
+//#define NO_EXCHANGE_TEST
+
+#ifndef NO_EXCHANGE_TEST
+
+#if !defined(MIRANDAEXCHANGE_H__INCLUDED_)
+#define MIRANDAEXCHANGE_H__INCLUDED_
+
+#undef _DEBUG
+#undef DEBUG
+
+#include <mapix.h>
+#include <mapival.h>
+
+#define _DEBUG
+#define DEBUG
+
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#define MAX_NUMBER_OF_HEADERS 512
+
+#if !defined(__cplusplus) || defined(CINTERFACE)
+#define MAPICALL(x) (x)->lpVtbl
+#else
+#define MAPICALL(x) (x)
+#endif
+
+#define FREEPROWS(x) \
+{ \
+ FreeProws((x)); \
+ (x) = NULL; \
+}
+
+
+#define pidFolderMin 0x6638
+#define pidProfileMin 0x6600
+#define PR_PROFILE_UNRESOLVED_NAME PROP_TAG( PT_STRING8, pidProfileMin+0x07)
+#define PR_PROFILE_UNRESOLVED_SERVER PROP_TAG( PT_STRING8, pidProfileMin+0x08)
+#define PR_FOLDER_CHILD_COUNT PROP_TAG( PT_LONG, pidFolderMin)
+
+// -----------------------------------------------------------------------------
+// Helpers.h: Template Class that wraps MAPI buffers or interfaces so that you
+// don't have to concern yourself with freeing or releasing them.
+//
+// Copyright (C) Microsoft Corp. 1986 - 2000. All Rights Reserved.
+// -----------------------------------------------------------------------------
+
+#ifndef _HELPERS_H_
+#define _HELPERS_H_
+
+// -----------------------------------------------------------------------------
+// Use this class to wrap a pointer to a mapi buffer. It will automaticly get
+// freed when it goes out of scope. Use the instance of this just as you would
+// its base type. Example:
+// CMAPIBuffer< LPENTRYID> lpeid;
+// HRESULT hr = HrMAPIFindDefaultMsgStore( m_pMAPISession, &cbeid, &lpeid);
+// hr = m_pMAPISession->OpenMsgStore( 0, cbeid, lpeid, ...
+//
+// The intended use of this class is for declaring mapi buffer pointers on the
+// stack or inside of another class or structure. There is NO value in creating
+// an instance of this class on the heap with new(). It's sole purpose in life
+// is to keep you from having to remember to free the buffer.
+//
+// If you need to reuse the pointer be sure to call MAPIFREEBUFFER before
+// reusing it. Example:
+// CMAPIBuffer< LPENTRYID> lpeid;
+// HRESULT hr = HrMAPIFindDefaultMsgStore( m_pMAPISession, &cbeid, &lpeid);
+// ... // Do some other work...
+// MAPIFREEBUFFER( lpeid);
+// hr = HrGetSomeOtherEID( &cbeid, &lpeid);
+// -----------------------------------------------------------------------------
+
+template< class TYPE>
+class CMAPIBuffer
+{
+public:
+ CMAPIBuffer( TYPE ptr = NULL) { m_ptr = ptr;}
+ ~CMAPIBuffer() { MAPIFREEBUFFER( m_ptr);}
+
+ // Returns a pointer to the TYPE by just specifying the object.
+ operator TYPE() {return( m_ptr);}
+
+ // Returns the address of the object correct for the base type.
+ TYPE* operator &() {return( &m_ptr);}
+
+ void operator =(LPVOID lpv) {m_ptr = (TYPE) lpv;}
+
+protected:
+ TYPE m_ptr;
+};
+
+// -----------------------------------------------------------------------------
+// Use this class to wrap a pointer to a mapi interface. It is nearly identical
+// to the above class except that it releases the interface pointer when the
+// instance of the object goes out of scope.
+//
+// The intended use of this class is for declaring mapi interface pointers on the
+// stack or inside of another class or structure. There is NO value in creating
+// an instance of this class on the heap with new(). It's sole purpose in life
+// is to keep you from having to remember to release the interface.
+// -----------------------------------------------------------------------------
+
+template< class TYPE>
+class CMAPIInterface
+{
+public:
+ CMAPIInterface( TYPE ptr = NULL) { m_ptr = ptr;}
+ ~CMAPIInterface() { UlRelease( m_ptr);}
+
+ // Returns a pointer to the TYPE by just specifying the object.
+ operator TYPE() {return( m_ptr);}
+
+ // Returns the address of the object correct for the base type.
+ TYPE* operator &() {return( &m_ptr);}
+
+ // Returns a pointer to the TYPE for -> operations.
+ TYPE operator ->() {return( m_ptr);}
+
+ void operator =(LPVOID lpv) {m_ptr = (TYPE) lpv;}
+
+protected:
+ TYPE m_ptr;
+};
+
+// $--CMAPIIsInitialized--------------------------------------------------------
+// Initialize MAPI using MAPIInitialize(). If it is successful then create an
+// instance of this object which will uninitialize MAPI at destruction.
+// -----------------------------------------------------------------------------
+
+class CMAPIIsInitialized
+{
+public:
+ ~CMAPIIsInitialized() {MAPIUninitialize();}
+};
+
+// $--CMAPISession--------------------------------------------------------------
+// Works just like CMAPIInterface but it also Logs off at destruction.
+// -----------------------------------------------------------------------------
+
+class CMAPISession : public CMAPIInterface< LPMAPISESSION>
+{
+public:
+ // DESTRUCTOR logs off of the MAPI session and releases the session handle.
+ ~CMAPISession()
+ {
+ if( m_ptr)
+ m_ptr->Logoff( 0L, 0L, 0L);
+ }
+};
+
+// -----------------------------------------------------------------------------
+
+#endif // _HELPERS_H_
+
+class CKeeper
+{
+public:
+ CKeeper ( LPTSTR szSender, LPTSTR szSubject, LPSTR szEntryID );
+ ~CKeeper ();
+
+public:
+ UINT m_nSizeSender ;
+ UINT m_nSizeSubject;
+ UINT m_nSizeEntryID;
+
+ LPTSTR m_szSender ;
+ LPTSTR m_szSubject ;
+ LPSTR m_szEntryID ;
+};
+
+
+class CMirandaExchange
+{
+public:
+
+ CMirandaExchange();
+ //CMirandaExchange ( LPCTSTR szUsername, LPCTSTR szPassword, LPCTSTR szExchangeServer );
+ virtual ~CMirandaExchange ();
+
+ HRESULT CheckForNewMails ( int &nNewMails );
+ HRESULT CreateProfile ( LPTSTR szProcessID );
+ HRESULT InitializeAndLogin ( LPCTSTR szUsername, LPCTSTR szPassword, LPCTSTR szExchangeServer );
+ HRESULT CheckInFolder ( LPMAPIFOLDER lpFolder );
+ HRESULT MarkAsRead ( LPTSTR szEntryID );
+ HRESULT LogOFF ();
+ HRESULT OpenTheMessage ( LPTSTR szEntryID );
+ HRESULT isMapiSessionOK ( LPMAPISESSION lpSession );
+ CKeeper* m_HeadersKeeper[MAX_NUMBER_OF_HEADERS+1];
+
+private:
+ LPTSTR m_szUsername;
+ LPTSTR m_szPassword;
+ LPTSTR m_szExchangeServer;
+ LPMAPISESSION m_lpMAPISession;
+ LPMAPIFOLDER m_lpInbox;
+ LPMDB m_lpMDB;
+ bool m_bLoginOK;
+ bool m_bFolderInboxOK;
+
+ bool m_bNoInitAgain;
+ UINT m_nNumberOfHeaders;
+ CRITICAL_SECTION m_myCritical;
+
+};
+
+#endif // !defined(MIRANDAEXCHANGE_H__INCLUDED_)
+#endif //NO_EXCHANGE_TEST
diff --git a/plugins/Exchange/src/StdAfx.cpp b/plugins/Exchange/src/StdAfx.cpp
new file mode 100644
index 0000000000..4e991b8f0d
--- /dev/null
+++ b/plugins/Exchange/src/StdAfx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// exchange.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/plugins/Exchange/src/StdAfx.h b/plugins/Exchange/src/StdAfx.h
new file mode 100644
index 0000000000..82627ab92d
--- /dev/null
+++ b/plugins/Exchange/src/StdAfx.h
@@ -0,0 +1,24 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__B170AF8E_BA64_4233_BF83_B4F0D1F3B775__INCLUDED_)
+#define AFX_STDAFX_H__B170AF8E_BA64_4233_BF83_B4F0D1F3B775__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// Insert your headers here
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+#include <windows.h>
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__B170AF8E_BA64_4233_BF83_B4F0D1F3B775__INCLUDED_)
diff --git a/plugins/Exchange/src/commonheaders.h b/plugins/Exchange/src/commonheaders.h
new file mode 100644
index 0000000000..bbfdcc9b59
--- /dev/null
+++ b/plugins/Exchange/src/commonheaders.h
@@ -0,0 +1,71 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+#ifndef M_EXCHANGE_COMMONHEADERS_H
+#define M_EXCHANGE_COMMONHEADERS_H
+#if !defined(MIID_EXCHANGE)
+ #define MIID_EXCHANGE {0xcfd79a89, 0x9959, 0x4e65, {0xb0, 0x76, 0x41, 0x3f, 0x98, 0xfe, 0x0d, 0x15}}
+#endif
+
+#define EXCHANGE_PORT 25
+#define DEFAULT_INTERVAL 60 //in seconds
+#define DEFAULT_RECONNECT_INTERVAL 10 //in minutes
+
+#include <windows.h>
+//#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "resource.h"
+
+#include "version.h"
+#include "utils.h"
+#include "emails.h"
+#include "services.h"
+#include "hooked_events.h"
+//#include "mirandaMem.h"
+
+//#include "forkthread.h"
+
+#include <newpluginapi.h>
+#include <m_core.h>
+#include <m_popup.h>
+#include <m_database.h>
+#include <m_system.h>
+//#include "m_skin.h"
+#include <m_options.h>
+#include <m_clist.h>
+#include <m_langpack.h>
+//#include "m_history.h"
+//#include "m_contacts.h"
+//#include "m_fontservice.h"
+
+#include "m_utils.h"
+
+//#include "m_updater.h"
+
+extern char ModuleName[];
+extern HINSTANCE hInstance;
+extern HICON hiMailIcon;
+extern HWND hEmailsDlg;
+
+
+
+#endif //M_EXCHANGE_COMMONHEADERS_H \ No newline at end of file
diff --git a/plugins/Exchange/src/dlg_handlers.cpp b/plugins/Exchange/src/dlg_handlers.cpp
new file mode 100644
index 0000000000..1e291b9ce5
--- /dev/null
+++ b/plugins/Exchange/src/dlg_handlers.cpp
@@ -0,0 +1,514 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "dlg_handlers.h"
+
+#define MIN_EMAILS_WIDTH 300
+#define MIN_EMAILS_HEIGHT 250
+
+static WNDPROC OldListProc;
+
+BOOL CALLBACK DlgProcOptions(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int bInitializing; //true when dialog is being created
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TCHAR buffer[4096];
+ long port;
+ long interval;
+ int bCheck;
+ int portCheck;
+ int retries;
+ bInitializing = 1;
+ DBVARIANT dbv = {0};
+
+
+ dbv.type = DBVT_ASCIIZ;
+
+ TranslateDialogDefault(hWnd);
+
+ bCheck = db_get_b(NULL, ModuleName, "Check", 1);
+ GetStringFromDatabase("Username", _T(""), buffer, sizeof(buffer));
+ SetWindowText(GetDlgItem(hWnd, IDC_USER_EDIT), buffer);
+ GetStringFromDatabase("Password", _T(""), buffer, sizeof(buffer));
+ CallService(MS_DB_CRYPT_DECODESTRING, sizeof(buffer), (LPARAM) buffer);
+ SetWindowText(GetDlgItem(hWnd, IDC_PASSWORD_EDIT), buffer);
+ GetStringFromDatabase("Server", _T(""), buffer, sizeof(buffer));
+ SetWindowText(GetDlgItem(hWnd, IDC_SERVER_EDIT), buffer);
+
+ port = db_get_dw(NULL, ModuleName, "Port", EXCHANGE_PORT);
+ //_itoa(port, buffer, 10);
+ //SetWindowText(GetDlgItem(hWnd, IDC_PORT_EDIT), buffer);
+ SetDlgItemInt(hWnd,IDC_PORT_EDIT,port,FALSE);
+
+ interval = db_get_dw(NULL, ModuleName, "Interval", DEFAULT_INTERVAL);
+ //_itoa(interval, buffer, 10);
+ //SetWindowText(GetDlgItem(hWnd, IDC_INTERVAL_EDIT), buffer);
+ SetDlgItemInt(hWnd,IDC_INTERVAL_EDIT,interval,FALSE);
+
+ CheckDlgButton(hWnd, IDC_RECONNECT, (db_get_b(NULL, ModuleName, "Reconnect", 0)) ? BST_CHECKED : BST_UNCHECKED);
+
+ interval = db_get_dw(NULL, ModuleName, "ReconnectInterval", DEFAULT_RECONNECT_INTERVAL);
+ //_itoa(interval, buffer, 10);
+ //SetWindowText(GetDlgItem(hWnd, IDC_RECONNECT_INTERVAL), buffer);
+ SetDlgItemInt(hWnd,IDC_RECONNECT_INTERVAL,interval,FALSE);
+ CheckDlgButton(hWnd, IDC_USE_POPUPS, (BOOL) db_get_b(NULL, ModuleName, "UsePopups", 0) ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hWnd, IDC_USE_POPUPS), ServiceExists(MS_POPUP_ADDPOPUP)); //disable the popups checkbox if no popup module is present
+
+ CheckDlgButton(hWnd, IDC_CHECK_EMAILS, (bCheck) ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hWnd, IDC_INTERVAL_EDIT), bCheck);
+
+ portCheck = (BOOL) db_get_b(NULL, ModuleName, "UsePortCheck", 1);
+ CheckDlgButton(hWnd, IDC_USE_PORTCHECK, (portCheck) ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hWnd, IDC_PORT_EDIT), portCheck);
+
+ //_itoa(db_get_b(NULL, ModuleName, "MaxRetries", MAX_EXCHANGE_CONNECT_RETRIES), buffer, 10);
+ //SetWindowText(GetDlgItem(hWnd, IDC_MAX_RETRIES), buffer);
+ retries=db_get_b(NULL, ModuleName, "MaxRetries", MAX_EXCHANGE_CONNECT_RETRIES);
+ SetDlgItemInt(hWnd,IDC_MAX_RETRIES,retries,FALSE);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_RECONNECT_INTERVAL), IsDlgButtonChecked(hWnd, IDC_RECONNECT));
+
+ bInitializing = 0;
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_USER_EDIT:
+ case IDC_PASSWORD_EDIT:
+ case IDC_SERVER_EDIT:
+ case IDC_PORT_EDIT:
+ case IDC_INTERVAL_EDIT:
+ case IDC_RECONNECT_INTERVAL:
+ case IDC_MAX_RETRIES:
+ {
+ if ((!bInitializing) && (HIWORD(wParam) == EN_CHANGE))// || (HIWORD(wParam) == CBN_SELENDOK))
+ {
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+ }
+
+ break;
+ }
+ case IDC_USE_POPUPS:
+ case IDC_CHECK_EMAILS:
+ case IDC_RECONNECT:
+ case IDC_USE_PORTCHECK:
+ {
+ int portCheck = IsDlgButtonChecked(hWnd, IDC_USE_PORTCHECK);
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+
+ EnableWindow(GetDlgItem(hWnd, IDC_INTERVAL_EDIT), IsDlgButtonChecked(hWnd, IDC_CHECK_EMAILS));
+ EnableWindow(GetDlgItem(hWnd, IDC_RECONNECT_INTERVAL), IsDlgButtonChecked(hWnd, IDC_RECONNECT));
+ EnableWindow(GetDlgItem(hWnd, IDC_PORT_EDIT), portCheck);
+ //EnableWindow(GetDlgItem(hWnd, IDC_MAX_RETRIES), portCheck);
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ TCHAR buffer[4096];
+ long port = 0;
+ long interval = DEFAULT_INTERVAL;
+ int bCheck = IsDlgButtonChecked(hWnd, IDC_CHECK_EMAILS);
+ int retries = MAX_EXCHANGE_CONNECT_RETRIES;
+
+ db_set_b(NULL, ModuleName, "Check", bCheck);
+ GetWindowText(GetDlgItem(hWnd, IDC_USER_EDIT), buffer, sizeof(buffer));
+ db_set_ts(NULL, ModuleName, "Username", buffer);
+ GetWindowText(GetDlgItem(hWnd, IDC_PASSWORD_EDIT), buffer, sizeof(buffer));
+ CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buffer), (LPARAM) buffer);
+ db_set_ts(NULL, ModuleName, "Password", buffer);
+ GetWindowText(GetDlgItem(hWnd, IDC_SERVER_EDIT), buffer, sizeof(buffer));
+ db_set_ts(NULL, ModuleName, "Server", buffer);
+ GetWindowText(GetDlgItem(hWnd, IDC_PORT_EDIT), buffer, sizeof(buffer));
+ //port = atoi(buffer);
+ //db_set_dw(NULL, ModuleName, "Port", port);
+ db_set_dw(NULL, ModuleName, "Port", GetDlgItemInt(hWnd,IDC_PORT_EDIT,NULL,FALSE));
+
+ //GetWindowText(GetDlgItem(hWnd, IDC_INTERVAL_EDIT), buffer, sizeof(buffer));
+ //interval = atoi(buffer);
+ interval=GetDlgItemInt(hWnd,IDC_INTERVAL_EDIT,NULL,FALSE);
+ db_set_dw(NULL, ModuleName, "Interval", interval);
+
+ db_set_b(NULL, ModuleName, "Reconnect", IsDlgButtonChecked(hWnd, IDC_RECONNECT));
+
+ GetWindowText(GetDlgItem(hWnd, IDC_RECONNECT_INTERVAL), buffer, sizeof(buffer));
+ //interval = atoi(buffer);
+ interval=GetDlgItemInt(hWnd,IDC_RECONNECT_INTERVAL,NULL,FALSE);
+ db_set_dw(NULL, ModuleName, "ReconnectInterval", interval);
+
+ db_set_b(NULL, ModuleName, "UsePopups", IsDlgButtonChecked(hWnd, IDC_USE_POPUPS));
+ db_set_b(NULL, ModuleName, "UsePortCheck", IsDlgButtonChecked(hWnd, IDC_USE_PORTCHECK));
+
+ //GetWindowText(GetDlgItem(hWnd, IDC_MAX_RETRIES), buffer, sizeof(buffer));
+ //retries = atoi(buffer);
+ retries=GetDlgItemInt(hWnd,IDC_MAX_RETRIES,NULL,FALSE);
+ db_set_b(NULL, ModuleName, "MaxRetries", retries);
+
+
+ exchangeServer.Reconnect(); //login info may be changed
+ UpdateTimers(); //interval might get changed
+
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+#include "commctrl.h"
+
+void AddAnchorWindowToDeferList(HDWP &hdWnds, HWND window, RECT *rParent, WINDOWPOS *wndPos, int anchors)
+{
+ RECT rChild = AnchorCalcPos(window, rParent, wndPos, anchors);
+ hdWnds = DeferWindowPos(hdWnds, window, HWND_NOTOPMOST, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, SWP_NOZORDER);
+}
+
+void SavePosition(HWND hWnd)
+{
+ RECT rWnd;
+ GetWindowRect(hWnd, &rWnd);
+ db_set_dw(0, ModuleName, "PosX", rWnd.left);
+ db_set_dw(0, ModuleName, "PosY", rWnd.top);
+ //DBWriteContactSettingDword(0, ModuleName, "Width", rWnd.right - rWnd.left);
+ //DBWriteContactSettingDword(0, ModuleName, "Height", rWnd.bottom - rWnd.top);
+}
+
+void LoadPosition(HWND hWnd)
+{
+ int x, y;
+ int width = 500, height = 300;
+ x = db_get_dw(0, ModuleName, "PosX", 0);
+ y = db_get_dw(0, ModuleName, "PosY", 0);
+ //width = DBGetContactSettingDword(0, ModuleName, "Width", 500);
+ //height = DBGetContactSettingDword(0, ModuleName, "Height", 300);
+ SetWindowPos(hWnd, NULL, x, y, width, height, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSIZE);
+}
+
+int CALLBACK ListSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_KEYUP:
+ {
+ if (wParam == VK_ESCAPE)
+ {
+ SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_SYSKEYDOWN:
+ {
+ if (wParam == 'X')
+ {
+ SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_LBUTTONDBLCLK:
+ {
+ int i;
+ int count = ListView_GetItemCount(hWnd);
+ for (i = 0; i < count; i++)
+ {
+ if (ListView_GetItemState(hWnd, i, LVIS_SELECTED))
+ {
+ TCHAR emailID[4096]; //uhh
+ ListView_GetItemText(hWnd, i, 2, emailID, sizeof(emailID));
+ exchangeServer.OpenMessage(emailID);
+ }
+ }
+
+ break;
+ }
+ }
+
+ return CallWindowProc(OldListProc, hWnd, msg, wParam, lParam);
+}
+
+BOOL CALLBACK DlgProcEmails(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hWnd);
+
+ SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hiMailIcon);
+
+ LVCOLUMN col = {0};
+ HWND hList = GetDlgItem(hWnd, IDC_EMAILS_LIST);
+ OldListProc = (WNDPROC) SetWindowLong(hList, GWLP_WNDPROC, (LONG) ListSubclassProc);
+ ListView_SetExtendedListViewStyle(hList, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES);
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.cx = 100;
+ col.pszText = TranslateT("Entry ID");
+ col.cchTextMax = _tcslen(col.pszText) + 1;
+ ListView_InsertColumn(hList, 0, &col);
+ col.pszText = TranslateT("Subject");
+ col.cx = 300;
+ col.cchTextMax = _tcslen(col.pszText) + 1;
+ ListView_InsertColumn(hList, 0, &col);
+ col.cx = 200;
+ col.iSubItem = 1;
+ col.pszText = TranslateT("Sender");
+ col.cchTextMax = _tcslen(col.pszText) + 1;
+ ListView_InsertColumn(hList, 0, &col);
+
+ //LoadPosition(hWnd);
+
+ return TRUE;
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ hEmailsDlg = NULL;
+
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ //ShowWindow(hWnd, SW_HIDE);
+ DestroyWindow(hWnd); //close the window - no need to keep it in memory
+ //SavePosition(hWnd);
+
+ break;
+ }
+
+ case EXM_UPDATE_EMAILS:
+ {
+ HWND hList = GetDlgItem(hWnd, IDC_EMAILS_LIST);
+ ListView_DeleteAllItems(hList);
+ int i;
+ int count = GetWindowLong(hWnd, GWLP_USERDATA);
+ LVITEM item = {0};
+ TEmailHeader email = {0};
+ email.cbSize = sizeof(TEmailHeader);
+ TCHAR sender[1024] = _T("");
+ TCHAR subject[1024] = _T("");
+ //char buffer[4096];
+ email.cSender = sizeof(sender);
+ email.cSubject = sizeof(subject);
+ email.szSender = sender;
+ email.szSubject = subject;
+ item.mask = LVIF_TEXT;
+
+ for (i = 0; i < count; i++)
+ {
+ exchangeServer.GetEmailHeader(i, &email);
+ item.iItem = i;
+ item.iSubItem = 0;
+ item.pszText = email.szSender;
+ ListView_InsertItem(hList, &item);
+ ListView_SetItemText(hList, i, 1, email.szSubject);
+ ListView_SetItemText(hList, i, 2, mir_a2t(email.emailID));
+ }
+ SetFocus(hList);
+
+ break;
+ }
+
+ case WM_SHOWWINDOW:
+ {
+ if (wParam)
+ {
+ SendMessage(hWnd, EXM_UPDATE_EMAILS, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_KEYUP:
+ {
+ if (wParam == VK_ESCAPE)
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_SYSKEYDOWN:
+ {
+ if (wParam == 'X')
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_WINDOWPOSCHANGING:
+ {
+ HDWP hdWnds = BeginDeferWindowPos(3);
+ RECT rParent;
+ WINDOWPOS *wndPos = (WINDOWPOS *) lParam;
+
+ if ((!wndPos) || (wndPos->flags & SWP_NOSIZE))
+ {
+ break;
+ }
+ GetWindowRect(hWnd, &rParent);
+ if (wndPos->cx < MIN_EMAILS_WIDTH)
+ {
+ wndPos->cx = MIN_EMAILS_WIDTH;
+ }
+ if (wndPos->cy < MIN_EMAILS_HEIGHT)
+ {
+ wndPos->cy = MIN_EMAILS_HEIGHT;
+ }
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_EMAILS_LIST), &rParent, wndPos, ANCHOR_ALL);
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_CLOSE), &rParent, wndPos, ANCHOR_BOTTOM | ANCHOR_RIGHT);
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_MARK_READ), &rParent, wndPos, ANCHOR_BOTTOM | ANCHOR_LEFT);
+
+ EndDeferWindowPos(hdWnds);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CLOSE:
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ //HWND hList = GetDlgItem(hWnd, IDC_EMAILS_LIST);
+ //ListView_SetItemState(hList, -1, LVIS_SELECTED, LVIS_SELECTED);
+ //SetFocus(hList);
+
+ break;
+ }
+
+ case IDC_MARK_READ:
+ {
+ HWND hList = GetDlgItem(hWnd, IDC_EMAILS_LIST);
+ int i;
+ int count = ListView_GetItemCount(hList);
+ for (i = 0; i < count; i++)
+ {
+ if (ListView_GetCheckState(hList, i))
+ {
+ //char sender[1024]; //nooo
+ TCHAR emailID[2048]; //uhh ohh
+ LVITEM item = {0};
+ item.iItem = i;
+ item.mask = LVIF_TEXT;
+ //item.pszText = sender;
+ //item.cchTextMax = sizeof(sender);
+ //ListView_GetItem(hList, &item);
+
+ item.iSubItem = 2;
+ item.cchTextMax = sizeof(emailID);
+ item.pszText = emailID;
+ ListView_GetItem(hList, &item);
+ exchangeServer.MarkEmailAsRead(emailID);
+ }
+ }
+ count = exchangeServer.GetUnreadEmailsCount();
+ if (count > 0)
+ {
+ SetWindowLong(hWnd, GWLP_USERDATA, count);
+ SendMessage(hWnd, EXM_UPDATE_EMAILS, 0, 0);
+ }
+ else{
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+ }
+
+ break;
+ }
+ default:
+
+ break;
+ }
+
+ return 0;
+}
+
+BOOL CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+ {
+ switch (HIWORD(wParam))
+ {
+ case STN_CLICKED:
+ {
+ //HWND hParent = FindWindow(MIRANDACLASS, NULL);
+ //CreateDialog(hInstance, MAKEINTRESOURCE(IDD_EMAILS), hParent, DlgProcEmails);
+ int count = (int) PUGetPluginData(hWnd);
+ ShowEmailsWindow(count);
+ PUDeletePopup(hWnd);
+
+ break;
+ }
+ }
+
+ break;
+ }
+ case WM_CONTEXTMENU:
+ {
+ PUDeletePopup(hWnd);
+
+ break;
+ }
+ }
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+} \ No newline at end of file
diff --git a/plugins/Exchange/src/dlg_handlers.h b/plugins/Exchange/src/dlg_handlers.h
new file mode 100644
index 0000000000..3aa2550604
--- /dev/null
+++ b/plugins/Exchange/src/dlg_handlers.h
@@ -0,0 +1,32 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_DIALOG_HANDLERS_H
+#define M_EXCHANGE_DIALOG_HANDLERS_H
+
+#include "commonheaders.h"
+
+#define EXM_UPDATE_EMAILS WM_USER + 101
+
+BOOL CALLBACK DlgProcOptions(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcEmails(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#endif //M_EXCHANGE_DIALOG_HANDLERS_H \ No newline at end of file
diff --git a/plugins/Exchange/src/emails.cpp b/plugins/Exchange/src/emails.cpp
new file mode 100644
index 0000000000..1ee8a90688
--- /dev/null
+++ b/plugins/Exchange/src/emails.cpp
@@ -0,0 +1,424 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "emails.h"
+
+CExchangeServer::CExchangeServer()
+{
+ bConnected = 0; //not connected
+ bTryConnect = 1; //try to connect
+ cConnections = 0; //first attempt
+}
+
+CExchangeServer::~CExchangeServer()
+{
+ Disconnect();
+}
+
+int CExchangeServer::Connect(int bForceConnect)
+{
+ int maxRetries = db_get_b(NULL, ModuleName, "MaxRetries", MAX_EXCHANGE_CONNECT_RETRIES);
+ if (bForceConnect)
+ {
+ bTryConnect = 1;
+ cConnections = 0;
+ }
+
+ if (cConnections >= maxRetries)
+ {
+ bTryConnect = 0;
+ cConnections = 0;
+ _popupUtil("Maximum number of retries reached.\nPlugin will stop trying to connect automatically.");
+ }
+ if (bTryConnect)
+ {
+ cConnections++;
+ }
+
+ if ((bTryConnect) && !IsServerAvailable())
+ {
+ bTryConnect = 0;
+ _popupUtil("Server not available");
+ }
+
+ if ((!IsConnected()) && (bTryConnect))
+ {
+ TCHAR user[1024]; //lovely
+ TCHAR password[1024]; //i know
+ TCHAR server[1024];
+ int port;
+
+ GetStringFromDatabase("Username", _T(""), user, _countof(user));
+ if (ServiceExists(MS_UTILS_REPLACEVARS))
+ {
+ TCHAR *tmpUser = Utils_ReplaceVarsT(user);
+
+ _tcsncpy(user, tmpUser, _countof(user));
+ mir_free(tmpUser);
+ }
+
+ GetStringFromDatabase("Password", _T(""), password, _countof(password));
+ CallService(MS_DB_CRYPT_DECODESTRING, sizeof(password), (LPARAM) password);
+ GetStringFromDatabase("Server", _T(""), server, _countof(server));
+ port = db_get_dw(NULL, ModuleName, "Port", EXCHANGE_PORT);
+ if (_tcslen(server) > 0) //only connect if there's a server to connect to
+ {
+ return DoConnect(user, password, server, port);
+ }
+ else {
+ _popupUtil("Server is not configured ...");
+ }
+ }
+ return -1; //0 on success, != 0 otherwise
+}
+
+int CExchangeServer::Reconnect()
+{
+ Disconnect();
+ Connect();
+ return 0;
+}
+
+int CExchangeServer::Disconnect()
+{
+// if (IsConnected())
+// {
+ return DoDisconnect();
+// }
+// return -1; //0 on success, != 0 otherwise
+}
+
+int CExchangeServer::DoConnect(TCHAR *user, TCHAR *password, TCHAR *server, int port)
+{
+
+ if (bTryConnect)
+ {
+ bConnected = 0;
+#ifndef NO_EXCHANGE_TEST
+ if ( InitializeAndLogin( user, password, server )== S_OK)
+ {
+ bConnected = 1;
+ cConnections = 0; //restart connection attempts counter
+ }
+
+#endif
+ }
+
+ return !bConnected; //0 on success, != 0 otherwise
+}
+
+int CExchangeServer::DoDisconnect()
+{
+#ifndef NO_EXCHANGE_TEST
+ LogOFF();
+#endif
+ bConnected = 0;
+ return bConnected; //0 on success, != 0 otherwise
+}
+
+int CExchangeServer::IsConnected()
+{
+#ifndef NO_EXCHANGE_TEST
+ return bConnected;
+#else
+ return true;
+#endif
+}
+
+void InitSocketAddr(sockaddr_in *addrServer, char *szServer)
+{
+ hostent *hp;
+ hp = gethostbyname(szServer);
+ addrServer->sin_family = AF_INET;
+ if (hp == NULL)
+ {
+ addrServer->sin_addr.s_addr = inet_addr(szServer);
+ }
+ else{
+ memcpy(&(addrServer->sin_addr), hp->h_addr, hp->h_length);
+ }
+ int port = db_get_dw(NULL, ModuleName, "Port", EXCHANGE_PORT);
+ addrServer->sin_port = htons(port);
+}
+
+int CExchangeServer::IsServerAvailable()
+{
+ int check = db_get_b(NULL, ModuleName, "UsePortCheck", 1);
+ if (check)
+ {
+ SOCKET sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sServer == INVALID_SOCKET)
+ {
+ return 0; //server is not available
+ }
+ TCHAR szServer[1024];
+ GetStringFromDatabase("Server", _T(""), szServer, sizeof(szServer));
+ sockaddr_in addrServer;
+ InitSocketAddr(&addrServer, mir_t2a(szServer));
+ int res = connect(sServer, (sockaddr *) &addrServer, sizeof(addrServer));
+ int bAvailable = 0;
+ if (!res)
+ {//if connected then close smtp connection by sending a quit message
+ bAvailable = 1;
+ char message[] = "quit\n";
+ res = send(sServer, message, strlen(message), 0);
+ }
+ res = closesocket(sServer); //close the socket
+ return bAvailable;
+ }
+ else{
+ return 1; //if we're not using port check assume the server is available.
+ }
+}
+
+int CExchangeServer::GetUnreadEmailsCount()
+{
+ int nCount = -1;
+
+#ifndef NO_EXCHANGE_TEST
+ HRESULT hRes = CheckForNewMails(nCount);
+
+ if (hRes!=S_OK)
+ {
+ Reconnect();
+
+ if (IsConnected())
+ {
+ hRes = CheckForNewMails(nCount);
+ }
+ else {
+ nCount = -1;
+ }
+ }
+#else
+ nCount = 3;
+#endif
+
+ return nCount;
+}
+
+int CExchangeServer::GetEmailHeader(int iUnreadEmail, TEmailHeader *emailInfo)
+{
+ if (!IsConnected())
+ {
+ //Connect();
+ return -1;
+ }
+ if (emailInfo->cbSize != sizeof(TEmailHeader))
+ {
+ return -1;
+ }
+
+#ifndef NO_EXCHANGE_TEST
+
+ if(NULL!=m_HeadersKeeper[iUnreadEmail])
+ {
+ TCHAR* szSender = m_HeadersKeeper[iUnreadEmail]->m_szSender;
+ TCHAR* szSubject = m_HeadersKeeper[iUnreadEmail]->m_szSubject;
+
+ if( NULL == szSender)
+ {
+ szSender = _T("");
+ }
+
+ if( NULL == szSubject)
+ {
+ szSubject = _T("");
+ }
+
+ emailInfo->szSender = szSender;
+ emailInfo->szSubject = szSubject;
+ emailInfo->emailID = (NULL!=m_HeadersKeeper[iUnreadEmail]->m_szEntryID)?m_HeadersKeeper[iUnreadEmail]->m_szEntryID:"";
+
+ }
+ else {
+ return -1;
+ }
+
+
+#else
+ emailInfo->szSender = "<sender>";
+ emailInfo->szSubject = "<subject>";
+ emailInfo->emailID = "123";
+#endif
+
+ return 0;
+}
+
+int CExchangeServer::MarkEmailAsRead(TCHAR *emailID)
+{
+ if (!IsConnected())
+ {
+ return -1;
+ }
+
+#ifndef NO_EXCHANGE_TEST
+ MarkAsRead( emailID );
+#endif
+
+ return 0;
+}
+
+int CExchangeServer::OpenMessage(TCHAR *emailID)
+{
+ if (!IsConnected())
+ {
+ return -1;
+ }
+
+#ifndef NO_EXCHANGE_TEST
+ OpenTheMessage( emailID );
+#endif
+
+ return 0;
+}
+
+int CExchangeServer::Check(int bNoEmailsNotify)
+{
+
+ int count = -1;
+ if (IsConnected())
+ {
+ count = GetUnreadEmailsCount();
+
+ if (count==-1)
+ {
+ Reconnect();
+ if (IsConnected())
+ {
+ count = GetUnreadEmailsCount();
+ }
+ else {
+ return -1;
+ }
+ }
+
+ }
+ else {
+ Reconnect();
+ if (IsConnected())
+ {
+ count = GetUnreadEmailsCount();
+ }
+ else {
+ return -1;
+ }
+
+ if (count==-1)
+ {
+ return -1;
+ }
+ }
+
+ if( ( (count > 0) || ((bNoEmailsNotify) && (count >= 0)) )&& (count!=-1))
+ {
+ TCHAR buffer[1024];
+ if (count != 1)
+ {
+ mir_sntprintf(buffer,_countof(buffer), TranslateT("You have %d unread emails ..."), count);
+ }
+ else {
+ mir_sntprintf(buffer, _countof(buffer),TranslateT("You have one unread email ..."));
+ }
+
+ ShowMessage(buffer, count);
+ /*int i;
+ TEmailHeader emailInfo = {0};
+ char sender[1024];
+ char subject[1024];
+ emailInfo.cbSize = sizeof(emailInfo);
+ emailInfo.szSender = sender;
+ emailInfo.szSubject = subject;
+ emailInfo.cSender = sizeof(sender);
+ emailInfo.cSubject = sizeof(subject);
+ for (i = 0; i < count; i++)
+ {
+ GetEmailHeader(i, &emailInfo);
+ sprintf(buffer, "Unread email #%d:\nSender :%s\nSubject :%s", i + 1, sender, subject);
+ ShowMessage(buffer);
+ }*/
+ }
+
+ if (count==-1)
+ {
+ _popupUtil("Cannot connect to Exchange server ...");
+ }
+
+ return count;
+}
+
+int ShowMessage(TCHAR *message, int cUnreadEmails)
+{
+ int usePopups = ServiceExists(MS_POPUP_ADDPOPUP) ? db_get_b(NULL, ModuleName, "UsePopups", 0) : 0;
+ if (usePopups)
+ {
+ return ShowPopupMessage(TranslateT("Exchange email"), message, cUnreadEmails);
+ }
+ else{
+ return ShowMessageBoxMessage(TranslateT("Do you want to see the email headers ?"), message, cUnreadEmails);
+ }
+
+ return 0;
+}
+
+int ShowPopupMessage(TCHAR *title, TCHAR *message, int cUnreadEmails)
+{
+ POPUPDATAT popup = {0};
+ popup.lchContact = NULL;
+ popup.colorBack = NULL;
+ popup.colorText = NULL;
+ popup.lchIcon = hiMailIcon;
+ _tcsncpy(popup.lptzContactName, title,_tcslen(title));
+ _tcsncpy(popup.lptzText, message,_tcslen(message));
+ popup.PluginWindowProc = (WNDPROC) DlgProcPopup;
+ popup.PluginData = (int *) cUnreadEmails;
+ return PUAddPopupT(&popup);
+}
+
+int ShowMessageBoxMessage(TCHAR *title, TCHAR *message, int cUnreadEmails)
+{
+ if (MessageBox(0, message, title, MB_YESNO) == IDYES)
+ {
+ ShowEmailsWindow(cUnreadEmails);
+ }
+
+ return 0;
+}
+
+int ShowEmailsWindow(int cUnreadEmails)
+{
+ if (cUnreadEmails > 0) //show window only if there are unread emails
+ {
+ if (!hEmailsDlg)
+ {
+ hEmailsDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_EMAILS), NULL, (DLGPROC)DlgProcEmails);
+ }
+
+ SetWindowLong(hEmailsDlg, GWLP_USERDATA, cUnreadEmails);
+ if (IsWindowVisible(hEmailsDlg))
+ {
+ SendMessage(hEmailsDlg, EXM_UPDATE_EMAILS, 0, 0);
+ }
+ else {
+ ShowWindow(hEmailsDlg, SW_SHOW);
+ }
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/Exchange/src/emails.h b/plugins/Exchange/src/emails.h
new file mode 100644
index 0000000000..24f63ab233
--- /dev/null
+++ b/plugins/Exchange/src/emails.h
@@ -0,0 +1,96 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_EMAILS_H
+#define M_EXCHANGE_EMAILS_H
+
+//define if you want to test only the miranda part, and not the exchange one.
+//#define NO_EXCHANGE_TEST
+
+#include "commonheaders.h"
+
+#ifndef NO_EXCHANGE_TEST
+#include "MirandaExchange.h"
+#endif
+
+#define MAX_EXCHANGE_CONNECT_RETRIES 15
+
+struct TEmailHeader{
+ int cbSize;
+ DWORD flags; //flags
+ TCHAR *szSender; //pointer to string that receives the sender name
+ int cSender; //size of szSender buffer
+ TCHAR *szSubject; //pointer to string that receives the email subject
+ int cSubject; //size of szSubject buffer
+ char *emailID;
+};
+
+#ifndef NO_EXCHANGE_TEST
+class CExchangeServer: public CMirandaExchange{
+#else
+class CExchangeServer{
+#endif
+ protected:
+ int bConnected; //are we connected
+ int cConnections; //number of connection attempts
+ int bTryConnect;
+
+ int DoConnect(TCHAR *user, TCHAR *password, TCHAR *server, int port);
+ int DoDisconnect();
+
+ public:
+ CExchangeServer();
+ ~CExchangeServer();
+
+ int Connect(int bRestartCounter = 0);
+ int Disconnect();
+ int Reconnect();
+
+ int IsConnected();
+ int IsServerAvailable();
+
+ /*
+ Returns the number of unread emails.
+ */
+ int GetUnreadEmailsCount();
+ /*
+ iUnreadEmail - the index of the unread email, 0 = the oldest unread email, <count> = the newest unread email.
+ emailInfo - will be filled with the relevant info (sender and subject). cbSize will be set before the call to the function; the caller also has to allocate memory for the sender and subject
+ */
+ int GetEmailHeader(int iUnreadEmail, TEmailHeader *emailInfo);
+
+ /*
+ */
+ int MarkEmailAsRead(TCHAR *emailID);
+
+ int OpenMessage(TCHAR *emailID);
+
+ int Check(int bNoEmailsNotify = FALSE);
+};
+
+extern CExchangeServer &exchangeServer;
+
+int ShowMessage(TCHAR *message, int cUnreadEmails);
+int ShowPopupMessage(TCHAR *title, TCHAR *message, int cUnreadEmails);
+int ShowMessageBoxMessage(TCHAR *title, TCHAR *message, int cUnreadEmails);
+
+int ShowEmailsWindow(int cUnreadEmails);
+
+#endif //M_EXCHANGE_EMAILS_H
diff --git a/plugins/Exchange/src/exchange.cpp b/plugins/Exchange/src/exchange.cpp
new file mode 100644
index 0000000000..6d789db56f
--- /dev/null
+++ b/plugins/Exchange/src/exchange.cpp
@@ -0,0 +1,99 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "commonheaders.h"
+
+char ModuleName[] = "ExchangeNotify";
+HINSTANCE hInstance;
+HICON hiMailIcon = NULL;
+HWND hEmailsDlg = NULL;
+int hLangpack=0;
+
+CExchangeServer &exchangeServer = CExchangeServer();
+
+//PLUGINLINK *pluginLink;
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_DISPLAY_NAME,
+ VERSION,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ {0x2fd0df15, 0x7098, 0x41ce, {0xaa, 0x92, 0xff, 0x62, 0x18, 0x06, 0xe3, 0x8b}} //{2fd0df15-7098-41ce-aa92-ff621806e38b}
+}; //not used
+
+//OLD_MIRANDAPLUGININFO_SUPPORT;
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+// Log("%s", "Entering function " __FUNCTION__);
+// Log("%s", "Leaving function " __FUNCTION__);
+ return &pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_EXCHANGE, MIID_LAST};
+
+extern "C" __declspec(dllexport) const MUUID *MirandaPluginInterfaces()
+{
+ return interfaces;
+}
+
+extern "C" int __declspec(dllexport) Load()
+{
+// Log("%s", "Entering function " __FUNCTION__);
+ //pluginLink = link;
+ mir_getLP( &pluginInfo );
+// Log("%s", "Initialising miranda memory functions");
+// InitializeMirandaMemFunctions();
+ hiMailIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIL));
+// Log("%s", "Creating service functions ...");
+ InitServices();
+// Log("%s", "Hooking events ...");
+ HookEvents();
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload()
+{
+// Log("%s", "Entering function " __FUNCTION__);
+// Log("%s", "Unhooking events ...");
+
+// Log("%s", "Destroying service functions ...");
+ DestroyServices();
+// DestroyEvents();
+ UnhookEvents();
+
+// Log("%s", "Leaving function " __FUNCTION__);
+ return 0;
+}
+
+extern "C" bool WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInstance = hinstDLL; //save global instance
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hinstDLL);
+ }
+ return TRUE;
+} \ No newline at end of file
diff --git a/plugins/Exchange/src/hooked_events.cpp b/plugins/Exchange/src/hooked_events.cpp
new file mode 100644
index 0000000000..f3eb3b60bc
--- /dev/null
+++ b/plugins/Exchange/src/hooked_events.cpp
@@ -0,0 +1,176 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "hooked_events.h"
+
+HANDLE hModulesLoaded;
+HANDLE hOptionsInitialise;
+HANDLE hPreShutdown;
+
+UINT_PTR hCheckTimer = NULL;
+UINT_PTR hReconnectTimer = NULL;
+UINT_PTR hFirstCheckTimer = NULL;
+
+#define HOST "http://eblis.tla.ro/projects"
+
+#define EXCHANGE_VERSION_URL HOST "/miranda/Exchange/updater/Exchange.html"
+#define EXCHANGE_UPDATE_URL HOST "/miranda/Exchange/updater/Exchange.zip"
+#define EXCHANGE_VERSION_PREFIX "Exchange notifier plugin version "
+
+int HookEvents()
+{
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ hOptionsInitialise = HookEvent(ME_OPT_INITIALISE, OnOptionsInitialise);
+ hPreShutdown = HookEvent(ME_SYSTEM_PRESHUTDOWN, OnSystemPreShutdown);
+
+ return 0;
+}
+
+int UnhookEvents()
+{
+ UnhookEvent(hModulesLoaded);
+ UnhookEvent(hOptionsInitialise);
+ UnhookEvent(hPreShutdown);
+
+ KillTimers();
+
+ return 0;
+}
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+
+ UpdateTimers();
+ CLISTMENUITEM cl = {0};
+ cl.cbSize = sizeof(CLISTMENUITEM);
+ cl.hIcon = hiMailIcon;
+ cl.position = 10000000;
+ cl.pszService = MS_EXCHANGE_CHECKEMAIL;
+ cl.pszName = Translate("Check exchange mailbox");
+ Menu_AddMainMenuItem (&cl);
+
+ hEmailsDlg = NULL; //CreateDialog(hInstance, MAKEINTRESOURCE(IDD_EMAILS), NULL, DlgProcEmails); //create emails window
+ FirstTimeCheck();
+// CheckEmail();
+ return 0;
+}
+
+//add the exchange options dialog to miranda
+int OnOptionsInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInstance;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_EXCHANGE);
+ odp.ptszTitle = LPGENT("Exchange notify");
+ odp.ptszGroup = LPGENT("Plugins");
+ odp.groupPosition = 910000000;
+ odp.flags=ODPF_BOLDGROUPS|ODPF_TCHAR;
+ odp.pfnDlgProc = (DLGPROC)DlgProcOptions;
+ //CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ Options_AddPage(wParam, &odp);
+ return 0;
+}
+
+int OnSystemPreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ if (hEmailsDlg)
+ {
+ SendMessage(hEmailsDlg, WM_CLOSE, 0, 0); //close the window if it's opened
+ }
+
+ exchangeServer.Disconnect();
+
+ return 0;
+}
+
+void FirstTimeCheck()
+{
+ hFirstCheckTimer = SetTimer(NULL, 0, 5 * 1000, OnFirstCheckTimer);
+}
+
+int UpdateTimers()
+{
+ KillTimers();
+ int interval;
+ interval = db_get_dw(NULL, ModuleName, "Interval", DEFAULT_INTERVAL);
+ interval *= 1000; //go from miliseconds to seconds
+ hCheckTimer = SetTimer(NULL, 0, interval, (TIMERPROC) OnCheckTimer);
+
+ int bReconnect = db_get_b(NULL, ModuleName, "Reconnect", 0);
+ if (bReconnect) //user wants to forcefully reconnect every x minutes
+ {
+ interval = db_get_dw(NULL, ModuleName, "ReconnectInterval", DEFAULT_RECONNECT_INTERVAL);
+ interval *= 1000 * 60; //go from miliseconds to seconds to minutes
+ hReconnectTimer = SetTimer(NULL, 0, interval, (TIMERPROC) OnReconnectTimer);
+ }
+
+ return 0;
+}
+
+int KillTimers()
+{
+ if (hCheckTimer)
+ {
+ KillTimer(NULL, hCheckTimer);
+ hCheckTimer = NULL;
+ }
+ if (hReconnectTimer)
+ {
+ KillTimer(NULL, hReconnectTimer);
+ hReconnectTimer = NULL;
+ }
+ return 0;
+}
+
+VOID CALLBACK OnCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+ /*if (exchangeServer.IsConnected())
+ {
+ exchangeServer.Check();
+ }
+ else{
+ exchangeServer.Connect();
+ }*/
+ int bCheck = db_get_b(NULL, ModuleName, "Check", 1);
+
+ if (bCheck) //only check if we were told to
+ {
+ ThreadCheckEmail(FALSE);
+ }
+}
+
+VOID CALLBACK OnReconnectTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+
+ _popupUtil("Forcefully reconnecting to Exchange server ...");
+
+ exchangeServer.Reconnect(); //reconnect
+}
+
+VOID CALLBACK OnFirstCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+ KillTimer(NULL, hFirstCheckTimer);
+ OnCheckTimer(hWnd, msg, idEvent, dwTime);
+
+ hFirstCheckTimer = NULL;
+} \ No newline at end of file
diff --git a/plugins/Exchange/src/hooked_events.h b/plugins/Exchange/src/hooked_events.h
new file mode 100644
index 0000000000..064e11c4a9
--- /dev/null
+++ b/plugins/Exchange/src/hooked_events.h
@@ -0,0 +1,49 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_HOOKED_EVENTS_H
+#define M_EXCHANGE_HOOKED_EVENTS_H
+
+#include "commonheaders.h"
+#include "dlg_handlers.h"
+
+extern HANDLE hModulesLoaded;
+extern HANDLE hOptionsInitialise;
+extern HANDLE hPreShutdown;
+
+extern UINT_PTR hCheckTimer;
+extern UINT_PTR hReconnectTimer;
+
+int HookEvents();
+int UnhookEvents();
+
+void FirstTimeCheck();
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam);
+int OnOptionsInitialise(WPARAM wParam, LPARAM lParam);
+int OnSystemPreShutdown(WPARAM wParam, LPARAM lParam);
+
+int UpdateTimers();
+int KillTimers();
+VOID CALLBACK OnCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime);
+VOID CALLBACK OnReconnectTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime);
+VOID CALLBACK OnFirstCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime);
+
+#endif \ No newline at end of file
diff --git a/plugins/Exchange/src/resource.h b/plugins/Exchange/src/resource.h
new file mode 100644
index 0000000000..866688bd70
--- /dev/null
+++ b/plugins/Exchange/src/resource.h
@@ -0,0 +1,29 @@
+#ifndef IDC_STATIC
+#define IDC_STATIC (-1)
+#endif
+
+#define IDD_OPT_EXCHANGE 101
+#define IDI_MAIL 104
+#define IDD_EMAILS 105
+#define IDI_ICON1 107
+#define IDI_UNREAD 108
+#define IDC_USER_EDIT 1001
+#define IDC_PASSWORD_EDIT 1002
+#define IDC_SERVER_EDIT 1003
+#define IDC_PORT_EDIT 1004
+#define IDC_EDIT5 1005
+#define IDC_USE_POPUPS 1005
+#define IDC_EDIT6 1006
+#define IDC_INTERVAL_EDIT 1006
+#define IDC_EMAILS_LIST 1008
+#define IDC_CLOSE 1009
+#define IDC_BUTTON1 1010
+#define IDC_MARK_READ 1010
+#define IDC_CHECKEMAILS 1010
+#define IDC_CHECK_EMAILS 1010
+#define IDC_RECONNECT 1011
+#define IDC_EDIT1 1012
+#define IDC_RECONNECT_INTERVAL 1012
+#define IDC_USE_PORTCHECK 1013
+#define IDC_EDIT2 1014
+#define IDC_MAX_RETRIES 1014
diff --git a/plugins/Exchange/src/services.cpp b/plugins/Exchange/src/services.cpp
new file mode 100644
index 0000000000..b15e25d734
--- /dev/null
+++ b/plugins/Exchange/src/services.cpp
@@ -0,0 +1,50 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "services.h"
+
+CRITICAL_SECTION csCheck;
+
+int InitServices()
+{
+ CreateServiceFunction(MS_EXCHANGE_CHECKEMAIL, (MIRANDASERVICE) CheckEmailService);
+ InitializeCriticalSection(&csCheck);
+
+ return 0;
+}
+
+int DestroyServices()
+{
+ DestroyServiceFunction(MS_EXCHANGE_CHECKEMAIL);
+ DeleteCriticalSection(&csCheck);
+
+ return 0;
+}
+
+int CheckEmailService(WPARAM wParam, LPARAM lParam)
+{
+/*
+ if (!exchangeServer.IsConnected())
+ {
+ exchangeServer.Connect(1); //force connection attempt
+ }
+ return exchangeServer.Check(TRUE); */
+ return ThreadCheckEmail(TRUE);
+} \ No newline at end of file
diff --git a/plugins/Exchange/src/services.h b/plugins/Exchange/src/services.h
new file mode 100644
index 0000000000..4640f6bed6
--- /dev/null
+++ b/plugins/Exchange/src/services.h
@@ -0,0 +1,35 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_SERVICES_H
+#define M_EXCHANGE_SERVICES_H
+
+#define MS_EXCHANGE_CHECKEMAIL "Exchange/CheckEmail"
+
+#include "commonheaders.h"
+
+extern CRITICAL_SECTION csCheck;
+
+int InitServices();
+int DestroyServices();
+
+int CheckEmailService(WPARAM wParam, LPARAM lParam);
+
+#endif //M_EXCHANGE_SERVICES_H \ No newline at end of file
diff --git a/plugins/Exchange/src/utils.cpp b/plugins/Exchange/src/utils.cpp
new file mode 100644
index 0000000000..97aed40a68
--- /dev/null
+++ b/plugins/Exchange/src/utils.cpp
@@ -0,0 +1,276 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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 "utils.h"
+
+#define ___DEB
+
+int LogInit()
+{
+#ifdef ___DEBUGG
+ FILE *fout = fopen(LOG_FILE, "wt");
+ fclose(fout);
+#endif
+ return 0;
+}
+
+int Log(char *format, ...)
+{
+#ifdef ___DEBUGG
+ char str[4096];
+ va_list vararg;
+ int tBytes;
+ FILE *fout = fopen(LOG_FILE, "at");
+ if (!fout)
+ {
+// MessageBox(0, "can't open file", NULL, MB_OK);
+ return -1;
+ }
+
+ va_start(vararg, format);
+
+ tBytes = _vsnprintf(str, sizeof(str), format, vararg);
+ if (tBytes > 0)
+ {
+ str[tBytes] = 0;
+ }
+
+ va_end(vararg);
+ if (str[strlen(str) - 1] != '\n')
+ {
+ strcat(str, "\n");
+ }
+ fputs(str, fout);
+ fclose(fout);
+#endif
+ return 0;
+}
+
+int Info(char *title, char *format, ...)
+{
+ char str[4096];
+ va_list vararg;
+ int tBytes;
+ va_start(vararg, format);
+ tBytes = _vsnprintf(str, sizeof(str), format, vararg);
+ if (tBytes > 0)
+ {
+ str[tBytes] = 0;
+ }
+ va_end(vararg);
+ return MessageBoxA(0, str, title, MB_OK | MB_ICONINFORMATION);
+}
+
+#define HEX_SIZE 8
+
+char *BinToHex(int size, PBYTE data)
+{
+ char *szresult = NULL;
+ char buffer[32] = {0}; //should be more than enough
+ int maxSize = size * 2 + HEX_SIZE + 1;
+ szresult = (char *) new char[ maxSize ];
+ memset(szresult, 0, maxSize);
+ sprintf(buffer, "%0*X", HEX_SIZE, size);
+ strcpy(szresult, buffer);
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ sprintf(buffer, "%02X", data[i]);
+ strcpy(szresult + (HEX_SIZE + i * 2), buffer);
+ }
+ return szresult;
+}
+/*
+TCHAR *BinToHex(int size, PBYTE data)
+{
+ TCHAR *szresult = NULL;
+ TCHAR buffer[32] = {0}; //should be more than enough
+ int maxSize = size * 2 + HEX_SIZE + 1;
+ szresult = (TCHAR *) new TCHAR[ maxSize ];
+ memset(szresult, 0, maxSize);
+ mir_sntprintf(buffer,_countof(buffer), _T("%0*X"), HEX_SIZE, size);
+ _tcsncpy(szresult, buffer,_countof(buffer));
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ mir_sntprintf(buffer, _countof(buffer),_T("%02X"), data[i]);
+ _tcsncpy(szresult + (HEX_SIZE + i * 2), buffer,_countof(buffer));
+ }
+ return szresult;
+}
+*/
+
+void HexToBin(TCHAR *inData, ULONG &size, LPBYTE &outData)
+{
+ TCHAR buffer[32] = {0};
+ _tcsncpy(buffer, _T("0x"),_countof(_T("0x")));
+ _tcsncpy(buffer + 2, inData, HEX_SIZE);
+ _stscanf(buffer, _T("%x"), &size);
+ outData = (unsigned char*)new char[size*2];
+ UINT i;
+ //size = i;
+ TCHAR *tmp = inData + HEX_SIZE;
+ buffer[4] = '\0'; //mark the end of the string
+ for (i = 0; i < size; i++)
+ {
+ _tcsncpy(buffer + 2, &tmp[i * 2], 2);
+ _stscanf(buffer, _T("%x"), &outData[i]);
+ }
+ i = size;
+}
+
+int GetStringFromDatabase(char *szSettingName, TCHAR *szError, TCHAR *szResult, int size)
+{
+ DBVARIANT dbv = {0};
+ int res = 1;
+ int len;
+ dbv.type = DBVT_ASCIIZ;
+ if (db_get_ts(NULL, ModuleName, szSettingName, &dbv) == 0)
+ {
+ res = 0;
+ int tmp = _tcslen(dbv.ptszVal);
+ len = (tmp < size - 1) ? tmp : size - 1;
+ _tcsncpy(szResult, dbv.ptszVal, len);
+ szResult[len] = '\0';
+ mir_free(dbv.ptszVal);
+ }
+ else{
+ res = 1;
+ int tmp = _tcslen(szError);
+ len = (tmp < size - 1) ? tmp : size - 1;
+ _tcsncpy(szResult, szError, len);
+ szResult[len] = '\0';
+ }
+ return res;
+}
+
+void ScreenToClient(HWND hWnd, LPRECT rect)
+{
+ POINT pt;
+ int cx = rect->right - rect->left;
+ int cy = rect->bottom - rect->top;
+ pt.x = rect->left;
+ pt.y = rect->top;
+ ScreenToClient(hWnd, &pt);
+ rect->left = pt.x;
+ rect->top = pt.y;
+ rect->right = pt.x + cx;
+ rect->bottom = pt.y + cy;
+}
+
+void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors)
+{
+ RECT rParent;
+ RECT rChild;
+
+ if (parentPos->flags & SWP_NOSIZE)
+ {
+ return;
+ }
+ GetWindowRect(parentPos->hwnd, &rParent);
+ rChild = AnchorCalcPos(window, &rParent, parentPos, anchors);
+ MoveWindow(window, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, FALSE);
+}
+
+RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors)
+{
+ RECT rChild;
+ RECT rTmp;
+
+ GetWindowRect(window, &rChild);
+ ScreenToClient(parentPos->hwnd, &rChild);
+
+ int cx = rParent->right - rParent->left;
+ int cy = rParent->bottom - rParent->top;
+ if ((cx == parentPos->cx) && (cy == parentPos->cy))
+ {
+ return rChild;
+ }
+ if (parentPos->flags & SWP_NOSIZE)
+ {
+ return rChild;
+ }
+
+ rTmp.left = parentPos->x - rParent->left;
+ rTmp.right = (parentPos->x + parentPos->cx) - rParent->right;
+ rTmp.bottom = (parentPos->y + parentPos->cy) - rParent->bottom;
+ rTmp.top = parentPos->y - rParent->top;
+
+ cx = (rTmp.left) ? -rTmp.left : rTmp.right;
+ cy = (rTmp.top) ? -rTmp.top : rTmp.bottom;
+
+ rChild.right += cx;
+ rChild.bottom += cy;
+ //expanded the window accordingly, now we need to enforce the anchors
+ if ((anchors & ANCHOR_LEFT) && (!(anchors & ANCHOR_RIGHT)))
+ {
+ rChild.right -= cx;
+ }
+ if ((anchors & ANCHOR_TOP) && (!(anchors & ANCHOR_BOTTOM)))
+ {
+ rChild.bottom -= cy;
+ }
+ if ((anchors & ANCHOR_RIGHT) && (!(anchors & ANCHOR_LEFT)))
+ {
+ rChild.left += cx;
+ }
+ if ((anchors & ANCHOR_BOTTOM) && (!(anchors & ANCHOR_TOP)))
+ {
+ rChild.top += cy;
+ }
+ return rChild;
+}
+
+DWORD WINAPI CheckEmailWorkerThread(LPVOID data)
+{
+ EnterCriticalSection(&csCheck);
+
+ int bForceAttempt = (int) data;
+
+ if (!exchangeServer.IsConnected())
+ {
+ exchangeServer.Connect(bForceAttempt);
+ }
+ exchangeServer.Check(bForceAttempt);
+
+ LeaveCriticalSection(&csCheck);
+
+ return 0;
+}
+
+int ThreadCheckEmail(int bForceAttempt)
+{
+ DWORD idThread;
+ HANDLE hCheckThread = CreateThread(NULL, NULL, CheckEmailWorkerThread, (void *) bForceAttempt, 0, &idThread);
+ CloseHandle(hCheckThread);
+
+ return 0;
+}
+
+void _popupUtil(char* szMsg)
+{
+ POPUPDATAT ppd = {0};
+ ppd.lchIcon = hiMailIcon;
+ _tcscpy(ppd.lptzContactName, _T("Exchange notifier"));
+ _tcscpy(ppd.lptzText, mir_a2t(szMsg));
+ PUAddPopupT(&ppd); //show a popup to tell the user what we're doing.
+
+
+}
diff --git a/plugins/Exchange/src/utils.h b/plugins/Exchange/src/utils.h
new file mode 100644
index 0000000000..a1ad15fe43
--- /dev/null
+++ b/plugins/Exchange/src/utils.h
@@ -0,0 +1,52 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_UTILS_H
+#define M_EXCHANGE_UTILS_H
+
+#include <stdarg.h>
+#include "commonheaders.h"
+
+#define LOG_FILE "exchange.log"
+
+#define ANCHOR_LEFT 0x000001
+#define ANCHOR_RIGHT 0x000002
+#define ANCHOR_TOP 0x000004
+#define ANCHOR_BOTTOM 0x000008
+#define ANCHOR_ALL ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM
+
+int LogInit();
+int Log(char *format, ...);
+int Info(char *title, char *format, ...);
+
+char *BinToHex(int size, PBYTE data);
+void HexToBin(TCHAR *inData, ULONG &size, PBYTE &outData);
+
+
+void ScreenToClient(HWND hWnd, LPRECT rect);
+void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors);
+RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors);
+
+int GetStringFromDatabase(char *szSettingName, TCHAR *szError, TCHAR *szResult, int size);
+
+int ThreadCheckEmail(int bForceAttempt);
+
+void _popupUtil(char* szMsg);
+#endif \ No newline at end of file
diff --git a/plugins/Exchange/src/version.h b/plugins/Exchange/src/version.h
new file mode 100644
index 0000000000..6ca2653b57
--- /dev/null
+++ b/plugins/Exchange/src/version.h
@@ -0,0 +1,45 @@
+/*
+Exchange notifier plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean, Attila Vajda
+
+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.
+*/
+
+#ifndef M_EXCHANGE_VERSION_H
+#define M_EXCHANGE_VERSION_H
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 1
+#define __RELEASE_NUM 3
+#define __BUILD_NUM 4
+
+#define VERSION PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM)
+
+#define __PLUGINVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __PLUGINVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+#define __STRINGIFY_(x) #x
+#define __STRINGIFY(x) __STRINGIFY_(x)
+#define __VERSION_STRING __STRINGIFY(__PLUGINVERSION_STRING_DOTS)
+
+#define __DESC "Notifies you if you have unread email on an exchange server."
+#define __AUTHOR "Cristian Libotean, Attila Vajda, MaKaR (NG)"
+#define __AUTHOREMAIL "makar@poczta.of.pl"
+#define __COPYRIGHT "© 2006-2013 Cristian Libotean and Attila Vajda"
+#define __AUTHORWEB "http://maciej.wycik.pl/miranda"
+
+#define __PLUGIN_DISPLAY_NAME "Exchange notifier plugin"
+
+#endif //M_EXCHANGE_VERSION_H