Source code of Windows XP (NT5)
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.

431 lines
11 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1995 **/
  4. /**********************************************************************/
  5. /*
  6. main.cxx
  7. This module contains the main startup code for a Gibraltar Service.
  8. Since gibraltar service startup is a common operation, this source
  9. code will be shared with all services.
  10. To do this, you only need to set certain #defines to your specific service.
  11. See %MSNROOT%\apps\mail\[pop3,smtp]\server\main.cxx for examples.
  12. FILE HISTORY:
  13. KeithMo 07-Mar-1993 Created.
  14. rkamicar 20-Dec-1995 Modified for sharing
  15. */
  16. //
  17. // Private globals.
  18. //
  19. DEFINE_TSVC_INFO_INTERFACE();
  20. DECLARE_DEBUG_PRINTS_OBJECT( );
  21. DECLARE_DEBUG_VARIABLE( );
  22. #define INITIALIZE_IPC 0x00000001
  23. #define INITIALIZE_SOCKETS 0x00000002
  24. #define INITIALIZE_ACCESS 0x00000004
  25. #define INITIALIZE_SERVICE 0x00000008
  26. #define INITIALIZE_CONNECTIONS 0x00000010
  27. #define INITIALIZE_DISCOVERY 0x00000020
  28. DWORD GlobalInitializeStatus = 0;
  29. BOOL ServiceBooted = FALSE;
  30. //
  31. // Global startup named event
  32. //
  33. HANDLE ghStartupEvent = INVALID_HANDLE_VALUE;
  34. //
  35. //
  36. // Shared TCPSVCS.EXE data
  37. //
  38. PTCPSVCS_GLOBAL_DATA pTcpsvcsGlobalData;
  39. //
  40. // Private prototypes.
  41. //
  42. APIERR InitializeService( LPVOID pContext );
  43. APIERR TerminateService( LPVOID pContext );
  44. //+---------------------------------------------------------------------------
  45. //
  46. // Function:
  47. //
  48. // DllEntryPoint
  49. //
  50. // Synopsis:
  51. // Arguments:
  52. // Returns:
  53. // See Win32 SDK
  54. //
  55. // History:
  56. //
  57. // Richard Kamicar (rkamicar) 5 January 1996
  58. //
  59. // Notes:
  60. //
  61. // If we find we need this per service, we can move it out of here..
  62. //
  63. //----------------------------------------------------------------------------
  64. BOOL WINAPI
  65. DllEntryPoint(HINSTANCE hInst, DWORD dwReason, LPVOID lpvContext)
  66. {
  67. switch (dwReason)
  68. {
  69. case DLL_PROCESS_ATTACH:
  70. //
  71. // To help performance, cancel thread attach and detach notifications
  72. //
  73. DisableThreadLibraryCalls((HMODULE) hInst);
  74. break;
  75. case DLL_PROCESS_DETACH:
  76. if( ghStartupEvent != INVALID_HANDLE_VALUE )
  77. {
  78. _VERIFY( CloseHandle( ghStartupEvent ) );
  79. }
  80. break;
  81. case DLL_THREAD_ATTACH:
  82. break;
  83. case DLL_THREAD_DETACH:
  84. break;
  85. }
  86. return TRUE;
  87. }
  88. BOOL WINAPI DllMain (HANDLE hInst, ULONG dwReason, LPVOID lpvReserve)
  89. {
  90. return DllEntryPoint((HINSTANCE) hInst, dwReason, lpvReserve);
  91. }
  92. //
  93. // Public functions.
  94. //
  95. /*******************************************************************
  96. NAME: ServiceEntry
  97. SYNOPSIS: This is the "real" entrypoint for the service. When
  98. the Service Controller dispatcher is requested to
  99. start a service, it creates a thread that will begin
  100. executing this routine.
  101. ENTRY: cArgs - Number of command line arguments to this service.
  102. pArgs - Pointers to the command line arguments.
  103. pGlobalData - Points to global data shared amongst all
  104. services that live in TCPSVCS.EXE.
  105. EXIT: Does not return until service is stopped.
  106. HISTORY:
  107. KeithMo 07-Mar-1993 Created.
  108. KeithMo 07-Jan-1994 Modified for use as a DLL.
  109. ********************************************************************/
  110. VOID ServiceEntry( DWORD cArgs,
  111. LPWSTR pArgs[],
  112. PTCPSVCS_GLOBAL_DATA pGlobalData )
  113. {
  114. APIERR err = NO_ERROR;
  115. InitAsyncTrace();
  116. TraceQuietEnter( "ServiceEntry");
  117. //
  118. // Save the global data pointer.
  119. //
  120. pTcpsvcsGlobalData = pGlobalData;
  121. //
  122. // Initialize the service status structure.
  123. //
  124. DebugTrace( 0, "new TSVC_INFO( %s)", XXX_SERVICE_NAME);
  125. g_pTsvcInfo = new TSVC_INFO( XXX_SERVICE_NAME,
  126. XXX_MODULE_NAME,
  127. XXX_PARAMETERS_KEY_A,
  128. XXX_ANONYMOUS_SECRET_W,
  129. XXX_ROOT_SECRET_W,
  130. XXX_INET,
  131. InitializeService,
  132. TerminateService );
  133. //
  134. // If we couldn't allocate memory for the service info struct, then the
  135. // machine is really hosed -- we can't even log..
  136. //
  137. if (!g_pTsvcInfo || !g_pTsvcInfo->IsValid())
  138. {
  139. FatalTrace( 0, "new TSVC_INFO( %s) failed: %x",
  140. XXX_SERVICE_NAME, g_pTsvcInfo);
  141. if (g_pTsvcInfo != NULL)
  142. {
  143. delete g_pTsvcInfo;
  144. g_pTsvcInfo = NULL;
  145. }
  146. goto out;
  147. }
  148. //
  149. // save the global pointer for rpc thread
  150. //
  151. g_pTsvcInfo->SetTcpsvcsGlobalData( pTcpsvcsGlobalData);
  152. //
  153. // This blocks until the service is shutdown
  154. //
  155. err = g_pTsvcInfo->StartServiceOperation( SERVICE_CTRL_HANDLER() );
  156. delete g_pTsvcInfo;
  157. g_pTsvcInfo = NULL;
  158. out:
  159. TermAsyncTrace( );
  160. } // ServiceEntry
  161. //
  162. // Private functions.
  163. //
  164. /*******************************************************************
  165. NAME: InitializeService
  166. SYNOPSIS: Initializes the various W3 Service components.
  167. EXIT: If successful, then every component has been
  168. successfully initialized.
  169. RETURNS: APIERR - NO_ERROR if successful, otherwise a Win32
  170. status code.
  171. HISTORY:
  172. KeithMo 07-Mar-1993 Created.
  173. ********************************************************************/
  174. APIERR
  175. InitializeService( LPVOID pContext )
  176. {
  177. APIERR err;
  178. LPTSVC_INFO ptsi = (LPTSVC_INFO ) pContext;
  179. TraceFunctEnter("InitializeService");
  180. //
  181. // Create a startup named event. If this already exists, refuse to boot !
  182. //
  183. HANDLE hEvent = CreateEvent( NULL, FALSE, FALSE, XXX_NAMED_EVENT);
  184. if( !hEvent || GetLastError() != 0 )
  185. {
  186. if( hEvent)
  187. {
  188. _VERIFY( CloseHandle( hEvent ) );
  189. }
  190. g_pTsvcInfo->LogEvent(
  191. XXX_BOOT_ERROR,
  192. 0,
  193. (const CHAR **)NULL,
  194. ERROR_SERVICE_ALREADY_RUNNING
  195. );
  196. return ERROR_SERVICE_ALREADY_RUNNING ;
  197. }
  198. // set the global startup event. this is closed when our DLL_PROCESS_DETACH
  199. ghStartupEvent = hEvent;
  200. ServiceBooted = TRUE;
  201. g_pTsvcInfo->LogEvent(
  202. XXX_EVENT_SERVICE_STARTED,
  203. 0,
  204. (const CHAR **)NULL,
  205. 0
  206. );
  207. //
  208. // Initialize various components. The ordering of the
  209. // components is somewhat limited. Globals should be
  210. // initialized first, then the event logger. After
  211. // the event logger is initialized, the other components
  212. // may be initialized in any order with one exception.
  213. // InitializeSockets must be the last initialization
  214. // routine called. It kicks off the main socket connection
  215. // thread.
  216. //
  217. if(( err = InitializeGlobals()))
  218. {
  219. FatalTrace( 0, "InitializeGlobals failed, err=%d.", err);
  220. TraceFunctLeave();
  221. return err;
  222. }
  223. if( (err = ptsi->InitializeIpc( (UCHAR *) "ncacn_np",
  224. (UCHAR *) XXX_NAMED_PIPE,
  225. XXX_ServerIfHandle)) != NO_ERROR)
  226. {
  227. FatalTrace( 0, "InitializeIpc failed, err=%d.", err);
  228. TraceFunctLeave();
  229. return err;
  230. }
  231. GlobalInitializeStatus |= INITIALIZE_IPC;
  232. if((err = g_pTsvcInfo->InitializeDiscovery( NULL)))
  233. {
  234. FatalTrace( 0, "InitializeDiscovery failed, err=%d.", err);
  235. TraceFunctLeave();
  236. return err;
  237. }
  238. GlobalInitializeStatus |= INITIALIZE_DISCOVERY;
  239. if((err = InitializeSockets()))
  240. {
  241. FatalTrace( 0, "InitializeSockets failed, err=%d.", err);
  242. TraceFunctLeave();
  243. return err;
  244. }
  245. GlobalInitializeStatus |= INITIALIZE_SOCKETS;
  246. //
  247. // InitializeConnection
  248. //
  249. if ( !g_pTsvcInfo->InitializeConnections(
  250. &XXX_OnConnect,
  251. &XXX_OnConnectEx,
  252. &XXX_Completion,
  253. XXX_SECURE_PORT,
  254. 0 ))
  255. {
  256. err = GetLastError();
  257. g_pTsvcInfo->LogEvent(
  258. XXX_EVENT_CANNOT_INITIALIZE_WINSOCK,
  259. 0,
  260. (const CHAR **)NULL,
  261. err
  262. );
  263. ErrorTrace(0,"InitializeConnections failed, error %d",err );
  264. return err;
  265. }
  266. GlobalInitializeStatus |= INITIALIZE_CONNECTIONS;
  267. //
  268. // Success!
  269. //
  270. TraceFunctLeave();
  271. return NO_ERROR;
  272. } // InitializeService
  273. /*******************************************************************
  274. NAME: TerminateService
  275. SYNOPSIS: Terminates the various W3 Service components.
  276. EXIT: If successful, then every component has been
  277. successfully terminated.
  278. HISTORY:
  279. KeithMo 07-Mar-1993 Created.
  280. ********************************************************************/
  281. APIERR TerminateService( LPVOID pContext )
  282. {
  283. LPTSVC_INFO ptsi = (LPTSVC_INFO ) pContext;
  284. DWORD err;
  285. TraceFunctEnter("TerminateService");
  286. if(!ServiceBooted)
  287. {
  288. return NO_ERROR;
  289. }
  290. ServiceBooted = FALSE;
  291. _ASSERT(ptsi == g_pTsvcInfo);
  292. //
  293. // Components should be terminated in reverse
  294. // initialization order.
  295. //
  296. //
  297. // must happen after CleanupConnections so no new conns accepted
  298. //
  299. if ( GlobalInitializeStatus & INITIALIZE_CONNECTIONS)
  300. {
  301. g_pTsvcInfo->CleanupConnections();
  302. }
  303. if (XXX_g_Config != NULL)
  304. {
  305. XXX_g_Config->DisconnectAllConnections();
  306. }
  307. if ( GlobalInitializeStatus & INITIALIZE_SOCKETS)
  308. {
  309. TerminateSockets();
  310. }
  311. if ( GlobalInitializeStatus & INITIALIZE_DISCOVERY)
  312. {
  313. if ( (err = ptsi->TerminateDiscovery()) != NO_ERROR)
  314. {
  315. ErrorTrace(0, "TerminateDiscovery() failed. Error = %u", err);
  316. }
  317. }
  318. if ( GlobalInitializeStatus & INITIALIZE_IPC)
  319. {
  320. if ( (err = ptsi->CleanupIpc( XXX_ServerIfHandle)) != NO_ERROR)
  321. {
  322. ErrorTrace(0, "CleanupIpc() failed. Error = %u", err);
  323. }
  324. }
  325. TerminateGlobals();
  326. g_pTsvcInfo->LogEvent(
  327. XXX_EVENT_SERVICE_STOPPED,
  328. 0,
  329. (const CHAR **)NULL,
  330. 0
  331. );
  332. TraceFunctLeave();
  333. return NO_ERROR;
  334. } // TerminateService