// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. /* File Replication Sample Server System Service FILE: FileRepService.cpp PURPOSE: Provides file replication services. USAGE: FileRepService FUNCTIONS: main() - calls the StartServiceCtrlDispatcher function to connect to the SCM and start the control dispatcher thread. ServiceMain() - the entry point for the service. ServiceCtrl() - this function is called by the dispatcher thread. It handles the control code passed to it. ServiceStart() - performs actual initialization and starts the service. Makes the RPC server listen for calls. ServiceStop() - stops listening for RPCs. COMMENTS: */ // Common definitions #include "common.h" #define SECURITY_WIN32 #include #include #include #include #include #include #include #include #include #include #include // Generated by the MIDL compiler #include "FileRepServer.h" #include "FileRepClient.h" // Contains declarations for system service functions. #include "Service.h" #ifdef PROF #include "Prof.h" #endif #ifdef DEBUG1 #include "DbgMsg.h" #endif /* Internal funtion declarations. See definitions for more info. */ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv); VOID WINAPI ServiceCtrl(DWORD Opcode); VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv); VOID ServiceStop(); /* FUNCTION: main() PURPOSE: main() calls StartServiceCtrlDispatcher to register the main service thread. When this call returns, the service has stopped. PARAMETERS: dwArgc - number of command line arguments lpszArgv - array of command line arguments RETURN VALUE: none COMMENTS: */ VOID _cdecl main(int argc, char **argv){ // Since we provide a single service there is only // one entry in the service dispatch table SERVICE_TABLE_ENTRY DispatchTable[] = { { SERVICENAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain }, { NULL, NULL } }; // The service control manager may be starting the service with // this call, so we must call StartServiceCtrlDispatcher. if (!StartServiceCtrlDispatcher(DispatchTable)) { AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed")); } } /* FUNCTION: ServiceMain PURPOSE: To perform actual initialization of the client service. It is the entry point into the service. PARAMETERS: dwArgc - number of command line arguments lpszArgv - array of command line arguments RETURN VALUE: none COMMENTS: This routine performs the service initialization and then calls the user defined ServiceStart() routine to perform majority of the work. */ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { // Initial service configuration ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ssStatus.dwCurrentState = SERVICE_START_PENDING; ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; ssStatus.dwWin32ExitCode = 0; ssStatus.dwServiceSpecificExitCode = 0; ssStatus.dwCheckPoint = 0; ssStatus.dwWaitHint = 0; sshStatusHandle = RegisterServiceCtrlHandler(SERVICENAME, ServiceCtrl); // Tell the SCM that the service is starting up. if (!SetServiceStatus(sshStatusHandle, &ssStatus)) { AddToMessageLog(TEXT("ServiceMain: SetServiceStatus failed\n")); return; } // Initialize the service and start it. ServiceStart(dwArgc, lpszArgv); return; } /* FUNCTION: ServiceCtrl PURPOSE: This function is called by the SCM whenever ControlService() is called on this service. PARAMETERS: dwCtrlCode - type of control requested RETURN VALUE: none COMMENTS: */ VOID WINAPI ServiceCtrl(DWORD Opcode) { // We only handle the STOP control requsts. switch(Opcode) { case SERVICE_CONTROL_STOP: // Stop the service. ServiceStop(); break; default: AddToMessageLog(TEXT("ServiceCtrl: unrecognized or unimplemented opcode\n")); } return; } /* FUNCTION: ServiceStart PURPOSE: Actual code of the service that does the work. PARAMETERS: dwArgc - number of command line arguments lpszArgv - array of command line arguments RETURN VALUE: none COMMENTS: Starts the service listening for RPC requests. */ VOID ServiceStart (DWORD dwArgc, LPTSTR *szArgList){ RPC_STATUS status; // Report the status to the service control manager. if (!ReportStatusToSCMgr(&sshStatusHandle, &ssStatus, SERVICE_START_PENDING, NO_ERROR, 1000)) { AddToMessageLog(TEXT("ServiceStart: ReportStatusToSCMgr failed\n")); ServiceStop(); return; } // Allow the user to override settings with command line switches. for (unsigned i = 1; i < dwArgc; i++) { // Well-formed argument switches start with '/' or '-' and are // two characters long. if (((*szArgList[i] == TEXT('-')) || (*szArgList[i] == TEXT('/'))) && _tcsclen(szArgList[i]) == 2) { switch (_totlower(*(szArgList[i]+1))) { case TEXT('f'): bNoFileIO = true; break; default: AddToMessageLog(TEXT("ServiceStart: bad arguments")); ServiceStop(); return; } } else { AddToMessageLog(TEXT("ServiceStart: bad arguments")); ServiceStop(); return; } } if (!StartFileRepServer()) { ServiceStop(); } else { bServerListening = TRUE; // Tell The SCM that the service is running. if (!ReportStatusToSCMgr(&sshStatusHandle, &ssStatus, SERVICE_RUNNING, NO_ERROR, 0)){ AddToMessageLog(TEXT("ServiceStart: ReportStatusToSCMgr failed")); ServiceStop(); return; } // RpcMgmtWaitServerListen() will block until the server has // stopped listening. status = RpcMgmtWaitServerListen(); if (status != RPC_S_OK){ AddToMessageLogProcFailureEEInfo(TEXT("ServiceStart: RpcMgmtWaitServerListen"), status); ServiceStop(); return; } } return; } VOID ServiceStop(VOID) { ServerStop(); } // end FileRepService.cpp