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.

393 lines
10 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: main.c
  7. //
  8. // Description: This module contains the main procedure of the AFP server
  9. // service. It will contain code to initialize and install
  10. // itself and the kernel-mode AFP Server. It also contains
  11. // code to respond to the server controller. It will also
  12. // handle service shutdown.
  13. //
  14. // ??? Does the service controller log start/stop events etc ??
  15. // if not log it.
  16. //
  17. // History:
  18. // May 11,1990. NarenG Created original version.
  19. //
  20. #define DEFINE_AFP_GLOBALS // This will cause AfpGlobals to be defined.
  21. #include "afpsvcp.h"
  22. // Prototypes of functions used only within this module.
  23. //
  24. VOID
  25. AfpMain(
  26. IN DWORD argc,
  27. IN LPWSTR * lpwsServiceArgs
  28. );
  29. VOID
  30. AfpCleanupAndExit(
  31. IN DWORD dwError
  32. );
  33. VOID
  34. AfpControlResponse(
  35. IN DWORD dwControlCode
  36. );
  37. //**
  38. //
  39. // Call: main.c
  40. //
  41. // Returns: none.
  42. //
  43. // Description: Will simply register the entry point of the AFP server
  44. // service with the service controller. The service controller
  45. // will capture this thread. It will be freed only when
  46. // the service is shutdown. At that point we will simply exit
  47. // the process.
  48. //
  49. void
  50. _cdecl
  51. main( int argc, unsigned char * argv[] )
  52. {
  53. SERVICE_TABLE_ENTRY AfpServiceDispatchTable[2];
  54. #ifdef DBG
  55. CONSOLE_SCREEN_BUFFER_INFO csbi;
  56. COORD coord;
  57. (VOID)AllocConsole( );
  58. (VOID)GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE),
  59. &csbi
  60. );
  61. coord.X = (SHORT)(csbi.srWindow.Right - csbi.srWindow.Left + 1);
  62. coord.Y = (SHORT)((csbi.srWindow.Bottom - csbi.srWindow.Top + 1) * 20);
  63. (VOID)SetConsoleScreenBufferSize( GetStdHandle(STD_OUTPUT_HANDLE),
  64. coord
  65. );
  66. #endif
  67. AFP_UNREFERENCED( argc );
  68. AFP_UNREFERENCED( argv );
  69. AfpServiceDispatchTable[0].lpServiceName = AFP_SERVICE_NAME;
  70. AfpServiceDispatchTable[0].lpServiceProc = AfpMain;
  71. AfpServiceDispatchTable[1].lpServiceName = NULL;
  72. AfpServiceDispatchTable[1].lpServiceProc = NULL;
  73. if ( !StartServiceCtrlDispatcher( AfpServiceDispatchTable ) )
  74. AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
  75. GetLastError(), EVENTLOG_ERROR_TYPE );
  76. ExitProcess(0);
  77. }
  78. //**
  79. //
  80. // Call: AfpMain
  81. //
  82. // Returns: none.
  83. //
  84. // Description: This is the main procedure for the Afp Server Service. It
  85. // will be called when the service is supposed to start itself.
  86. // It will do all service wide initialization.
  87. //
  88. VOID
  89. AfpMain( DWORD argc, // Command line arguments. Will be ignored.
  90. LPWSTR * lpwsServiceArgs
  91. )
  92. {
  93. DWORD dwRetCode;
  94. AFP_UNREFERENCED( argc );
  95. AFP_UNREFERENCED( lpwsServiceArgs );
  96. // NULL out all the globals
  97. //
  98. ZeroMemory( (LPBYTE)&AfpGlobals, sizeof(AfpGlobals) );
  99. // Register the service control handler with the service controller
  100. //
  101. AfpGlobals.hServiceStatus = RegisterServiceCtrlHandler(AFP_SERVICE_NAME,
  102. AfpControlResponse );
  103. if ( AfpGlobals.hServiceStatus == (SERVICE_STATUS_HANDLE)0 ) {
  104. AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
  105. GetLastError(), EVENTLOG_ERROR_TYPE );
  106. AfpCleanupAndExit( GetLastError() );
  107. return;
  108. }
  109. AfpGlobals.ServiceStatus.dwServiceType = SERVICE_WIN32;
  110. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  111. AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
  112. AfpGlobals.ServiceStatus.dwWin32ExitCode = NO_ERROR;
  113. AfpGlobals.ServiceStatus.dwServiceSpecificExitCode= 0;
  114. AfpGlobals.ServiceStatus.dwCheckPoint = 1;
  115. AfpGlobals.ServiceStatus.dwWaitHint =AFP_SERVICE_INSTALL_TIME;
  116. AfpAnnounceServiceStatus();
  117. // Read in registry information and initialize the kernel-mode
  118. // server. Initialize the server to accept RPC calls. Initialize
  119. // all global vriables etc.
  120. //
  121. if ( dwRetCode = AfpInitialize() )
  122. {
  123. if (AfpGlobals.dwServerState & AFPSTATE_BLOCKED_ON_DOMINFO)
  124. {
  125. AfpCleanupAndExit( NO_ERROR );
  126. }
  127. else
  128. {
  129. AfpCleanupAndExit( dwRetCode );
  130. }
  131. return;
  132. }
  133. // Set the MAC bit for NetServerEnum
  134. //
  135. if ( !I_ScSetServiceBits( AfpGlobals.hServiceStatus,
  136. SV_TYPE_AFP,
  137. TRUE,
  138. TRUE,
  139. NULL ))
  140. {
  141. dwRetCode = GetLastError();
  142. AfpLogEvent( AFPLOG_CANT_START, 0, NULL,
  143. GetLastError(), EVENTLOG_ERROR_TYPE );
  144. AfpCleanupAndExit( dwRetCode );
  145. return;
  146. }
  147. // now tell the service controller that we are up
  148. //
  149. if (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_START_PENDING)
  150. {
  151. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  152. AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  153. SERVICE_ACCEPT_PAUSE_CONTINUE;
  154. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  155. AfpGlobals.ServiceStatus.dwWaitHint = 0;
  156. AfpAnnounceServiceStatus();
  157. }
  158. // Start listening for RPC admin client calls. This will block
  159. // until RpcMgmtStopServerListening is called while processing a
  160. // STOP_SERVICE control request.
  161. //
  162. if ( dwRetCode = RpcServerListen( 1,
  163. RPC_C_LISTEN_MAX_CALLS_DEFAULT,
  164. 0 ) ) // Blocking mode
  165. {
  166. AfpLogEvent( AFPLOG_CANT_INIT_RPC, 0, NULL,
  167. dwRetCode, EVENTLOG_ERROR_TYPE );
  168. }
  169. AfpCleanupAndExit( dwRetCode );
  170. }
  171. //**
  172. //
  173. // Call: AfpCleanupAndExit
  174. //
  175. // Returns: none
  176. //
  177. // Description: Will free any allocated memory, deinitialize RPC, deinitialize
  178. // the kernel-mode server and unload it if it was loaded.
  179. // This could have been called due to an error on SERVICE_START
  180. // or normal termination.
  181. //
  182. VOID
  183. AfpCleanupAndExit(
  184. IN DWORD dwError
  185. )
  186. {
  187. AFP_PRINT( ("AFPSVC_main: Cleaning up and exiting Code = %d\n", dwError));
  188. // Tear down and free everything
  189. //
  190. AfpTerminate();
  191. if ( dwError == NO_ERROR )
  192. AfpGlobals.ServiceStatus.dwWin32ExitCode = NO_ERROR;
  193. else {
  194. AfpGlobals.ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
  195. //AFP_ASSERT(0);
  196. }
  197. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_STOPPED;
  198. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  199. AfpGlobals.ServiceStatus.dwWaitHint = 0;
  200. AfpGlobals.ServiceStatus.dwServiceSpecificExitCode = dwError;
  201. AfpAnnounceServiceStatus();
  202. return;
  203. }
  204. //**
  205. //
  206. // Call: AfpControlResponse
  207. //
  208. // Returns: none
  209. //
  210. // Description: Will respond to control requests from the service controller.
  211. //
  212. VOID
  213. AfpControlResponse( IN DWORD dwControlCode )
  214. {
  215. AFP_REQUEST_PACKET AfpRequestPkt;
  216. DWORD dwRetCode;
  217. switch( dwControlCode ) {
  218. case SERVICE_CONTROL_STOP:
  219. if ( (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING)
  220. ||
  221. (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_STOPPED ))
  222. break;
  223. // Announce that we are stopping
  224. //
  225. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
  226. AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
  227. AfpGlobals.ServiceStatus.dwCheckPoint = 1;
  228. AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_STOP_TIME;
  229. AfpAnnounceServiceStatus();
  230. // if srvrhlpr thread is blocked retrying to get domain info, unblock it
  231. SetEvent(AfpGlobals.heventSrvrHlprSpecial);
  232. // if srvrhlpr thread was blocked, no more init was done, so we're done
  233. if (AfpGlobals.dwServerState & AFPSTATE_BLOCKED_ON_DOMINFO)
  234. {
  235. return;
  236. }
  237. // This call will unblock the main thread that had called
  238. // RpcServerListen. We let that thread do the announcing
  239. // while cleaning up.
  240. //
  241. if ( (dwRetCode =
  242. RpcMgmtStopServerListening( (RPC_BINDING_HANDLE)NULL ))
  243. != RPC_S_OK )
  244. {
  245. ASSERT (0);
  246. }
  247. return;
  248. case SERVICE_CONTROL_PAUSE:
  249. if ( (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING)
  250. ||
  251. (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_PAUSED ))
  252. break;
  253. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
  254. AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
  255. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  256. AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_PAUSE_TIME;
  257. AfpAnnounceServiceStatus();
  258. // Tell the kernel-mode that we want to pause.
  259. //
  260. AfpRequestPkt.dwRequestCode = OP_SERVICE_PAUSE;
  261. AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
  262. dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
  263. AFP_ASSERT( dwRetCode == NO_ERROR );
  264. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  265. AfpGlobals.ServiceStatus.dwWaitHint = 0;
  266. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_PAUSED;
  267. AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  268. SERVICE_ACCEPT_PAUSE_CONTINUE;
  269. break;
  270. case SERVICE_CONTROL_CONTINUE:
  271. if ( (AfpGlobals.ServiceStatus.dwCurrentState==SERVICE_CONTINUE_PENDING)
  272. ||
  273. (AfpGlobals.ServiceStatus.dwCurrentState == SERVICE_RUNNING ))
  274. break;
  275. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_CONTINUE_PENDING;
  276. AfpGlobals.ServiceStatus.dwControlsAccepted = 0;
  277. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  278. AfpGlobals.ServiceStatus.dwWaitHint = AFP_SERVICE_CONTINUE_TIME;
  279. AfpAnnounceServiceStatus();
  280. // Tell the kernel-mode that we want to continue.
  281. //
  282. AfpRequestPkt.dwRequestCode = OP_SERVICE_CONTINUE;
  283. AfpRequestPkt.dwApiType = AFP_API_TYPE_COMMAND;
  284. dwRetCode = AfpServerIOCtrl( &AfpRequestPkt );
  285. AFP_ASSERT( dwRetCode == NO_ERROR );
  286. AfpGlobals.ServiceStatus.dwCheckPoint = 0;
  287. AfpGlobals.ServiceStatus.dwWaitHint = 0;
  288. AfpGlobals.ServiceStatus.dwCurrentState = SERVICE_RUNNING;
  289. AfpGlobals.ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
  290. SERVICE_ACCEPT_PAUSE_CONTINUE;
  291. break;
  292. case SERVICE_CONTROL_INTERROGATE:
  293. break;
  294. default:
  295. break;
  296. }
  297. AfpAnnounceServiceStatus();
  298. }
  299. //**
  300. //
  301. // Call: AfpAnnounceServiceStatus
  302. //
  303. // Returns: none
  304. //
  305. // Description: Will simly call SetServiceStatus to inform the service
  306. // control manager of this service's current status.
  307. //
  308. VOID
  309. AfpAnnounceServiceStatus( VOID )
  310. {
  311. BOOL dwRetCode;
  312. dwRetCode = SetServiceStatus( AfpGlobals.hServiceStatus,
  313. &(AfpGlobals.ServiceStatus) );
  314. AFP_ASSERT( dwRetCode == TRUE );
  315. }