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.

517 lines
15 KiB

  1. /************************************************************************************************
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name: POP3Svc.hxx.
  4. Abstract: Implement the CPop3Svc class.
  5. Notes:
  6. History:
  7. ************************************************************************************************/
  8. #include "stdafx.h"
  9. #include <POP3Regkeys.h>
  10. #include <isexchng.h>
  11. #include <AuthID.h>
  12. #include "pop3Auth_i.c"
  13. // CService-derived class, must have this, as described in POP3Svc.hxx and Service.h
  14. IMPLEMENT_SERVICE(CPop3Svc, POP3SVC)
  15. BOOL CheckValidGreeting(WCHAR *wszGreeting)
  16. {
  17. if(NULL==wszGreeting)
  18. {
  19. return TRUE;
  20. }
  21. while(L'\0'!= *wszGreeting)
  22. {
  23. if(!iswprint(*wszGreeting) ||
  24. (L'<'== (*wszGreeting))||
  25. (L'>'== (*wszGreeting)) )
  26. {
  27. return FALSE;
  28. }
  29. wszGreeting++;
  30. }
  31. return TRUE;
  32. }
  33. CPop3Svc::CPop3Svc(LPCTSTR szName, LPCTSTR szDisplay, DWORD dwType):
  34. CService(szName, szDisplay, dwType)
  35. {
  36. // CService-derived class, must have this, as described in Service.h
  37. IMPLEMENT_STATIC_REFERENCE();
  38. }
  39. void CPop3Svc::Run()
  40. {
  41. // Main service, do the timeout checking here
  42. DWORD dwTimeToWait=DEFAULT_TIME_OUT;
  43. DWORD dwWaitResult;
  44. HANDLE pHdArray[2]={m_hServiceEvent[STOP], g_hDoSEvent};
  45. BOOL bIsAnyTimedOut;
  46. while(1)
  47. {
  48. dwWaitResult=WaitForMultipleObjects(2, pHdArray,FALSE,dwTimeToWait);
  49. if(WAIT_TIMEOUT == dwWaitResult)
  50. {
  51. dwTimeToWait=DEFAULT_TIME_OUT -
  52. g_BusyList.CheckTimeOut(DEFAULT_TIME_OUT);
  53. }
  54. else if( WAIT_OBJECT_0 + 1 == dwWaitResult ) // g_hDoSEvent
  55. {
  56. ResetEvent(g_hDoSEvent);
  57. bIsAnyTimedOut=FALSE;
  58. DWORD dwRunCount=3; //Run this 3 times at most
  59. while( (!bIsAnyTimedOut) &&
  60. g_SocketPool.IsMaxSocketUsed()
  61. && dwRunCount>0) //Extra check needed for the last connection
  62. {
  63. dwTimeToWait=DEFAULT_TIME_OUT-
  64. g_BusyList.CheckTimeOut(SHORTENED_TIMEOUT, &bIsAnyTimedOut);
  65. dwRunCount--;
  66. Sleep(SHORTENED_TIMEOUT);
  67. }
  68. }
  69. else if( WAIT_OBJECT_0 == dwWaitResult ) //Shutdown
  70. {
  71. break;
  72. }
  73. else
  74. {
  75. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  76. EVENT_POP3_UNEXPECTED_ERROR);
  77. AbortService();
  78. break;
  79. }
  80. }
  81. }
  82. void CPop3Svc::OnStop(DWORD dwErrorCode)
  83. {
  84. if(0 == dwErrorCode)
  85. {
  86. g_EventLogger.LogEvent(LOGTYPE_INFORMATION,
  87. EVENT_POP3_SERVER_STOPPED);
  88. }
  89. else
  90. {
  91. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  92. EVENT_POP3_SERVER_STOP_ERROR, dwErrorCode);
  93. }
  94. g_dwServerStatus=SERVICE_STOPPED;
  95. SetStatus(SERVICE_STOPPED);
  96. }
  97. void CPop3Svc::OnAfterStart()
  98. {
  99. //More operation should be added here
  100. SetStatus(SERVICE_RUNNING,
  101. 0,
  102. 0,
  103. SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE);
  104. g_dwServerStatus=SERVICE_RUNNING;
  105. g_EventLogger.LogEvent(LOGTYPE_INFORMATION,
  106. EVENT_POP3_SERVER_STARTED);
  107. }
  108. void CPop3Svc::OnStopRequest()
  109. {
  110. g_dwServerStatus=SERVICE_STOP_PENDING;
  111. SetStatus(SERVICE_STOP_PENDING, 1, 30000);
  112. }
  113. void CPop3Svc::PreInit()
  114. {
  115. CService::PreInit();
  116. WCHAR wszMailRoot[POP3_MAX_MAILROOT_LENGTH];
  117. HKEY hPop3Key;
  118. DWORD dwType=REG_DWORD;
  119. DWORD cbSize=sizeof(DWORD);
  120. DWORD dwThreadPerCPU=0;
  121. DWORD dwMaxSockets=0;
  122. DWORD dwMinSockets=0;
  123. DWORD dwPort=0;
  124. DWORD dwThreshold=0;
  125. DWORD dwBacklog=0;
  126. DWORD dwLoggingLevel=LOGGING_LEVEL_3;
  127. LONG lErr;
  128. IAuthMethods *pAuthMethods=NULL;
  129. HRESULT hr=S_OK;
  130. VARIANT vCurAuth;
  131. VariantInit(&vCurAuth);
  132. DWORD dwSize=MAX_PATH;
  133. g_dwServerStatus=SERVICE_START_PENDING;
  134. if ( 0 == RegQueryLoggingLevel(dwLoggingLevel) )
  135. {
  136. if(dwLoggingLevel > LOGGING_LEVEL_3 )
  137. {
  138. dwLoggingLevel = LOGGING_LEVEL_3;
  139. }
  140. }
  141. if ( 0 != g_EventLogger.InitEventLog(POP3_SERVICE_NAME ,0, (LOGLEVEL)dwLoggingLevel) )
  142. {
  143. AbortService();
  144. }
  145. if (_IsExchangeInstalled())
  146. {
  147. //We can not start if Exchange is installed
  148. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  149. POP3SVR_START_FAILED_EXCHANGE);
  150. AbortService();
  151. }
  152. //Init the PerfMon Conters
  153. hr= g_PerfCounters.HrInit(cntrMaxGlobalCntrs,
  154. szPOP3PerfMem,
  155. POP3_SERVICE_NAME);
  156. if( S_OK != hr )
  157. {
  158. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  159. EVENT_POP3_NO_CONFIG_DATA);
  160. AbortService();
  161. }
  162. g_hShutDown=CreateEvent(NULL, TRUE, FALSE, NULL);
  163. if( NULL == g_hShutDown )
  164. {
  165. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  166. POP3SVR_INIT_CREATE_EVENT_FAILED,
  167. GetLastError());
  168. AbortService();
  169. }
  170. g_hDoSEvent=CreateEvent(NULL, TRUE, FALSE, NULL);
  171. if( NULL == g_hDoSEvent )
  172. {
  173. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  174. POP3SVR_INIT_CREATE_EVENT_FAILED,
  175. GetLastError());
  176. AbortService();
  177. }
  178. if( ERROR_SUCCESS== RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  179. POP3SERVICE_SERVICES_SUBKEY,
  180. 0,
  181. KEY_READ,
  182. &hPop3Key) )
  183. {
  184. lErr = RegQueryValueEx( hPop3Key,
  185. VALUENAME_THREADCOUNT,
  186. NULL,
  187. &dwType,
  188. (LPBYTE)&dwThreadPerCPU,
  189. &cbSize);
  190. if(ERROR_SUCCESS==lErr)
  191. {
  192. lErr = RegQueryValueEx( hPop3Key,
  193. VALUENAME_MAX,
  194. NULL,
  195. &dwType,
  196. (LPBYTE)&dwMaxSockets,
  197. &cbSize);
  198. }
  199. if(ERROR_SUCCESS==lErr)
  200. {
  201. lErr = RegQueryValueEx( hPop3Key,
  202. VALUENAME_MIN,
  203. NULL,
  204. &dwType,
  205. (LPBYTE)&dwMinSockets,
  206. &cbSize);
  207. }
  208. if(ERROR_SUCCESS==lErr)
  209. {
  210. lErr = RegQueryValueEx( hPop3Key,
  211. VALUENAME_THRESHOLD,
  212. NULL,
  213. &dwType,
  214. (LPBYTE)&dwThreshold,
  215. &cbSize);
  216. }
  217. if(ERROR_SUCCESS==lErr)
  218. {
  219. lErr = RegQueryValueEx( hPop3Key,
  220. VALUENAME_BACKLOG,
  221. NULL,
  222. &dwType,
  223. (LPBYTE)&dwBacklog,
  224. &cbSize);
  225. }
  226. if(ERROR_SUCCESS==lErr)
  227. {
  228. lErr = RegQueryValueEx( hPop3Key,
  229. VALUENAME_PORT,
  230. NULL,
  231. &dwType,
  232. (LPBYTE)&dwPort,
  233. &cbSize);
  234. if (ERROR_SUCCESS!=lErr)
  235. {
  236. dwPort=110;
  237. lErr=ERROR_SUCCESS;
  238. }
  239. lErr = RegQueryValueEx( hPop3Key,
  240. VALUENAME_SOCK_VERSION,
  241. NULL,
  242. &dwType,
  243. (LPBYTE)&g_dwIPVersion,
  244. &cbSize);
  245. if (ERROR_SUCCESS!=lErr)
  246. {
  247. g_dwIPVersion=4;
  248. lErr=ERROR_SUCCESS;
  249. }
  250. lErr = RegQueryValueEx( hPop3Key,
  251. VALUENAME_MAXMSG_PERDOWNLOAD,
  252. NULL,
  253. &dwType,
  254. (LPBYTE) &g_dwMaxMsgPerDnld,
  255. &cbSize);
  256. if (ERROR_SUCCESS!=lErr)
  257. {
  258. g_dwMaxMsgPerDnld=DEFAULT_MAX_MSG_PER_DNLD;
  259. lErr=ERROR_SUCCESS;
  260. }
  261. }
  262. RegCloseKey(hPop3Key);
  263. }
  264. if( ERROR_SUCCESS == lErr )
  265. {
  266. lErr= RegQueryMailRoot( wszMailRoot, sizeof( wszMailRoot )/sizeof( WCHAR));
  267. }
  268. if( ERROR_SUCCESS == lErr )
  269. {
  270. lErr= RegQueryGreeting( g_wszGreeting, sizeof(g_wszGreeting));
  271. if(ERROR_SUCCESS == lErr)
  272. {
  273. //All characters in the greetings must be valid
  274. if(!CheckValidGreeting(g_wszGreeting))
  275. {
  276. g_wszGreeting[0]=0;
  277. }
  278. }
  279. else
  280. {
  281. g_wszGreeting[0]=0;
  282. }
  283. lErr= RegQuerySPARequired(g_dwRequireSPA);
  284. if(ERROR_SUCCESS != lErr)
  285. {
  286. g_dwRequireSPA=0;
  287. lErr=ERROR_SUCCESS;
  288. }
  289. }
  290. if( ERROR_SUCCESS!=lErr )
  291. {
  292. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  293. EVENT_POP3_NO_CONFIG_DATA);
  294. AbortService();
  295. }
  296. if(0==UnicodeToAnsi(g_szMailRoot, sizeof(g_szMailRoot)/sizeof(char), wszMailRoot, -1))
  297. {
  298. //We limit the mailroot to be less than POP3_MAX_MAILROOT_LENGTH characters
  299. //in all languages.
  300. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  301. EVENT_POP3_NO_CONFIG_DATA);
  302. AbortService();
  303. }
  304. if( !CMailBox::SetMailRoot(wszMailRoot) )
  305. {
  306. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  307. EVENT_POP3_NO_CONFIG_DATA);
  308. AbortService();
  309. }
  310. dwSize=sizeof(g_wszComputerName)/sizeof(WCHAR);
  311. if( !GetComputerNameExW(ComputerNameDnsFullyQualified,
  312. g_wszComputerName,
  313. &dwSize))
  314. {
  315. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  316. EVENT_POP3_NO_CONFIG_DATA);
  317. AbortService();
  318. }
  319. if( FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)) )
  320. {
  321. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  322. EVENT_POP3_COM_INIT_FAIL);
  323. AbortService();
  324. }
  325. hr=CoCreateInstance(CLSID_AuthMethods,
  326. NULL,
  327. CLSCTX_INPROC_SERVER,
  328. IID_IAuthMethods,
  329. (LPVOID *)&pAuthMethods);
  330. if(SUCCEEDED(hr))
  331. {
  332. hr=pAuthMethods->get_CurrentAuthMethod(&vCurAuth);
  333. if(SUCCEEDED(hr))
  334. {
  335. hr=pAuthMethods->get_Item(vCurAuth, &g_pAuthMethod);
  336. if(FAILED(hr) || NULL == g_pAuthMethod)
  337. {
  338. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  339. POP3SVR_INIT_AUTH_METHOD_FAILED);
  340. AbortService();
  341. }
  342. }
  343. else
  344. {
  345. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  346. POP3SVR_AUTH_METHOD_INVALID);
  347. AbortService();
  348. }
  349. BSTR bstrAuthMethod=NULL;
  350. hr=g_pAuthMethod->get_ID(&bstrAuthMethod);
  351. if(SUCCEEDED(hr))
  352. {
  353. if(0==wcscmp(bstrAuthMethod,SZ_AUTH_ID_LOCAL_SAM))
  354. {
  355. g_dwAuthMethod=AUTH_LOCAL_SAM;
  356. }
  357. else if(0==wcscmp(bstrAuthMethod,SZ_AUTH_ID_DOMAIN_AD))
  358. {
  359. g_dwAuthMethod=AUTH_AD;
  360. }
  361. else
  362. {
  363. g_dwAuthMethod=AUTH_OTHER;
  364. }
  365. SysFreeString(bstrAuthMethod);
  366. }
  367. pAuthMethods->Release();
  368. }
  369. else //CoCreate Failed
  370. {
  371. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  372. POP3SVR_INIT_AUTH_METHOD_FAILED);
  373. AbortService();
  374. }
  375. //Some Auth methods may not need these
  376. //Ignore return values.
  377. VARIANT vMailRoot;
  378. vMailRoot.vt=VT_BSTR;
  379. vMailRoot.bstrVal=SysAllocString(wszMailRoot);
  380. if(NULL == vMailRoot.bstrVal)
  381. {
  382. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  383. POP3SVR_NOT_ENOUGH_MEMORY);
  384. AbortService();
  385. }
  386. g_pAuthMethod->Put(SZ_PROPNAME_MAIL_ROOT, vMailRoot);
  387. VariantClear(&vMailRoot);
  388. //Initialize the NTLM\Kerberos
  389. hr=CAuthServer::GlobalInit();
  390. if(S_OK!=hr)
  391. {
  392. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,
  393. POP3SVR_NO_SECURITY_INIT_FAIL,hr);
  394. AbortService();
  395. }
  396. if( !g_ThreadPool.Initialize(dwThreadPerCPU) )
  397. {
  398. //Eventlogging is done in the thread pool code
  399. AbortService();
  400. }
  401. if( !g_SocketPool.Initialize(dwMaxSockets,
  402. dwMinSockets,
  403. dwThreshold,
  404. dwPort,
  405. dwBacklog) )
  406. {
  407. AbortService();
  408. }
  409. }
  410. void CPop3Svc::DeInit()
  411. {
  412. g_ThreadPool.Uninitialize();
  413. g_SocketPool.Uninitialize();
  414. g_BusyList.Cleanup();
  415. g_FreeList.Cleanup();
  416. //The following must be called after all
  417. //Pop3Context are released
  418. CAuthServer::GlobalUninit();
  419. if(NULL != g_pAuthMethod)
  420. {
  421. g_pAuthMethod->Release();
  422. g_pAuthMethod=NULL;
  423. }
  424. //Shutdown perf conters
  425. g_PerfCounters.Shutdown();
  426. CoUninitialize();
  427. //Signal the watch thread to stop
  428. SetEvent(g_hShutDown);
  429. CService::DeInit();
  430. CloseHandle(g_hShutDown);
  431. CloseHandle(g_hDoSEvent);
  432. OnStop(ERROR_SUCCESS);
  433. }
  434. void CPop3Svc::OnPause()
  435. {
  436. g_dwServerStatus=SERVICE_PAUSED;
  437. SetStatus(SERVICE_PAUSED);
  438. }
  439. void CPop3Svc::OnContinueRequest()
  440. {
  441. g_dwServerStatus=SERVICE_RUNNING;
  442. SetStatus(SERVICE_RUNNING);
  443. //Since no new sockets are created when service is paused,
  444. //We need to check in new sockets are needed
  445. if( g_SocketPool.IsMoreSocketsNeeded() )
  446. {
  447. if(!g_SocketPool.AddSockets())
  448. {
  449. g_EventLogger.LogEvent(LOGTYPE_ERR_CRITICAL,POP3SVR_CREATE_ADDITIONAL_SOCKET_FAILED);
  450. }
  451. }
  452. }