MainWin.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:13k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "UsrUtils.h"
  28. #include "SvrUtils.h"
  29. #include "MessQueue.h"
  30. #include "SMAILUtils.h"
  31. #include "QueueUtils.h"
  32. #include "AppDefines.h"
  33. #include "MailSvr.h"
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //  Comment this statement if You want a normal startup ( not as a service )
  36. ///////////////////////////////////////////////////////////////////////////////
  37. #define SERVICE
  38. #define NULFILE         "nul"
  39. #ifndef SERVICE
  40. ///////////////////////////////////////////////////////////////////////////////
  41. //  Normal startup
  42. ///////////////////////////////////////////////////////////////////////////////
  43. int main(int iArgCount, char *pszArgs[])
  44. {
  45. return (SvrMain(iArgCount, pszArgs));
  46. }
  47. #else // #ifndef SERVICE
  48. ///////////////////////////////////////////////////////////////////////////////
  49. //  Service startup
  50. ///////////////////////////////////////////////////////////////////////////////
  51. #define SZDEPENDENCIES              _T("Tcpip")
  52. #define SERVER_START_WAIT           8000
  53. #define SERVER_STOP_WAIT            4000
  54. static int MnSetupStdHandles(void);
  55. static VOID WINAPI ServiceCtrl(DWORD dwCtrlCode);
  56. static VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR lpszArgv[]);
  57. static BOOL CmdInstallService(DWORD dwStartType);
  58. static BOOL CmdRemoveService(void);
  59. static int CmdDebugService(int argc, TCHAR * argv[]);
  60. static BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
  61. static LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize);
  62. static VOID AddToMessageLog(LPCTSTR lpszMsg);
  63. static int GetServiceNameFromModule(LPCTSTR pszModule, LPTSTR pszName, int iSize);
  64. static SERVICE_STATUS ssStatus;
  65. static SERVICE_STATUS_HANDLE sshStatusHandle = NULL;
  66. static DWORD dwErr = 0;
  67. static BOOL bDebug = FALSE;
  68. static TCHAR szErr[2048] = _T("");
  69. static TCHAR szServicePath[MAX_PATH] = _T("");
  70. static TCHAR szServiceName[128] = _T("");
  71. static TCHAR szServiceDispName[256] = _T("");
  72. static int MnSetupStdHandles(void)
  73. {
  74. HANDLE hInFile = CreateFile(NULFILE, GENERIC_READ | GENERIC_WRITE,
  75.     FILE_SHARE_READ | FILE_SHARE_WRITE,
  76.     NULL, OPEN_EXISTING, 0, NULL);
  77. if (hInFile == INVALID_HANDLE_VALUE) {
  78. AddToMessageLog(_T("CreateFile"));
  79. return (-1);
  80. }
  81. HANDLE hOutFile = CreateFile(NULFILE, GENERIC_READ | GENERIC_WRITE,
  82.      FILE_SHARE_READ | FILE_SHARE_WRITE,
  83.      NULL, OPEN_EXISTING, 0, NULL);
  84. if (hOutFile == INVALID_HANDLE_VALUE) {
  85. AddToMessageLog(_T("CreateFile"));
  86. CloseHandle(hInFile);
  87. return (-1);
  88. }
  89. HANDLE hErrFile = CreateFile(NULFILE, GENERIC_READ | GENERIC_WRITE,
  90.      FILE_SHARE_READ | FILE_SHARE_WRITE,
  91.      NULL, OPEN_EXISTING, 0, NULL);
  92. if (hErrFile == INVALID_HANDLE_VALUE) {
  93. AddToMessageLog(_T("CreateFile"));
  94. CloseHandle(hOutFile);
  95. CloseHandle(hInFile);
  96. return (-1);
  97. }
  98. if (!SetStdHandle(STD_INPUT_HANDLE, hInFile) || !SetStdHandle(STD_OUTPUT_HANDLE, hOutFile)
  99.     || !SetStdHandle(STD_ERROR_HANDLE, hErrFile)) {
  100. AddToMessageLog(_T("SetStdHandle"));
  101. CloseHandle(hErrFile);
  102. CloseHandle(hOutFile);
  103. CloseHandle(hInFile);
  104. return (-1);
  105. }
  106. return (0);
  107. }
  108. int _tmain(int argc, TCHAR * argv[])
  109. {
  110. if (GetModuleFileName(NULL, szServicePath, CountOf(szServicePath)) == 0) {
  111. _tprintf(_T("Unable to get module name - %sn"),
  112.  GetLastErrorText(szErr, CountOf(szErr)));
  113. return (1);
  114. }
  115. GetServiceNameFromModule(szServicePath, szServiceName, CountOf(szServiceName));
  116. _stprintf(szServiceDispName, _T("%s Server"), szServiceName);
  117. SERVICE_TABLE_ENTRY DispTable[] = {
  118. {szServiceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain}
  119. ,
  120. {NULL, NULL}
  121. };
  122. if (argc > 1) {
  123. if (_tcsicmp(_T("--install"), argv[1]) == 0) {
  124. CmdInstallService(SERVICE_DEMAND_START);
  125. return (0);
  126. }
  127. if (_tcsicmp(_T("--install-auto"), argv[1]) == 0) {
  128. CmdInstallService(SERVICE_AUTO_START);
  129. return (0);
  130. } else if (_tcsicmp(_T("--remove"), argv[1]) == 0) {
  131. CmdRemoveService();
  132. return (0);
  133. } else if (_tcsicmp(_T("--debug"), argv[1]) == 0) {
  134. bDebug = TRUE;
  135. CmdDebugService(argc, argv);
  136. return (0);
  137. }
  138. }
  139. _tprintf(_T("%s --install          = Install the servicen"), argv[0]);
  140. _tprintf(_T("%s --remove           = Remove the servicen"), argv[0]);
  141. _tprintf(_T("%s --debug [params]   = Run as a console app for debuggingn"), argv[0]);
  142. _tprintf(_T("nStartServiceCtrlDispatcher being called.n"));
  143. _tprintf(_T("This may take several seconds.  Please wait.n"));
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //  Setup std handles
  146. ///////////////////////////////////////////////////////////////////////////////
  147. if (MnSetupStdHandles() < 0)
  148. return (1);
  149. ///////////////////////////////////////////////////////////////////////////////
  150. //  Service loop
  151. ///////////////////////////////////////////////////////////////////////////////
  152. if (!StartServiceCtrlDispatcher(DispTable))
  153. AddToMessageLog(_T("StartServiceCtrlDispatcher"));
  154. return (0);
  155. }
  156. static void WINAPI ServiceMain(DWORD dwArgc, LPTSTR lpszArgv[])
  157. {
  158. if ((sshStatusHandle = RegisterServiceCtrlHandler(szServiceName, ServiceCtrl)) != NULL) {
  159. ZeroData(ssStatus);
  160. ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
  161. ssStatus.dwServiceSpecificExitCode = 0;
  162. if (ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, SERVER_START_WAIT)) {
  163. ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0);
  164. ///////////////////////////////////////////////////////////////////////////////
  165. //  Run server
  166. ///////////////////////////////////////////////////////////////////////////////
  167. int iSvrResult = SvrMain((int) dwArgc, lpszArgv);
  168. if (iSvrResult < 0) {
  169. AddToMessageLog(ErrGetErrorString(iSvrResult));
  170. }
  171. }
  172. ReportStatusToSCMgr(SERVICE_STOPPED, dwErr, 0);
  173. } else
  174. AddToMessageLog(_T("RegisterServiceCtrlHandler"));
  175. }
  176. static VOID WINAPI ServiceCtrl(DWORD dwCtrlCode)
  177. {
  178. switch (dwCtrlCode) {
  179. case (SERVICE_CONTROL_SHUTDOWN):
  180. case (SERVICE_CONTROL_STOP):
  181. {
  182. ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, SERVER_STOP_WAIT);
  183. ///////////////////////////////////////////////////////////////////////////////
  184. //  Signal the server to stop and wait for completion
  185. ///////////////////////////////////////////////////////////////////////////////
  186. SvrStopServer(false);
  187. while (SvrInShutdown()) {
  188. Sleep(SERVER_STOP_WAIT / 2);
  189. ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR,
  190.     SERVER_STOP_WAIT);
  191. }
  192. ReportStatusToSCMgr(SERVICE_STOPPED, 0, 0);
  193. }
  194. break;
  195. default:
  196. ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
  197. }
  198. }
  199. static BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
  200. {
  201. static DWORD dwCheckPoint = 1;
  202. BOOL bResult = TRUE;
  203. if (!bDebug) {
  204. if (dwCurrentState == SERVICE_START_PENDING)
  205. ssStatus.dwControlsAccepted = 0;
  206. else
  207. ssStatus.dwControlsAccepted =
  208.     SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  209. ssStatus.dwCurrentState = dwCurrentState;
  210. ssStatus.dwWin32ExitCode = dwWin32ExitCode;
  211. ssStatus.dwWaitHint = dwWaitHint;
  212. if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
  213. ssStatus.dwCheckPoint = 0;
  214. else
  215. ssStatus.dwCheckPoint = dwCheckPoint++;
  216. if (!(bResult = SetServiceStatus(sshStatusHandle, &ssStatus)))
  217. AddToMessageLog(_T("SetServiceStatus"));
  218. }
  219. return (bResult);
  220. }
  221. static VOID AddToMessageLog(LPCTSTR lpszMsg)
  222. {
  223. HANDLE hEventSource = NULL;
  224. LPTSTR lpszStrings[2];
  225. TCHAR szMsg[512] = _T("");
  226. TCHAR szErrMsg[2048] = _T("");
  227. if (!bDebug) {
  228. dwErr = GetLastError();
  229. GetLastErrorText(szErr, CountOf(szErr));
  230. _stprintf(szMsg, _T("%s error: %d"), szServiceName, dwErr);
  231. _stprintf(szErrMsg, _T("{%s}: %s"), lpszMsg, szErr);
  232. lpszStrings[0] = szMsg;
  233. lpszStrings[1] = szErrMsg;
  234. if ((hEventSource = RegisterEventSource(NULL, szServiceName)) != NULL) {
  235. ReportEvent(hEventSource, // handle of event source
  236.     EVENTLOG_ERROR_TYPE, // event type
  237.     0, // event category
  238.     0, // event ID
  239.     NULL, // current user's SID
  240.     2, // strings in lpszStrings
  241.     0, // no bytes of raw data
  242.     (const char **) lpszStrings, // array of error strings
  243.     NULL); // no raw data
  244. DeregisterEventSource(hEventSource);
  245. }
  246. }
  247. }
  248. static BOOL CmdInstallService(DWORD dwStartType)
  249. {
  250. SC_HANDLE schService = NULL;
  251. SC_HANDLE schSCManager = NULL;
  252. if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) != NULL) {
  253. schService = CreateService(schSCManager, // SCManager database
  254.    szServiceName, // name of service
  255.    szServiceDispName, // name to display
  256.    SERVICE_ALL_ACCESS, // desired access
  257.    SERVICE_WIN32_OWN_PROCESS, // service type
  258.    dwStartType, // start type
  259.    SERVICE_ERROR_NORMAL, // error control type
  260.    szServicePath, // service's binary
  261.    NULL, // no load ordering group
  262.    NULL, // no tag identifier
  263.    SZDEPENDENCIES, // dependencies
  264.    NULL, // LocalSystem account
  265.    NULL); // no password
  266. if (schService != NULL) {
  267. _tprintf(_T("%s installed.n"), szServiceDispName);
  268. CloseServiceHandle(schService);
  269. CloseServiceHandle(schSCManager);
  270. return (TRUE);
  271. } else
  272. _tprintf(_T("CreateService failed - %sn"),
  273.  GetLastErrorText(szErr, CountOf(szErr)));
  274. CloseServiceHandle(schSCManager);
  275. } else
  276. _tprintf(_T("OpenSCManager failed - %sn"),
  277.  GetLastErrorText(szErr, CountOf(szErr)));
  278. return (FALSE);
  279. }
  280. static BOOL CmdRemoveService(void)
  281. {
  282. SC_HANDLE schService = NULL;
  283. SC_HANDLE schSCManager = NULL;
  284. if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) != NULL) {
  285. schService = OpenService(schSCManager, szServiceName, SERVICE_ALL_ACCESS);
  286. if (schService != NULL) {
  287. if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) {
  288. _tprintf(_T("Stopping %s."), szServiceDispName);
  289. Sleep(1000);
  290. while (QueryServiceStatus(schService, &ssStatus)) {
  291. if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
  292. _tprintf(_T("."));
  293. Sleep(1000);
  294. } else
  295. break;
  296. }
  297. if (ssStatus.dwCurrentState == SERVICE_STOPPED)
  298. _tprintf(_T("n%s stopped.n"), szServiceDispName);
  299. else
  300. _tprintf(_T("n%s failed to stop.n"), szServiceDispName);
  301. }
  302. if (DeleteService(schService)) {
  303. _tprintf(_T("%s removed.n"), szServiceDispName);
  304. CloseServiceHandle(schService);
  305. CloseServiceHandle(schSCManager);
  306. return (TRUE);
  307. } else
  308. _tprintf(_T("DeleteService failed - %sn"),
  309.  GetLastErrorText(szErr, CountOf(szErr)));
  310. CloseServiceHandle(schService);
  311. } else
  312. _tprintf(_T("OpenService failed - %sn"),
  313.  GetLastErrorText(szErr, CountOf(szErr)));
  314. CloseServiceHandle(schSCManager);
  315. } else
  316. _tprintf(_T("OpenSCManager failed - %sn"),
  317.  GetLastErrorText(szErr, CountOf(szErr)));
  318. return (FALSE);
  319. }
  320. static int CmdDebugService(int argc, LPTSTR argv[])
  321. {
  322. _tprintf(_T("Debugging %s.n"), szServiceDispName);
  323. ///////////////////////////////////////////////////////////////////////////////
  324. //  Run server
  325. ///////////////////////////////////////////////////////////////////////////////
  326. return (SvrMain(argc, argv));
  327. }
  328. static LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
  329. {
  330. DWORD dwRet;
  331. DWORD dwError = GetLastError();
  332. LPTSTR lpszTemp = NULL;
  333. dwRet =
  334.     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
  335.   FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, dwError, LANG_NEUTRAL,
  336.   (LPTSTR) & lpszTemp, 0, NULL);
  337. if ((dwRet == 0) || ((long) dwSize < (long) (dwRet + 14)))
  338. lpszBuf[0] = TCHAR('');
  339. else {
  340. lpszTemp[lstrlen(lpszTemp) - 2] = TCHAR('');
  341. _stprintf(lpszBuf, _T("%s (0x%x)"), lpszTemp, dwError);
  342. }
  343. if (lpszTemp != NULL)
  344. LocalFree((HLOCAL) lpszTemp);
  345. return (lpszBuf);
  346. }
  347. static int GetServiceNameFromModule(LPCTSTR pszModule, LPTSTR pszName, int iSize)
  348. {
  349. LPCTSTR pszSlash;
  350. LPCTSTR pszDot;
  351. if ((pszSlash = _tcsrchr(pszModule, (TCHAR) '\')) == NULL)
  352. pszSlash = pszModule;
  353. else
  354. pszSlash++;
  355. if ((pszDot = _tcschr(pszSlash, (TCHAR) '.')) == NULL)
  356. pszDot = pszSlash + _tcslen(pszSlash);
  357. iSize = Min(iSize - 1, (int) (pszDot - pszSlash));
  358. Cpy2Sz(pszName, pszSlash, iSize);
  359. return (0);
  360. }
  361. #endif // #ifndef SERVICE