You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
10 KiB
263 lines
10 KiB
// CSimpleDriver.cpp : Implementation of CCSimpleDriver
|
|
#include "stdafx.h"
|
|
#include "SimpleDriver.h"
|
|
#include "CSimpleDriver.h"
|
|
|
|
#include "POP3DropDir.h"
|
|
#include <stdio.h>
|
|
#include "mailmsgprops.h"
|
|
|
|
#include <IMFUtil.h>
|
|
#include <MailBox.h>
|
|
#include <POP3Events.h>
|
|
#include <POP3Server.h>
|
|
#include <POP3RegKeys.h>
|
|
//#include <winerror.h>
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CCSimpleDriver
|
|
|
|
CStoreDriverCriticalSection g_oSDCS;
|
|
CSimpleDriver *CSimpleDriver::s_pStoreDriver = NULL;
|
|
DWORD CSimpleDriver::s_dwCounter = 0;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// constructor/destructor
|
|
|
|
CSimpleDriver::CSimpleDriver() :
|
|
m_fInit(FALSE), m_lPrepareForShutdown(0)
|
|
{
|
|
m_szComputerName[0] = 0x0;
|
|
}
|
|
|
|
CSimpleDriver::~CSimpleDriver()
|
|
{
|
|
EnterCriticalSection(&g_oSDCS.s_csStoreDriver);
|
|
if (s_pStoreDriver == this)
|
|
s_pStoreDriver = NULL;
|
|
LeaveCriticalSection(&g_oSDCS.s_csStoreDriver);
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// ISMTPStoreDriver
|
|
|
|
HRESULT CSimpleDriver::Init( DWORD /*dwInstance*/, IUnknown* /*pBinding*/, IUnknown* /*pServer*/, DWORD /*dwReason*/, IUnknown **ppStoreDriver )
|
|
{
|
|
if (m_fInit) return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
|
|
if ( 0 != m_lPrepareForShutdown ) return HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS);
|
|
|
|
#if DBG == 1
|
|
TCHAR buf[255];
|
|
|
|
_stprintf(buf, _T( "new CSimpleDriver 0x%x, refcount = %x\n" ), this);
|
|
OutputDebugString(buf);
|
|
#endif
|
|
|
|
EnterCriticalSection(&g_oSDCS.s_csStoreDriver); // returns void
|
|
|
|
// smtpsvc may call the Init function on a store driver multiple
|
|
// times for the same instance. It expects an initialized
|
|
// store driver to be returned via ppStoreDriver. To prevent
|
|
// multiple store drivers from being created for the same instance
|
|
// we use s_pStoreDriver to hold a pointer to the one valid
|
|
// store driver. If this variable is currently NULL then we create
|
|
// a store driver which we can return.
|
|
//
|
|
// If a store driver needs to support being used by multiple
|
|
// SMTP instances then you need to maintain a list of store drivers,
|
|
// one per instance.
|
|
if (!s_pStoreDriver)
|
|
{
|
|
DWORD dwSize, dwRC;
|
|
DWORD dwLoggingLevel = 3;
|
|
CMailBox mailboxX;
|
|
|
|
mailboxX.SetMailRoot(); // Do this to refresh the static CMailBox::m_szMailRoot
|
|
|
|
assert( NULL == s_pStoreDriver );
|
|
|
|
dwSize = sizeof( m_szComputerName );
|
|
GetComputerNameA( m_szComputerName, &dwSize );
|
|
m_fInit = TRUE;
|
|
s_pStoreDriver = this;
|
|
m_EventLoggerX.InitEventLog( POP3_SERVER_NAME, EVENTCAT_POP3STOREDRIVER );
|
|
if ( ERROR_SUCCESS == RegQueryLoggingLevel( dwLoggingLevel ))
|
|
m_EventLoggerX.SetLoggingLevel( dwLoggingLevel );
|
|
m_EventLoggerX.LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_STARTED );
|
|
// Duplicate the Process token we'll need it to ENABLE SE_RESTORE_NAME privileges when creating mail
|
|
dwRC = m_AdjustTokenPrivilegesX.DuplicateProcessToken( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
|
|
if ( ERROR_SUCCESS != dwRC )
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_DUPLICATEPROCESSTOKEN_FAILED, dwRC );
|
|
}
|
|
|
|
// tell it about the one good store driver
|
|
s_pStoreDriver->AddRef();
|
|
*ppStoreDriver = (IUnknown *) (ISMTPStoreDriver*) s_pStoreDriver;
|
|
// in failure case handles are cleaned up in destructor
|
|
LeaveCriticalSection(&g_oSDCS.s_csStoreDriver);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSimpleDriver::PrepareForShutdown( DWORD /*dwReason*/ )
|
|
{
|
|
InterlockedExchange( &m_lPrepareForShutdown, 1 );
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CSimpleDriver::Shutdown( DWORD /*dwReason*/ )
|
|
{
|
|
if (m_fInit)
|
|
m_fInit = FALSE;
|
|
m_EventLoggerX.LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_STOPPED );
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// This function directly called DoLocalDelivery in the simple case, or
|
|
// adds the local delivery request to the queue if we support async
|
|
// requests
|
|
//
|
|
HRESULT CSimpleDriver::LocalDelivery(
|
|
IMailMsgProperties *pIMailMsgProperties,
|
|
DWORD dwRecipCount,
|
|
DWORD *pdwRecipIndexes,
|
|
IMailMsgNotify *pNotify
|
|
)
|
|
{
|
|
if ( NULL == pIMailMsgProperties || NULL == pdwRecipIndexes ) return E_INVALIDARG;
|
|
|
|
HRESULT hr;
|
|
|
|
if ( NULL == pNotify )
|
|
{ // do the local delivery - synchronously
|
|
hr = DoLocalDelivery(pIMailMsgProperties, dwRecipCount, pdwRecipIndexes);
|
|
}
|
|
else
|
|
{ // do the local delivery - asynchronously
|
|
CPOP3DropDir *pDropDirX = new CPOP3DropDir( pIMailMsgProperties, dwRecipCount, pdwRecipIndexes, pNotify );
|
|
|
|
if ( NULL != pDropDirX )
|
|
{
|
|
hr = pDropDirX->DoLocalDelivery();
|
|
if ( MAILMSG_S_PENDING != hr )
|
|
delete pDropDirX;
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSimpleDriver::DoLocalDelivery(
|
|
IMailMsgProperties *pIMailMsgProperties,
|
|
DWORD dwRecipCount,
|
|
DWORD *pdwRecipIndexes
|
|
)
|
|
{
|
|
HRESULT hr = S_OK; //STOREDRV_E_RETRY;
|
|
HRESULT hr2;
|
|
DWORD i;
|
|
WCHAR wszAddress[MAX_PATH];
|
|
char szAddress[MAX_PATH];
|
|
DWORD dwRecipFlags;
|
|
WCHAR wszStoreFileName[MAX_PATH * 2];
|
|
HANDLE hf;
|
|
PFIO_CONTEXT pfio;
|
|
CMailBox mailboxX;
|
|
IMailMsgRecipients *pIMailMsgRecipients;
|
|
SYSTEMTIME st;
|
|
|
|
GetLocalTime( &st );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIMailMsgProperties->QueryInterface(IID_IMailMsgRecipients, (void **) &pIMailMsgRecipients);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
for (i = 0; (SUCCEEDED(hr)) && (i < dwRecipCount); i++)
|
|
{
|
|
hr = pIMailMsgRecipients->GetStringA(pdwRecipIndexes[i], IMMPID_RP_ADDRESS_SMTP, sizeof(szAddress), szAddress);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
if(0 == MultiByteToWideChar(CP_ACP,0, szAddress, -1, wszAddress, sizeof(wszAddress)/sizeof(WCHAR)))
|
|
{
|
|
hr=HRESULT_FROM_WIN32( GetLastError() );
|
|
}
|
|
else if ( mailboxX.OpenMailBox( wszAddress ))
|
|
{
|
|
swprintf( wszStoreFileName, L"%s%04u%02u%02u%02u%02u%02u%04u%08x",
|
|
MAILBOX_PREFIX_W, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, InterlockedIncrement( reinterpret_cast<PLONG>( &s_dwCounter )) );
|
|
hf = mailboxX.CreateMail( wszStoreFileName, FILE_FLAG_OVERLAPPED|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_SEQUENTIAL_SCAN );
|
|
if ( INVALID_HANDLE_VALUE != hf )
|
|
{
|
|
pfio = AssociateFile( hf );
|
|
if ( NULL != pfio )
|
|
{
|
|
hr = pIMailMsgProperties->CopyContentToFileEx( pfio, TRUE, NULL );
|
|
if FAILED( hr )
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_COPYCONTENTTOFILE_FAILED, hr );
|
|
ReleaseContext( pfio );
|
|
}
|
|
else
|
|
{
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_ASSOCIATEFILE_FAILED, GetLastError() );
|
|
CloseHandle( hf );
|
|
}
|
|
if ( ERROR_SUCCESS != mailboxX.CloseMail( NULL, FILE_FLAG_OVERLAPPED ))
|
|
{
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CLOSEMAIL_FAILED );
|
|
hr = (SUCCEEDED(hr)) ? E_FAIL : hr;
|
|
}
|
|
}
|
|
else
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CREATEMAIL_FAILED, GetLastError() );
|
|
mailboxX.CloseMailBox();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr2 = pIMailMsgRecipients->GetDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
|
|
if SUCCEEDED( hr2 )
|
|
{
|
|
dwRecipFlags |= RP_DELIVERED; // mark the recipient as delivered
|
|
hr2 = pIMailMsgRecipients->PutDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
|
|
if FAILED( hr2 )
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
|
|
}
|
|
else
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr2 = pIMailMsgRecipients->GetDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
|
|
if SUCCEEDED( hr2 )
|
|
{
|
|
dwRecipFlags |= RP_FAILED; // mark the recipient as failed
|
|
hr2 = pIMailMsgRecipients->PutDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
|
|
if FAILED( hr2 )
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
|
|
}
|
|
else
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
|
|
}
|
|
}
|
|
else
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_GET_IMMPID_RP_ADDRESS_SMTP_FAILED, hr );
|
|
}
|
|
pIMailMsgRecipients->Release();
|
|
}
|
|
else
|
|
m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_QI_MAILMSGRECIPIENTS_FAILED, hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSimpleDriver::EnumerateAndSubmitMessages( IMailMsgNotify* /*pNotify*/ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
#include "mailmsg_i.c"
|