2025-11-28 00:35:46 +09:00

269 lines
6.6 KiB
C++

// 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 <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <tchar.h>
#include <rpc.h>
#include <Ntdsapi.h>
#include <Ntsecapi.h>
#include <Security.h>
#include <Secext.h>
#include <Dsgetdc.h>
#include <Lm.h>
// 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