Leaked source code of windows server 2003
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

  1. // POP3DropDir.cpp: implementation of the POP3DropDir class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "stdafx.h"
  5. #include "POP3DropDir.h"
  6. #include "SimpleDriver.h"
  7. #include "CSimpleDriver.h"
  8. #include "mailmsgprops.h"
  9. #include <POP3Events.h>
  10. #include <POP3Server.h>
  11. #include <POP3RegKeys.h>
  12. VOID POP3DropDirReadCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbRead, DWORD dwCompletionStatus );
  13. VOID POP3DropDirWriteCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbWritten, DWORD dwCompletionStatus );
  14. //////////////////////////////////////////////////////////////////////
  15. // Construction/Destruction
  16. //////////////////////////////////////////////////////////////////////
  17. CPOP3DropDir::CPOP3DropDir( IMailMsgProperties *pIMailMsgProperties, DWORD dwRecipCount, DWORD *pdwRecipIndexes, IMailMsgNotify *pIMailMsgNotify ) :
  18. m_pIMailMsgProperties(pIMailMsgProperties), m_pIMailMsgNotify(pIMailMsgNotify), m_pIMailMsgBind(NULL), m_pIMailMsgRecipients(NULL),
  19. m_pdwRecipIndexes(NULL), m_dwRecipCount(dwRecipCount), m_dwRecipCurrent(0), m_hr( S_OK ), m_enumBWS( NA )
  20. {
  21. ZeroMemory( &m_OverlappedRead, sizeof( m_OverlappedRead ));
  22. ZeroMemory( &m_OverlappedWrite, sizeof( m_OverlappedWrite ));
  23. m_sStoreFileName[0] = 0;
  24. m_PFIOContextWrite = NULL;
  25. if ( NULL != m_pIMailMsgProperties )
  26. m_pIMailMsgProperties->AddRef();
  27. if ( NULL != m_pIMailMsgNotify )
  28. m_pIMailMsgNotify->AddRef();
  29. if ( 0 != dwRecipCount )
  30. {
  31. m_pdwRecipIndexes = new DWORD[dwRecipCount];
  32. if ( NULL != m_pdwRecipIndexes )
  33. memcpy( m_pdwRecipIndexes, pdwRecipIndexes, sizeof( DWORD ) * dwRecipCount );
  34. else
  35. m_hr = E_OUTOFMEMORY;
  36. }
  37. else
  38. m_hr = E_UNEXPECTED;
  39. if ( NULL == CSimpleDriver::s_pStoreDriver )
  40. m_hr = E_POINTER;
  41. }
  42. CPOP3DropDir::~CPOP3DropDir()
  43. {
  44. if ( SUCCEEDED( m_hr ))
  45. MailboxAndContextCleanup( false ); // No value in checking return codes
  46. else
  47. {
  48. MailboxAndContextCleanup( true ); // No value in checking return codes
  49. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_MESSAGEDELIVERY_FAILED, m_hr );
  50. }
  51. if ( NULL != m_pdwRecipIndexes )
  52. delete [] m_pdwRecipIndexes;
  53. if ( NULL != m_pIMailMsgRecipients )
  54. m_pIMailMsgRecipients->Release();
  55. if ( NULL != m_pIMailMsgBind )
  56. {
  57. m_pIMailMsgBind->ReleaseContext();
  58. m_pIMailMsgBind->Release();
  59. }
  60. if ( NULL != m_pIMailMsgProperties )
  61. m_pIMailMsgProperties->Release();
  62. if ( NULL != m_pIMailMsgNotify )
  63. {
  64. m_pIMailMsgNotify->Notify( m_hr );
  65. m_pIMailMsgNotify->Release();
  66. }
  67. }
  68. //////////////////////////////////////////////////////////////////////
  69. // Implementation - public
  70. //////////////////////////////////////////////////////////////////////
  71. /////////////////////////////////////////////////////////////////////////////
  72. // DoLocalDelivery, public
  73. //
  74. // Purpose:
  75. // Initiate the asynchronous delivery of the current recipient
  76. //
  77. // Returns: MAILMSG_S_PENDING on success, an appropriate HRESULT otherwise
  78. HRESULT CPOP3DropDir::DoLocalDelivery()
  79. {
  80. HRESULT hr = m_hr;
  81. // May contain error from constructor
  82. if ( S_OK == hr ) // Get the FIO_CONTEXT for the mail message
  83. {
  84. hr = m_pIMailMsgProperties->QueryInterface( IID_IMailMsgBind, reinterpret_cast<LPVOID*>( &m_pIMailMsgBind ));
  85. if ( S_OK == hr )
  86. hr = m_pIMailMsgBind->GetBinding( &m_PFIOContextRead, NULL );
  87. }
  88. if ( S_OK == hr )
  89. {
  90. hr = m_pIMailMsgProperties->QueryInterface(IID_IMailMsgRecipients, reinterpret_cast<LPVOID*>( &m_pIMailMsgRecipients));
  91. if ( S_OK == hr ) // About to go Async (CopyMailToDropDir), don't use member variables anymore
  92. {
  93. do
  94. {
  95. hr = CopyMailToDropDir();
  96. }
  97. while ( ERROR_INVALID_MESSAGEDEST == hr );
  98. }
  99. else
  100. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_QI_MAILMSGRECIPIENTS_FAILED, hr );
  101. }
  102. if ( S_OK == hr )
  103. return MAILMSG_S_PENDING;
  104. else if ( FAILED( hr ))
  105. SetHr( hr );
  106. // 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
  107. if ( NULL != m_pIMailMsgNotify )
  108. {
  109. m_pIMailMsgNotify->Release();
  110. m_pIMailMsgNotify = NULL;
  111. }
  112. return hr;
  113. }
  114. //////////////////////////////////////////////////////////////////////
  115. // Implementation - private
  116. //////////////////////////////////////////////////////////////////////
  117. HRESULT CPOP3DropDir::CopyMailToDropDir()
  118. {
  119. HRESULT hr = E_FAIL;
  120. HANDLE hf = INVALID_HANDLE_VALUE;
  121. DWORD dwRecipFlags, dwRC;
  122. IMailMsgRecipients *pIMailMsgRecipients;
  123. SYSTEMTIME st;
  124. char szRecpEmailName[sizeof(m_sRecipEmailName)/sizeof(WCHAR)];
  125. GetLocalTime( &st );
  126. if ( m_dwRecipCurrent < m_dwRecipCount )
  127. {
  128. hr = m_pIMailMsgRecipients->GetStringA(m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_ADDRESS_SMTP, sizeof(szRecpEmailName), szRecpEmailName);
  129. if ( S_OK == hr )
  130. {
  131. if ( 0 == MultiByteToWideChar( CP_ACP, 0, szRecpEmailName, -1, m_sRecipEmailName, sizeof(m_sRecipEmailName)/sizeof(WCHAR) ))
  132. hr = HRESULT_FROM_WIN32( GetLastError() );
  133. else if ( m_mailboxX.OpenMailBox( m_sRecipEmailName ))
  134. {
  135. swprintf( m_sStoreFileName, L"%s%04u%02u%02u%02u%02u%02u%04u%08x.eml",
  136. MAILBOX_PREFIX_W, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, InterlockedIncrement( reinterpret_cast<PLONG>( &CSimpleDriver::s_dwCounter )) );
  137. dwRC = CSimpleDriver::s_pStoreDriver->m_AdjustTokenPrivilegesX.SetToken();
  138. if ( ERROR_SUCCESS != dwRC )
  139. {
  140. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_SETTHREADTOKEN_FAILED, dwRC );
  141. hr = HRESULT_FROM_WIN32( dwRC );
  142. }
  143. hf = m_mailboxX.CreateMail( m_sStoreFileName, FILE_FLAG_OVERLAPPED|FILE_FLAG_SEQUENTIAL_SCAN );
  144. dwRC = CSimpleDriver::s_pStoreDriver->m_AdjustTokenPrivilegesX.ResetToken(); // Safe to call even if SetToken failed
  145. if ( ERROR_SUCCESS != dwRC )
  146. {
  147. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_RESETTHREADTOKEN_FAILED, dwRC );
  148. m_hr = HRESULT_FROM_WIN32( dwRC );
  149. }
  150. if ( INVALID_HANDLE_VALUE != hf )
  151. {
  152. m_PFIOContextWrite = AssociateFile( hf );
  153. if ( NULL != m_PFIOContextWrite )
  154. { // Okay let's start the Asynchronous operations - Read first
  155. m_i64ReadOffset = m_i64WriteOffset = 0;
  156. hr = ReadFile( m_sBuffer, PRIVATE_OPTIMAL_BUFFER_SIZE );
  157. }
  158. else
  159. {
  160. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_ASSOCIATEFILE_FAILED );
  161. CloseHandle( hf ); // Will get deleted in desstructor
  162. hr = E_FAIL;
  163. }
  164. }
  165. else
  166. {
  167. hr = HRESULT_FROM_WIN32( GetLastError() );
  168. if ( HRESULT_FROM_WIN32( ERROR_DISK_FULL ) == hr )
  169. {
  170. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, ERROR_DISK_FULL );
  171. hr = ERROR_INVALID_MESSAGEDEST; // Quota (or really a disk) failure continue with next recipient
  172. }
  173. else
  174. {
  175. if ( S_OK == hr ) hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  176. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CREATEMAIL_FAILED, hr );
  177. }
  178. }
  179. }
  180. else
  181. hr = ERROR_INVALID_MESSAGEDEST; // Continue with next recipient!
  182. if ( S_OK != hr )
  183. {
  184. MarkRecipient( RP_FAILED ); // No value in checking return codes
  185. MailboxAndContextCleanup( true ); // No value in checking return codes
  186. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  187. if ( ERROR_INVALID_MESSAGEDEST == hr )
  188. {
  189. if ( isAllRecipientsProcessed() )
  190. hr = S_FALSE;
  191. }
  192. }
  193. }
  194. else
  195. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_GET_IMMPID_RP_ADDRESS_SMTP_FAILED, hr );
  196. }
  197. return hr;
  198. }
  199. BYTE g_Matrix[256] = { 0,0,0,0,0,0,0,0,0,0,2,0,0,3,0,0, // 00-0F
  200. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 10-1F
  201. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0, // 20-2F
  202. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 30-3F
  203. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40-4F
  204. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 50-5F
  205. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60-6F
  206. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 70-7F
  207. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 80-8F
  208. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 90-9F
  209. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // A0-AF
  210. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // B0-BF
  211. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // C0-CF
  212. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // D0-DF
  213. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // E0-EF
  214. 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // F0-FF
  215. };
  216. HRESULT CPOP3DropDir::DotStuffBuffer( LPVOID *ppbBuffer, LPDWORD pdwSize )
  217. {
  218. if ( NULL == ppbBuffer || NULL == pdwSize )
  219. return E_INVALIDARG;
  220. if ( 0 == *pdwSize )
  221. return E_INVALIDARG;
  222. DWORD dwSize = *pdwSize;
  223. bool bStuff = false;
  224. CHAR *pbBuffer = static_cast<CHAR*>( *ppbBuffer );
  225. CHAR *pToEnd = m_sBuffer + sizeof( m_sBuffer );
  226. CHAR *pFromEnd = pbBuffer + dwSize;
  227. CHAR *pToStart, *pFromStart = NULL;
  228. CHAR *pChar;
  229. for ( pChar = pbBuffer + dwSize - 3; pChar > pbBuffer + 2; pChar -= 3 )
  230. {
  231. if ( g_Matrix[static_cast<BYTE>(*pChar)] )
  232. { // Found a '\r' '\n' or '.'
  233. pChar += g_Matrix[static_cast<BYTE>(*pChar)] - 1; // Start at the Dot
  234. if ( (0xd == *(pChar-2)) && (0xa == *(pChar-1)) && (0x2e == *(pChar)) )
  235. { // Stuff Required
  236. pFromStart = pChar; // Start copy at the Dot
  237. pToStart = pToEnd - ( pFromEnd - pFromStart );
  238. memmove( pToStart, pFromStart, pFromEnd - pFromStart );
  239. pToStart--;
  240. *pToStart = 0x2e; // Dot stuff
  241. dwSize++;
  242. // Reset the pointers
  243. pFromEnd = pFromStart;
  244. pToEnd = pToStart;
  245. }
  246. }
  247. }
  248. if ( NULL != pFromStart ) // Have we Dot stuffed anything yet?
  249. *pFromStart = 0x0; // yes.
  250. pChar = pbBuffer;
  251. if ( g_Matrix[static_cast<BYTE>(*pChar)] )
  252. {
  253. if ( (BufferWrapSequence::CR == m_enumBWS) && (0xa == *pChar) && (0x2e == *(pChar+1)) )
  254. pFromStart = pChar + 1; // Start at the Dot
  255. else if ( (BufferWrapSequence::CRLF == m_enumBWS) && (0x2e == *pChar) )
  256. pFromStart = pChar; // Start at the Dot
  257. else if ( (0xd == *pChar) && (0xa == *(pChar+1)) && (0x2e == *(pChar+2)) )
  258. pFromStart = pChar+2; // Start at the Dot
  259. }
  260. if ( NULL != pFromStart && 0x0 != *pFromStart )
  261. { // 1 more stuff required
  262. pToStart = pToEnd - ( pFromEnd - pFromStart );
  263. memmove( pToStart, pFromStart, pFromEnd - pFromStart );
  264. pToStart--;
  265. *pToStart = 0x2e; // Dot stuff
  266. dwSize++;
  267. // Reset the pointers
  268. pFromEnd = pFromStart;
  269. pToEnd = pToStart;
  270. }
  271. if ( NULL != pFromStart )
  272. { // Need to move the beginning of the buffer
  273. pFromEnd = pFromStart;
  274. pFromStart = pbBuffer;
  275. if ( pFromStart != pFromEnd )
  276. {
  277. pToStart = pToEnd - ( pFromEnd - pFromStart );
  278. memmove( pToStart, pFromStart, pFromEnd - pFromStart );
  279. }
  280. *ppbBuffer = pToStart;
  281. *pdwSize = dwSize;
  282. }
  283. // Update the Buffer Wrap Sequence
  284. if ( 0x0d == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 1))
  285. m_enumBWS = BufferWrapSequence::CR;
  286. else if ( 0x0d == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 2) && 0x0a == *( static_cast<CHAR*>(*ppbBuffer) + dwSize - 1) )
  287. m_enumBWS = BufferWrapSequence::CRLF;
  288. else
  289. m_enumBWS = BufferWrapSequence::NA;
  290. return S_OK;
  291. }
  292. HRESULT CPOP3DropDir::MailboxAndContextCleanup( bool bDeleteMailFile )
  293. {
  294. HRESULT hr = S_OK;
  295. if ( NULL != m_PFIOContextWrite )
  296. {
  297. if ( ERROR_SUCCESS != m_mailboxX.CloseMail( m_PFIOContextWrite->m_hFile,FILE_FLAG_OVERLAPPED ))
  298. {
  299. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CLOSEMAIL_FAILED );
  300. hr = E_FAIL;
  301. }
  302. ReleaseContext( m_PFIOContextWrite ); // no return void!
  303. m_PFIOContextWrite = NULL;
  304. }
  305. if ( bDeleteMailFile && 0 != m_sStoreFileName[0] )
  306. m_mailboxX.DeleteMail( m_sStoreFileName );
  307. m_mailboxX.CloseMailBox(); // no return void!
  308. return hr;
  309. }
  310. HRESULT CPOP3DropDir::MarkRecipient( DWORD dwMark )
  311. {
  312. HRESULT hr;
  313. DWORD dwRecipFlags;
  314. hr = m_pIMailMsgRecipients->GetDWORD( m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
  315. if ( S_OK == hr )
  316. {
  317. dwRecipFlags |= dwMark; // mark the recipient as failed
  318. hr = m_pIMailMsgRecipients->PutDWORD( m_pdwRecipIndexes[m_dwRecipCurrent], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
  319. if ( S_OK != hr )
  320. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr );
  321. }
  322. else
  323. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr );
  324. return hr;
  325. }
  326. HRESULT CPOP3DropDir::ReadFile( IN LPVOID pBuffer, IN DWORD cbSize )
  327. {
  328. if ( NULL == pBuffer || 0 == cbSize )
  329. return E_INVALIDARG;
  330. HRESULT hr = S_OK;
  331. m_OverlappedRead.Overlapped.Offset = LODWORD( m_i64ReadOffset );
  332. m_OverlappedRead.Overlapped.OffsetHigh = HIDWORD( m_i64ReadOffset );
  333. m_OverlappedRead.Overlapped.pfnCompletion = POP3DropDirReadCompletion;
  334. m_OverlappedRead.ThisPtr = (PVOID)this;
  335. BOOL bRC = FIOReadFile( m_PFIOContextRead, pBuffer, cbSize, &m_OverlappedRead.Overlapped);
  336. if( !bRC )
  337. {
  338. DWORD dwErr = GetLastError();
  339. if ( ERROR_IO_PENDING != dwErr )
  340. {
  341. hr = HRESULT_FROM_WIN32( dwErr );
  342. if ( dwErr == ERROR_HANDLE_EOF )
  343. { // Cleanup
  344. HRESULT hr2;
  345. hr2 = MarkRecipient( RP_DELIVERED );
  346. if ( S_OK != hr2 )
  347. hr = hr2;
  348. hr2 = MailboxAndContextCleanup( false );
  349. if ( S_OK != hr2 )
  350. hr = hr2;
  351. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  352. }
  353. else
  354. {
  355. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_READFILE_FAILED, dwErr );
  356. // Cleanup
  357. MarkRecipient( RP_FAILED ); // No value in checking return codes
  358. MailboxAndContextCleanup( true ); // No value in checking return codes
  359. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  360. }
  361. }
  362. }
  363. return hr;
  364. }
  365. HRESULT CPOP3DropDir::ReadFileCompletion( DWORD cbSize, DWORD dwErr, PFH_OVERLAPPED lpo )
  366. {
  367. HRESULT hr = S_OK;
  368. if (( NO_ERROR != dwErr ) && ( ERROR_HANDLE_EOF != dwErr ))
  369. {
  370. hr = HRESULT_FROM_WIN32( dwErr );
  371. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_READFILE_FAILED, dwErr );
  372. // Cleanup
  373. MarkRecipient( RP_FAILED ); // No value in checking return codes
  374. MailboxAndContextCleanup( true ); // No value in checking return codes
  375. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  376. }
  377. else
  378. {
  379. if ( ERROR_HANDLE_EOF == dwErr && 0 == cbSize )
  380. { // Cleanup
  381. HRESULT hr2;
  382. hr2 = MarkRecipient( RP_DELIVERED );
  383. if ( S_OK != hr2 )
  384. hr = hr2;
  385. hr2 = MailboxAndContextCleanup( (S_OK == hr) ? false : true );
  386. if ( S_OK != hr2 )
  387. hr = hr2;
  388. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  389. if ( S_OK == hr )
  390. hr = HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ); // Already done reading the file, nothing else to write
  391. }
  392. else
  393. {
  394. m_i64ReadOffset += cbSize;
  395. // Asynchronous operation - Write
  396. hr = WriteFile( m_sBuffer, cbSize );
  397. }
  398. }
  399. return hr;
  400. }
  401. HRESULT CPOP3DropDir::WriteFile( IN LPVOID pBuffer, IN DWORD cbSize )
  402. {
  403. if ( NULL == pBuffer || 0 == cbSize )
  404. return E_INVALIDARG;
  405. HRESULT hr = S_OK;
  406. hr = DotStuffBuffer( &pBuffer, &cbSize );
  407. if ( S_OK == hr )
  408. {
  409. m_OverlappedWrite.Overlapped.Offset = LODWORD( m_i64WriteOffset );
  410. m_OverlappedWrite.Overlapped.OffsetHigh = HIDWORD( m_i64WriteOffset );
  411. m_OverlappedWrite.Overlapped.pfnCompletion = POP3DropDirWriteCompletion;
  412. m_OverlappedWrite.ThisPtr = (PVOID)this;
  413. BOOL bRC = FIOWriteFile( m_PFIOContextWrite, pBuffer, cbSize, &m_OverlappedWrite.Overlapped);
  414. if( !bRC )
  415. {
  416. DWORD dwErr = GetLastError();
  417. if( dwErr != ERROR_IO_PENDING )
  418. {
  419. hr = HRESULT_FROM_WIN32( dwErr );
  420. if ( ERROR_DISK_FULL == dwErr )
  421. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, dwErr );
  422. else
  423. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_WRITEFILE_FAILED, dwErr );
  424. // Cleanup
  425. MarkRecipient( RP_FAILED ); // No value in checking return codes
  426. MailboxAndContextCleanup( true ); // No value in checking return codes
  427. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  428. }
  429. }
  430. }
  431. return hr;
  432. }
  433. HRESULT CPOP3DropDir::WriteFileCompletion( DWORD cbSize, DWORD dwErr, PFH_OVERLAPPED lpo )
  434. {
  435. HRESULT hr = S_OK;
  436. if (( dwErr != NO_ERROR ))
  437. {
  438. hr = HRESULT_FROM_WIN32( dwErr );
  439. if ( ERROR_DISK_FULL == dwErr )
  440. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_MESSAGEDELIERY_FAILED_OUTOFDISK, dwErr );
  441. else
  442. CSimpleDriver::s_pStoreDriver->LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_WRITEFILE_FAILED, dwErr );
  443. // Cleanup
  444. MarkRecipient( RP_FAILED ); // No value in checking return codes
  445. MailboxAndContextCleanup( true ); // No value in checking return codes
  446. m_dwRecipCurrent++; // Completion routine will re-initiate process for next recipient.
  447. }
  448. else
  449. {
  450. m_i64WriteOffset += cbSize;
  451. // Asynchronous operation - Read
  452. hr = ReadFile( m_sBuffer, PRIVATE_OPTIMAL_BUFFER_SIZE );
  453. }
  454. return hr;
  455. }
  456. //////////////////////////////////////////////////////////////////////
  457. // Other
  458. //////////////////////////////////////////////////////////////////////
  459. VOID POP3DropDirReadCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbRead, DWORD dwCompletionStatus )
  460. {
  461. if ( NULL == lpo ) return;
  462. POP3DROPDIR_OVERLAPPED *p = reinterpret_cast<POP3DROPDIR_OVERLAPPED*>( lpo );
  463. CPOP3DropDir *pThis = static_cast<CPOP3DropDir*>( p->ThisPtr );
  464. HRESULT hr = pThis->ReadFileCompletion( cbRead, dwCompletionStatus, lpo );
  465. if ( S_OK != hr )
  466. {
  467. if ( HRESULT_FROM_WIN32( ERROR_HANDLE_EOF ) == hr )
  468. {
  469. if ( pThis->isAllRecipientsProcessed( )) // More recipients to process?
  470. {
  471. hr = S_OK;
  472. delete pThis; // Were done!
  473. }
  474. else
  475. hr = pThis->NextRecipientCopyMailToDropDir();
  476. }
  477. if ( S_OK != hr )
  478. {
  479. pThis->SetHr( hr ); // Unexpected completion, set the error
  480. delete pThis; // Were done!
  481. }
  482. }
  483. }
  484. VOID POP3DropDirWriteCompletion( PFIO_CONTEXT pContext, PFH_OVERLAPPED lpo, DWORD cbWritten, DWORD dwCompletionStatus )
  485. {
  486. if ( NULL == lpo ) return;
  487. POP3DROPDIR_OVERLAPPED *p = reinterpret_cast<POP3DROPDIR_OVERLAPPED*>( lpo );
  488. CPOP3DropDir *pThis = static_cast<CPOP3DropDir*>( p->ThisPtr );
  489. HRESULT hr = pThis->WriteFileCompletion( cbWritten, dwCompletionStatus, lpo );
  490. if ( S_OK != hr )
  491. {
  492. if ( pThis->isAllRecipientsProcessed( )) // More recipients to process?
  493. {
  494. hr = S_OK;
  495. delete pThis; // Were done!
  496. }
  497. else
  498. hr = pThis->NextRecipientCopyMailToDropDir();
  499. if ( S_OK != hr )
  500. {
  501. pThis->SetHr( hr ); // Unexpected completion, set the error
  502. delete pThis; // Were done!
  503. }
  504. }
  505. }