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.

263 lines
10 KiB

  1. // CSimpleDriver.cpp : Implementation of CCSimpleDriver
  2. #include "stdafx.h"
  3. #include "SimpleDriver.h"
  4. #include "CSimpleDriver.h"
  5. #include "POP3DropDir.h"
  6. #include <stdio.h>
  7. #include "mailmsgprops.h"
  8. #include <IMFUtil.h>
  9. #include <MailBox.h>
  10. #include <POP3Events.h>
  11. #include <POP3Server.h>
  12. #include <POP3RegKeys.h>
  13. //#include <winerror.h>
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CCSimpleDriver
  16. CStoreDriverCriticalSection g_oSDCS;
  17. CSimpleDriver *CSimpleDriver::s_pStoreDriver = NULL;
  18. DWORD CSimpleDriver::s_dwCounter = 0;
  19. /////////////////////////////////////////////////////////////////////////////
  20. // constructor/destructor
  21. CSimpleDriver::CSimpleDriver() :
  22. m_fInit(FALSE), m_lPrepareForShutdown(0)
  23. {
  24. m_szComputerName[0] = 0x0;
  25. }
  26. CSimpleDriver::~CSimpleDriver()
  27. {
  28. EnterCriticalSection(&g_oSDCS.s_csStoreDriver);
  29. if (s_pStoreDriver == this)
  30. s_pStoreDriver = NULL;
  31. LeaveCriticalSection(&g_oSDCS.s_csStoreDriver);
  32. }
  33. /////////////////////////////////////////////////////////////////////////////
  34. // ISMTPStoreDriver
  35. HRESULT CSimpleDriver::Init( DWORD /*dwInstance*/, IUnknown* /*pBinding*/, IUnknown* /*pServer*/, DWORD /*dwReason*/, IUnknown **ppStoreDriver )
  36. {
  37. if (m_fInit) return HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
  38. if ( 0 != m_lPrepareForShutdown ) return HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS);
  39. #if DBG == 1
  40. TCHAR buf[255];
  41. _stprintf(buf, _T( "new CSimpleDriver 0x%x, refcount = %x\n" ), this);
  42. OutputDebugString(buf);
  43. #endif
  44. EnterCriticalSection(&g_oSDCS.s_csStoreDriver); // returns void
  45. // smtpsvc may call the Init function on a store driver multiple
  46. // times for the same instance. It expects an initialized
  47. // store driver to be returned via ppStoreDriver. To prevent
  48. // multiple store drivers from being created for the same instance
  49. // we use s_pStoreDriver to hold a pointer to the one valid
  50. // store driver. If this variable is currently NULL then we create
  51. // a store driver which we can return.
  52. //
  53. // If a store driver needs to support being used by multiple
  54. // SMTP instances then you need to maintain a list of store drivers,
  55. // one per instance.
  56. if (!s_pStoreDriver)
  57. {
  58. DWORD dwSize, dwRC;
  59. DWORD dwLoggingLevel = 3;
  60. CMailBox mailboxX;
  61. mailboxX.SetMailRoot(); // Do this to refresh the static CMailBox::m_szMailRoot
  62. assert( NULL == s_pStoreDriver );
  63. dwSize = sizeof( m_szComputerName );
  64. GetComputerNameA( m_szComputerName, &dwSize );
  65. m_fInit = TRUE;
  66. s_pStoreDriver = this;
  67. m_EventLoggerX.InitEventLog( POP3_SERVER_NAME, EVENTCAT_POP3STOREDRIVER );
  68. if ( ERROR_SUCCESS == RegQueryLoggingLevel( dwLoggingLevel ))
  69. m_EventLoggerX.SetLoggingLevel( dwLoggingLevel );
  70. m_EventLoggerX.LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_STARTED );
  71. // Duplicate the Process token we'll need it to ENABLE SE_RESTORE_NAME privileges when creating mail
  72. dwRC = m_AdjustTokenPrivilegesX.DuplicateProcessToken( SE_RESTORE_NAME, SE_PRIVILEGE_ENABLED );
  73. if ( ERROR_SUCCESS != dwRC )
  74. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_DUPLICATEPROCESSTOKEN_FAILED, dwRC );
  75. }
  76. // tell it about the one good store driver
  77. s_pStoreDriver->AddRef();
  78. *ppStoreDriver = (IUnknown *) (ISMTPStoreDriver*) s_pStoreDriver;
  79. // in failure case handles are cleaned up in destructor
  80. LeaveCriticalSection(&g_oSDCS.s_csStoreDriver);
  81. return S_OK;
  82. }
  83. HRESULT CSimpleDriver::PrepareForShutdown( DWORD /*dwReason*/ )
  84. {
  85. InterlockedExchange( &m_lPrepareForShutdown, 1 );
  86. return S_OK;
  87. }
  88. HRESULT CSimpleDriver::Shutdown( DWORD /*dwReason*/ )
  89. {
  90. if (m_fInit)
  91. m_fInit = FALSE;
  92. m_EventLoggerX.LogEvent( LOGTYPE_INFORMATION, POP3_SMTPSINK_STOPPED );
  93. return S_OK;
  94. }
  95. //
  96. // This function directly called DoLocalDelivery in the simple case, or
  97. // adds the local delivery request to the queue if we support async
  98. // requests
  99. //
  100. HRESULT CSimpleDriver::LocalDelivery(
  101. IMailMsgProperties *pIMailMsgProperties,
  102. DWORD dwRecipCount,
  103. DWORD *pdwRecipIndexes,
  104. IMailMsgNotify *pNotify
  105. )
  106. {
  107. if ( NULL == pIMailMsgProperties || NULL == pdwRecipIndexes ) return E_INVALIDARG;
  108. HRESULT hr;
  109. if ( NULL == pNotify )
  110. { // do the local delivery - synchronously
  111. hr = DoLocalDelivery(pIMailMsgProperties, dwRecipCount, pdwRecipIndexes);
  112. }
  113. else
  114. { // do the local delivery - asynchronously
  115. CPOP3DropDir *pDropDirX = new CPOP3DropDir( pIMailMsgProperties, dwRecipCount, pdwRecipIndexes, pNotify );
  116. if ( NULL != pDropDirX )
  117. {
  118. hr = pDropDirX->DoLocalDelivery();
  119. if ( MAILMSG_S_PENDING != hr )
  120. delete pDropDirX;
  121. }
  122. else
  123. hr = E_OUTOFMEMORY;
  124. }
  125. return hr;
  126. }
  127. HRESULT CSimpleDriver::DoLocalDelivery(
  128. IMailMsgProperties *pIMailMsgProperties,
  129. DWORD dwRecipCount,
  130. DWORD *pdwRecipIndexes
  131. )
  132. {
  133. HRESULT hr = S_OK; //STOREDRV_E_RETRY;
  134. HRESULT hr2;
  135. DWORD i;
  136. WCHAR wszAddress[MAX_PATH];
  137. char szAddress[MAX_PATH];
  138. DWORD dwRecipFlags;
  139. WCHAR wszStoreFileName[MAX_PATH * 2];
  140. HANDLE hf;
  141. PFIO_CONTEXT pfio;
  142. CMailBox mailboxX;
  143. IMailMsgRecipients *pIMailMsgRecipients;
  144. SYSTEMTIME st;
  145. GetLocalTime( &st );
  146. if (SUCCEEDED(hr))
  147. {
  148. hr = pIMailMsgProperties->QueryInterface(IID_IMailMsgRecipients, (void **) &pIMailMsgRecipients);
  149. if (SUCCEEDED(hr))
  150. {
  151. for (i = 0; (SUCCEEDED(hr)) && (i < dwRecipCount); i++)
  152. {
  153. hr = pIMailMsgRecipients->GetStringA(pdwRecipIndexes[i], IMMPID_RP_ADDRESS_SMTP, sizeof(szAddress), szAddress);
  154. if (SUCCEEDED(hr))
  155. {
  156. if(0 == MultiByteToWideChar(CP_ACP,0, szAddress, -1, wszAddress, sizeof(wszAddress)/sizeof(WCHAR)))
  157. {
  158. hr=HRESULT_FROM_WIN32( GetLastError() );
  159. }
  160. else if ( mailboxX.OpenMailBox( wszAddress ))
  161. {
  162. swprintf( wszStoreFileName, L"%s%04u%02u%02u%02u%02u%02u%04u%08x",
  163. MAILBOX_PREFIX_W, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, InterlockedIncrement( reinterpret_cast<PLONG>( &s_dwCounter )) );
  164. hf = mailboxX.CreateMail( wszStoreFileName, FILE_FLAG_OVERLAPPED|FILE_FLAG_WRITE_THROUGH|FILE_FLAG_SEQUENTIAL_SCAN );
  165. if ( INVALID_HANDLE_VALUE != hf )
  166. {
  167. pfio = AssociateFile( hf );
  168. if ( NULL != pfio )
  169. {
  170. hr = pIMailMsgProperties->CopyContentToFileEx( pfio, TRUE, NULL );
  171. if FAILED( hr )
  172. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_COPYCONTENTTOFILE_FAILED, hr );
  173. ReleaseContext( pfio );
  174. }
  175. else
  176. {
  177. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_ASSOCIATEFILE_FAILED, GetLastError() );
  178. CloseHandle( hf );
  179. }
  180. if ( ERROR_SUCCESS != mailboxX.CloseMail( NULL, FILE_FLAG_OVERLAPPED ))
  181. {
  182. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CLOSEMAIL_FAILED );
  183. hr = (SUCCEEDED(hr)) ? E_FAIL : hr;
  184. }
  185. }
  186. else
  187. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_CREATEMAIL_FAILED, GetLastError() );
  188. mailboxX.CloseMailBox();
  189. if (SUCCEEDED(hr))
  190. {
  191. hr2 = pIMailMsgRecipients->GetDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
  192. if SUCCEEDED( hr2 )
  193. {
  194. dwRecipFlags |= RP_DELIVERED; // mark the recipient as delivered
  195. hr2 = pIMailMsgRecipients->PutDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
  196. if FAILED( hr2 )
  197. m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
  198. }
  199. else
  200. m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
  201. }
  202. }
  203. else
  204. {
  205. hr2 = pIMailMsgRecipients->GetDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, &dwRecipFlags );
  206. if SUCCEEDED( hr2 )
  207. {
  208. dwRecipFlags |= RP_FAILED; // mark the recipient as failed
  209. hr2 = pIMailMsgRecipients->PutDWORD( pdwRecipIndexes[i], IMMPID_RP_RECIPIENT_FLAGS, dwRecipFlags );
  210. if FAILED( hr2 )
  211. m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_PUT_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
  212. }
  213. else
  214. m_EventLoggerX.LogEvent( LOGTYPE_ERR_WARNING, POP3_SMTPSINK_GET_IMMPID_RP_RECIPIENT_FLAGS_FAILED, hr2 );
  215. }
  216. }
  217. else
  218. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_GET_IMMPID_RP_ADDRESS_SMTP_FAILED, hr );
  219. }
  220. pIMailMsgRecipients->Release();
  221. }
  222. else
  223. m_EventLoggerX.LogEvent( LOGTYPE_ERR_CRITICAL, POP3_SMTPSINK_QI_MAILMSGRECIPIENTS_FAILED, hr );
  224. }
  225. return hr;
  226. }
  227. HRESULT CSimpleDriver::EnumerateAndSubmitMessages( IMailMsgNotify* /*pNotify*/ )
  228. {
  229. return S_OK;
  230. }
  231. #include "mailmsg_i.c"