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.
562 lines
22 KiB
562 lines
22 KiB
// POP3DropDir.cpp: implementation of the POP3DropDir class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "POP3DropDir.h"
|
|
|
|
#include "SimpleDriver.h"
|
|
#include "CSimpleDriver.h"
|
|
#include "mailmsgprops.h"
|
|
|
|
#include <POP3Events.h>
|
|
#include <POP3Server.h>
|
|
#include <POP3RegKeys.h>
|
|
|
|
VOID POP3DropDirReadCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbRead, DWORD dwCompletionStatus );
|
|
VOID POP3DropDirWriteCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbWritten, DWORD dwCompletionStatus );
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CPOP3DropDir::CPOP3DropDir( IMailMsgProperties *pIMailMsgProperties, DWORD dwRecipCount, DWORD *pdwRecipIndexes, IMailMsgNotify *pIMailMsgNotify ) :
|
|
m_pIMailMsgProperties(pIMailMsgProperties), m_pIMailMsgNotify(pIMailMsgNotify), m_pIMailMsgBind(NULL), m_pIMailMsgRecipients(NULL),
|
|
m_pdwRecipIndexes(NULL), m_dwRecipCount(dwRecipCount), m_dwRecipCurrent(0), m_hr( S_OK ), m_enumBWS( NA )
|
|
{
|
|
ZeroMemory( &m_OverlappedRead, sizeof( m_OverlappedRead ));
|
|
ZeroMemory( &m_OverlappedWrite, sizeof( m_OverlappedWrite ));
|
|
m_sStoreFileName[0] = 0;
|
|
m_PFIOContextWrite = NULL;
|
|
if ( NULL != m_pIMailMsgProperties )
|
|
m_pIMailMsgProperties->AddRef();
|
|
if ( NULL != m_pIMailMsgNotify )
|
|
m_pIMailMsgNotify->AddRef();
|
|
if ( 0 != dwRecipCount )
|
|
{
|
|
m_pdwRecipIndexes = new DWORD[dwRecipCount];
|
|
if ( NULL != m_pdwRecipIndexes )
|
|
memcpy( m_pdwRecipIndexes, pdwRecipIndexes, sizeof( DWORD ) * dwRecipCount );
|
|
else
|
|
m_hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
m_hr = E_UNEXPECTED;
|
|
if ( NULL == CSimpleDriver::s_pStoreDriver )
|
|
m_hr = E_POINTER;
|
|
}
|
|
|
|
CPOP3DropDir::~CPOP3DropDir()
|
|
{
|
|
if ( SUCCEEDED( m_hr ))
|
|
MailboxAndContextCleanup( false ); // No value in checking return codes
|
|
else
|
|
{
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_MESSAGEDELIVERY_FAILED, m_hr );
|
|
}
|
|
|
|
if ( NULL != m_pdwRecipIndexes )
|
|
delete [] m_pdwRecipIndexes;
|
|
if ( NULL != m_pIMailMsgRecipients )
|
|
m_pIMailMsgRecipients->Release();
|
|
if ( NULL != m_pIMailMsgBind )
|
|
{
|
|
m_pIMailMsgBind->ReleaseContext();
|
|
m_pIMailMsgBind->Release();
|
|
}
|
|
if ( NULL != m_pIMailMsgProperties )
|
|
m_pIMailMsgProperties->Release();
|
|
if ( NULL != m_pIMailMsgNotify )
|
|
{
|
|
m_pIMailMsgNotify->Notify( m_hr );
|
|
m_pIMailMsgNotify->Release();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Implementation - public
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DoLocalDelivery, public
|
|
//
|
|
// Purpose:
|
|
// Initiate the asynchronous delivery of the current recipient
|
|
//
|
|
// Returns: MAILMSG_S_PENDING on success, an appropriate HRESULT otherwise
|
|
HRESULT CPOP3DropDir::DoLocalDelivery()
|
|
{
|
|
HRESULT hr = m_hr;
|
|
|
|
// May contain error from constructor
|
|
if ( S_OK == hr ) // Get the FIO_CONTEXT for the mail message
|
|
{
|
|
hr = m_pIMailMsgProperties->QueryInterface( IID_IMailMsgBind, reinterpret_cast<LPVOID*>( &m_pIMailMsgBind ));
|
|
if ( S_OK == hr )
|
|
hr = m_pIMailMsgBind->GetBinding( &m_PFIOContextRead, NULL );
|
|
}
|
|
|
|
if ( S_OK == hr )
|
|
{
|
|
hr = m_pIMailMsgProperties->QueryInterface(IID_IMailMsgRecipients, reinterpret_cast<LPVOID*>( &m_pIMailMsgRecipients));
|
|
if ( S_OK == hr ) // About to go Async (CopyMailToDropDir), don't use member variables anymore
|
|
{
|
|
do
|
|
{
|
|
hr = CopyMailToDropDir();
|
|
}
|
|
while ( ERROR_INVALID_MESSAGEDEST == hr );
|
|
}
|
|
else
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_QI_MAILMSGRECIPIENTS_FAILED, hr );
|
|
}
|
|
if ( S_OK == hr )
|
|
return MAILMSG_S_PENDING;
|
|
else if ( FAILED( hr ))
|
|
SetHr( hr );
|
|
|
|
// There was an error so we don't need the Notify interface, release it right now so we don't do it incorrectly in the destrustructor
|
|
if ( NULL != m_pIMailMsgNotify )
|
|
{
|
|
m_pIMailMsgNotify->Release();
|
|
m_pIMailMsgNotify = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Implementation - private
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT CPOP3DropDir::CopyMailToDropDir()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hf = INVALID_HANDLE_VALUE;
|
|
DWORD dwRecipFlags, dwRC;
|
|
IMailMsgRecipients *pIMailMsgRecipients;
|
|
SYSTEMTIME st;
|
|
char szRecpEmailName[sizeof(m_sRecipEmailName)/sizeof(WCHAR)];
|
|
GetLocalTime( &st );
|
|
if ( m_dwRecipCurrent < m_dwRecipCount )
|
|
{
|
|
hr = m_pIMailMsgRecipients->GetStringA(m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_ADDRESS_SMTP, sizeof(szRecpEmailName), szRecpEmailName);
|
|
if ( S_OK == hr )
|
|
{
|
|
if ( 0 == MultiByteToWideChar( CP_ACP, 0, szRecpEmailName, -1, m_sRecipEmailName, sizeof(m_sRecipEmailName)/sizeof(WCHAR) ))
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
else if ( m_mailboxX.OpenMailBox( m_sRecipEmailName ))
|
|
{
|
|
swprintf( m_sStoreFileName, L"%s%04u%02u%02u%02u%02u%02u%04u%08x.eml",
|
|
MAILBOX_PREFIX_W, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, InterlockedIncrement( reinterpret_cast<PLONG>( &CSimpleDriver::s_dwCounter )) );
|
|
dwRC = CSimpleDriver::s_pStoreDriver->m_AdjustTokenPrivilegesX.SetToken();
|
|
if ( ERROR_SUCCESS != dwRC )
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_SETTHREADTOKEN_FAILED, dwRC );
|
|
hr = HRESULT_FROM_WIN32( dwRC );
|
|
}
|
|
hf = m_mailboxX.CreateMail( m_sStoreFileName, FILE_FLAG_OVERLAPPED|FILE_FLAG_SEQUENTIAL_SCAN );
|
|
dwRC = CSimpleDriver::s_pStoreDriver->m_AdjustTokenPrivilegesX.ResetToken(); // Safe to call even if SetToken failed
|
|
if ( ERROR_SUCCESS != dwRC )
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_RESETTHREADTOKEN_FAILED, dwRC );
|
|
m_hr = HRESULT_FROM_WIN32( dwRC );
|
|
}
|
|
if ( INVALID_HANDLE_VALUE != hf )
|
|
{
|
|
m_PFIOContextWrite = AssociateFile( hf );
|
|
if ( NULL != m_PFIOContextWrite )
|
|
{ // Okay let's start the Asynchronous operations - Read first
|
|
m_i64ReadOffset = m_i64WriteOffset = 0;
|
|
hr = ReadFile( m_sBuffer, PRIVATE_OPTIMAL_BUFFER_SIZE );
|
|
}
|
|
else
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_ASSOCIATEFILE_FAILED );
|
|
CloseHandle( hf ); // Will get deleted in desstructor
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
if ( HRESULT_FROM_WIN32( ERROR_DISK_FULL ) == hr )
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, ERROR_DISK_FULL );
|
|
hr = ERROR_INVALID_MESSAGEDEST; // Quota (or really a disk) failure continue with next recipient
|
|
}
|
|
else
|
|
{
|
|
if ( S_OK == hr ) hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CREATEMAIL_FAILED, hr );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hr = ERROR_INVALID_MESSAGEDEST; // Continue with next recipient!
|
|
|
|
if ( S_OK != hr )
|
|
{
|
|
MarkRecipient( RP_FAILED ); // No value in checking return codes
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
if ( ERROR_INVALID_MESSAGEDEST == hr )
|
|
{
|
|
if ( isAllRecipientsProcessed() )
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_GET_IMMPID_RP_ADDRESS_SMTP_FAILED, hr );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
BYTE g_Matrix[256] = { 0,0,0,0,0,0,0,0,0,0,2,0,0,3,0,0, // 00-0F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10-1F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, // 20-2F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30-3F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40-4F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 50-5F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60-6F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 70-7F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80-8F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90-9F
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A0-AF
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B0-BF
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C0-CF
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D0-DF
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E0-EF
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F0-FF
|
|
};
|
|
|
|
HRESULT CPOP3DropDir::DotStuffBuffer( LPVOID *ppbBuffer, LPDWORD pdwSize )
|
|
{
|
|
if ( NULL == ppbBuffer || NULL == pdwSize )
|
|
return E_INVALIDARG;
|
|
if ( 0 == *pdwSize )
|
|
return E_INVALIDARG;
|
|
|
|
DWORD dwSize = *pdwSize;
|
|
bool bStuff = false;
|
|
CHAR *pbBuffer = static_cast<CHAR*>( *ppbBuffer );
|
|
CHAR *pToEnd = m_sBuffer + sizeof( m_sBuffer );
|
|
CHAR *pFromEnd = pbBuffer + dwSize;
|
|
CHAR *pToStart, *pFromStart = NULL;
|
|
CHAR *pChar;
|
|
|
|
for ( pChar = pbBuffer + dwSize - 3; pChar > pbBuffer + 2; pChar -= 3 )
|
|
{
|
|
if ( g_Matrix[static_cast<BYTE>(*pChar)] )
|
|
{ // Found a '\r' '\n' or '.'
|
|
pChar += g_Matrix[static_cast<BYTE>(*pChar)] - 1; // Start at the Dot
|
|
if ( (0xd == *(pChar-2)) && (0xa == *(pChar-1)) && (0x2e == *(pChar)) )
|
|
{ // Stuff Required
|
|
pFromStart = pChar; // Start copy at the Dot
|
|
pToStart = pToEnd - ( pFromEnd - pFromStart );
|
|
memmove( pToStart, pFromStart, pFromEnd - pFromStart );
|
|
pToStart--;
|
|
*pToStart = 0x2e; // Dot stuff
|
|
dwSize++;
|
|
// Reset the pointers
|
|
pFromEnd = pFromStart;
|
|
pToEnd = pToStart;
|
|
}
|
|
}
|
|
}
|
|
if ( NULL != pFromStart ) // Have we Dot stuffed anything yet?
|
|
*pFromStart = 0x0; // yes.
|
|
pChar = pbBuffer;
|
|
if ( g_Matrix[static_cast<BYTE>(*pChar)] )
|
|
{
|
|
if ( (BufferWrapSequence::CR == m_enumBWS) && (0xa == *pChar) && (0x2e == *(pChar+1)) )
|
|
pFromStart = pChar + 1; // Start at the Dot
|
|
else if ( (BufferWrapSequence::CRLF == m_enumBWS) && (0x2e == *pChar) )
|
|
pFromStart = pChar; // Start at the Dot
|
|
else if ( (0xd == *pChar) && (0xa == *(pChar+1)) && (0x2e == *(pChar+2)) )
|
|
pFromStart = pChar+2; // Start at the Dot
|
|
}
|
|
if ( NULL != pFromStart && 0x0 != *pFromStart )
|
|
{ // 1 more stuff required
|
|
pToStart = pToEnd - ( pFromEnd - pFromStart );
|
|
memmove( pToStart, pFromStart, pFromEnd - pFromStart );
|
|
pToStart--;
|
|
*pToStart = 0x2e; // Dot stuff
|
|
dwSize++;
|
|
// Reset the pointers
|
|
pFromEnd = pFromStart;
|
|
pToEnd = pToStart;
|
|
}
|
|
if ( NULL != pFromStart )
|
|
{ // Need to move the beginning of the buffer
|
|
pFromEnd = pFromStart;
|
|
pFromStart = pbBuffer;
|
|
if ( pFromStart != pFromEnd )
|
|
{
|
|
pToStart = pToEnd - ( pFromEnd - pFromStart );
|
|
memmove( pToStart, pFromStart, pFromEnd - pFromStart );
|
|
}
|
|
*ppbBuffer = pToStart;
|
|
*pdwSize = dwSize;
|
|
}
|
|
// Update the Buffer Wrap Sequence
|
|
if ( 0x0d == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 1))
|
|
m_enumBWS = BufferWrapSequence::CR;
|
|
else if ( 0x0d == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 2) && 0x0a == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 1) )
|
|
m_enumBWS = BufferWrapSequence::CRLF;
|
|
else
|
|
m_enumBWS = BufferWrapSequence::NA;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::MailboxAndContextCleanup( bool bDeleteMailFile )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( NULL != m_PFIOContextWrite )
|
|
{
|
|
if ( ERROR_SUCCESS != m_mailboxX.CloseMail( m_PFIOContextWrite->m_hFile,FILE_FLAG_OVERLAPPED ))
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CLOSEMAIL_FAILED );
|
|
hr = E_FAIL;
|
|
}
|
|
ReleaseContext( m_PFIOContextWrite ); // no return void!
|
|
m_PFIOContextWrite = NULL;
|
|
}
|
|
if ( bDeleteMailFile && 0 != m_sStoreFileName[0] )
|
|
m_mailboxX.DeleteMail( m_sStoreFileName );
|
|
m_mailboxX.CloseMailBox(); // no return void!
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::MarkRecipient( DWORD dwMark )
|
|
{
|
|
HRESULT hr;
|
|
DWORD dwRecipFlags;
|
|
|
|
hr = m_pIMailMsgRecipients->GetDWORD( m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
|
|
if ( S_OK == hr )
|
|
{
|
|
dwRecipFlags |= dwMark; // mark the recipient as failed
|
|
hr = m_pIMailMsgRecipients->PutDWORD( m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
|
|
if ( S_OK != hr )
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr );
|
|
}
|
|
else
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr );
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::ReadFile( IN LPVOID pBuffer, IN DWORD cbSize )
|
|
{
|
|
if ( NULL == pBuffer || 0 == cbSize )
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_OverlappedRead.Overlapped.Offset = LODWORD( m_i64ReadOffset );
|
|
m_OverlappedRead.Overlapped.OffsetHigh = HIDWORD( m_i64ReadOffset );
|
|
m_OverlappedRead.Overlapped.pfnCompletion = POP3DropDirReadCompletion;
|
|
m_OverlappedRead.ThisPtr = (PVOID)this;
|
|
|
|
BOOL bRC = FIOReadFile( m_PFIOContextRead, pBuffer, cbSize, &m_OverlappedRead.Overlapped);
|
|
if( !bRC )
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if ( ERROR_IO_PENDING != dwErr )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
if ( dwErr == ERROR_HANDLE_EOF )
|
|
{ // Cleanup
|
|
HRESULT hr2;
|
|
|
|
hr2 = MarkRecipient( RP_DELIVERED );
|
|
if ( S_OK != hr2 )
|
|
hr = hr2;
|
|
hr2 = MailboxAndContextCleanup( false );
|
|
if ( S_OK != hr2 )
|
|
hr = hr2;
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
}
|
|
else
|
|
{
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_READFILE_FAILED, dwErr );
|
|
// Cleanup
|
|
MarkRecipient( RP_FAILED ); // No value in checking return codes
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::ReadFileCompletion( DWORD cbSize, DWORD dwErr, PFH_OVERLAPPED lpo )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (( NO_ERROR != dwErr ) && ( ERROR_HANDLE_EOF != dwErr ))
|
|
{
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_READFILE_FAILED, dwErr );
|
|
// Cleanup
|
|
MarkRecipient( RP_FAILED ); // No value in checking return codes
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
}
|
|
else
|
|
{
|
|
if ( ERROR_HANDLE_EOF == dwErr && 0 == cbSize )
|
|
{ // Cleanup
|
|
HRESULT hr2;
|
|
|
|
hr2 = MarkRecipient( RP_DELIVERED );
|
|
if ( S_OK != hr2 )
|
|
hr = hr2;
|
|
hr2 = MailboxAndContextCleanup( (S_OK == hr) ? false : true );
|
|
if ( S_OK != hr2 )
|
|
hr = hr2;
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
if ( S_OK == hr )
|
|
hr = HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); // Already done reading the file, nothing else to write
|
|
}
|
|
else
|
|
{
|
|
m_i64ReadOffset += cbSize;
|
|
// Asynchronous operation - Write
|
|
hr = WriteFile( m_sBuffer, cbSize );
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::WriteFile( IN LPVOID pBuffer, IN DWORD cbSize )
|
|
{
|
|
if ( NULL == pBuffer || 0 == cbSize )
|
|
return E_INVALIDARG;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = DotStuffBuffer( &pBuffer, &cbSize );
|
|
if ( S_OK == hr )
|
|
{
|
|
m_OverlappedWrite.Overlapped.Offset = LODWORD( m_i64WriteOffset );
|
|
m_OverlappedWrite.Overlapped.OffsetHigh = HIDWORD( m_i64WriteOffset );
|
|
m_OverlappedWrite.Overlapped.pfnCompletion = POP3DropDirWriteCompletion;
|
|
m_OverlappedWrite.ThisPtr = (PVOID)this;
|
|
|
|
BOOL bRC = FIOWriteFile( m_PFIOContextWrite, pBuffer, cbSize, &m_OverlappedWrite.Overlapped);
|
|
if( !bRC )
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
if( dwErr != ERROR_IO_PENDING )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
if ( ERROR_DISK_FULL == dwErr )
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, dwErr );
|
|
else
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_WRITEFILE_FAILED, dwErr );
|
|
// Cleanup
|
|
MarkRecipient( RP_FAILED ); // No value in checking return codes
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CPOP3DropDir::WriteFileCompletion( DWORD cbSize, DWORD dwErr, PFH_OVERLAPPED lpo )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (( dwErr != NO_ERROR ))
|
|
{
|
|
hr = HRESULT_FROM_WIN32( dwErr );
|
|
if ( ERROR_DISK_FULL == dwErr )
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, dwErr );
|
|
else
|
|
CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_WRITEFILE_FAILED, dwErr );
|
|
// Cleanup
|
|
MarkRecipient( RP_FAILED ); // No value in checking return codes
|
|
MailboxAndContextCleanup( true ); // No value in checking return codes
|
|
m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
|
|
}
|
|
else
|
|
{
|
|
m_i64WriteOffset += cbSize;
|
|
// Asynchronous operation - Read
|
|
hr = ReadFile( m_sBuffer, PRIVATE_OPTIMAL_BUFFER_SIZE );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Other
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
VOID POP3DropDirReadCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbRead, DWORD dwCompletionStatus )
|
|
{
|
|
if ( NULL == lpo ) return;
|
|
POP3DROPDIR_OVERLAPPED *p = reinterpret_cast<POP3DROPDIR_OVERLAPPED*>( lpo );
|
|
CPOP3DropDir *pThis = static_cast<CPOP3DropDir*>( p->ThisPtr );
|
|
|
|
HRESULT hr = pThis->ReadFileCompletion( cbRead, dwCompletionStatus, lpo );
|
|
if ( S_OK != hr )
|
|
{
|
|
if ( HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) == hr )
|
|
{
|
|
if ( pThis->isAllRecipientsProcessed( )) // More recipients to process?
|
|
{
|
|
hr = S_OK;
|
|
delete pThis; // Were done!
|
|
}
|
|
else
|
|
hr = pThis->NextRecipientCopyMailToDropDir();
|
|
}
|
|
if ( S_OK != hr )
|
|
{
|
|
pThis->SetHr( hr ); // Unexpected completion, set the error
|
|
delete pThis; // Were done!
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID POP3DropDirWriteCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbWritten, DWORD dwCompletionStatus )
|
|
{
|
|
if ( NULL == lpo ) return;
|
|
POP3DROPDIR_OVERLAPPED *p = reinterpret_cast<POP3DROPDIR_OVERLAPPED*>( lpo );
|
|
CPOP3DropDir *pThis = static_cast<CPOP3DropDir*>( p->ThisPtr );
|
|
|
|
HRESULT hr = pThis->WriteFileCompletion( cbWritten, dwCompletionStatus, lpo );
|
|
if ( S_OK != hr )
|
|
{
|
|
if ( pThis->isAllRecipientsProcessed( )) // More recipients to process?
|
|
{
|
|
hr = S_OK;
|
|
delete pThis; // Were done!
|
|
}
|
|
else
|
|
hr = pThis->NextRecipientCopyMailToDropDir();
|
|
if ( S_OK != hr )
|
|
{
|
|
pThis->SetHr( hr ); // Unexpected completion, set the error
|
|
delete pThis; // Were done!
|
|
}
|
|
}
|
|
}
|
|
|
|
|