您的位置:首页 > 其它

VC 服务程序的编写

2014-12-27 20:58 302 查看
参考:http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx

sample.h

// The following are message definitions.
//
//  Values are 32 bit values laid out as follows:
//
//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
//  +---+-+-+-----------------------+-------------------------------+
//  |Sev|C|R|     Facility          |               Code            |
//  +---+-+-+-----------------------+-------------------------------+
//
//  where
//
//      Sev - is the severity code
//
//          00 - Success
//          01 - Informational
//          10 - Warning
//          11 - Error
//
//      C - is the Customer code flag
//
//      R - is a reserved bit
//
//      Facility - is the facility code
//
//      Code - is the facility's status code
//
//
// Define the facility codes
//
#define FACILITY_SYSTEM                  0x0
#define FACILITY_STUBS                   0x3
#define FACILITY_RUNTIME                 0x2
#define FACILITY_IO_ERROR_CODE           0x4

//
// Define the severity codes
//
#define STATUS_SEVERITY_WARNING          0x2
#define STATUS_SEVERITY_SUCCESS          0x0
#define STATUS_SEVERITY_INFORMATIONAL    0x1
#define STATUS_SEVERITY_ERROR            0x3

//
// MessageId: SVC_ERROR
//
// MessageText:
//
// An error has occurred (%2).
//
#define SVC_ERROR                        ((DWORD)0xC0020001L)

// A message file must end with a period on its own line
// followed by a blank line.
svc.cpp

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include "sample.h"

#include <locale.h>
#include <iostream>
#include <conio.h>
using namespace std;

//#pragma comment(lib, "advapi32.lib")

#define SVCNAME TEXT("SvcName")

SERVICE_STATUS          gSvcStatus;
SERVICE_STATUS_HANDLE   gSvcStatusHandle;
HANDLE                  ghSvcStopEvent = NULL;

VOID SvcInstall(void);
VOID WINAPI SvcCtrlHandler( DWORD );
VOID WINAPI SvcMain( DWORD, LPTSTR * );

VOID ReportSvcStatus( DWORD, DWORD, DWORD );
VOID SvcInit( DWORD, LPTSTR * );
VOID SvcReportEvent( LPTSTR );
#define  logName "c:/log.txt"

TCHAR * GetErrString(TCHAR *str, DWORD errcode)
{
LPVOID lpbuf;
if(FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errcode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpbuf,
0,
NULL
))
{
lstrcpy(str,(LPCWSTR)lpbuf);
LocalFree(lpbuf);
}

return str;
}
void DebugA(const char *Format, ...)
{
va_list va;
char szOutputString[8096];
va_start(va, Format);
memset(szOutputString, 0, 8096);
wvsprintfA(szOutputString, Format, va);
sprintf(szOutputString,"%s\n",szOutputString);
OutputDebugStringA(szOutputString);

do {
freopen(logName, "a+", stdout);
fprintf(stdout, "(pid=%d)%s:%d\t", GetCurrentProcessId(), __FILE__, __LINE__);
fprintf(stdout, szOutputString );
fflush(stdout);
} while (0);

va_end(va);
}
void DebugW(const WCHAR *Format, ...)
{
va_list va;
WCHAR szOutputString[8096];
va_start(va, Format);
memset(szOutputString, 0, 8096);
wvsprintfW(szOutputString, Format, va);
wsprintf(szOutputString,L"%s\n",szOutputString);
OutputDebugStringW(szOutputString);

do {
freopen(logName, "a+", stdout);
fprintf(stdout, "(pid=%d)%s:%d\t", GetCurrentProcessId(), __FILE__, __LINE__);
setlocale(LC_ALL,"chs");   //chs
fwprintf_s(stdout,szOutputString);

//_locale_t locale;
// locale = _create_locale(LC_ALL, "chs");
//_fwprintf_l(stdout,szOutputString,_create_locale(LC_ALL, "chs"));
fflush(stdout);
} while (0);

va_end(va);
}
//
// Purpose:
//   Entry point for the process
//
// Parameters:
//   None
//
// Return value:
//   None
//
void __cdecl _tmain(int argc, TCHAR *argv[])
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.

if( lstrcmpi( argv[1], TEXT("install")) == 0 )
{
SvcInstall();
return;
}

// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
{ NULL, NULL }
};

// This call returns when the service has stopped.
// The process should simply terminate when the call returns.

BOOL ret=StartServiceCtrlDispatcher( DispatchTable );
if (!ret)
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));

TCHAR err[1024];
int code=GetLastError();
GetErrString(err,code);
DebugW(_T("Register Service Main Function Error msg:%d %s  %d!"),code,err,ret);
} else{
DebugA("StartServiceCtrlDispatcher success %d! ",ret);
}

}

//
// Purpose:
//   Installs a service in the SCM database
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID SvcInstall()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];

if( !GetModuleFileName(NULL, szPath, MAX_PATH ) )
{
printf("Cannot install service (%d)\n", GetLastError());
return;
}

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Create the service

schService = CreateService(
schSCManager,              // SCM database
SVCNAME,                   // name of service
SVCNAME,                   // service name to display
SERVICE_ALL_ACCESS,        // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START,      // start type
SERVICE_ERROR_NORMAL,      // error control type
szPath,                    // path to service's binary
NULL,                      // no load ordering group
NULL,                      // no tag identifier
NULL,                      // no dependencies
NULL,                      // LocalSystem account
NULL);                     // no password

if (schService == NULL)
{
printf("CreateService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else printf("Service installed successfully\n");

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Entry point for the service
//
// Parameters:
//   dwArgc - Number of arguments in the lpszArgv array
//   lpszArgv - Array of strings. The first string is the name of
//     the service and subsequent strings are passed by the process
//     that called the StartService function to start the service.
//
// Return value:
//   None.
//
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
// Register the handler function for the service

gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);

if( !gSvcStatusHandle )
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
DebugA("SvcMain...");

// These SERVICE_STATUS members remain as set here

gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;

// Report initial status to the SCM

ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );

// Perform service-specific initialization and work.

SvcInit( dwArgc, lpszArgv );
}

//
// Purpose:
//   The service code
//
// Parameters:
//   dwArgc - Number of arguments in the lpszArgv array
//   lpszArgv - Array of strings. The first string is the name of
//     the service and subsequent strings are passed by the process
//     that called the StartService function to start the service.
//
// Return value:
//   None
//
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
// TO_DO: Declare and set any required variables.
//   Be sure to periodically call ReportSvcStatus() with
//   SERVICE_START_PENDING. If initialization fails, call
//   ReportSvcStatus with SERVICE_STOPPED.

// Create an event. The control handler function, SvcCtrlHandler,
// signals this event when it receives the stop control code.

ghSvcStopEvent = CreateEvent(
NULL,    // default security attributes
TRUE,    // manual reset event
FALSE,   // not signaled
NULL);   // no name

if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}

// Report running status when initialization is complete.

ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );

// TO_DO: Perform work until service stops.

while(1)
{
// Check whether to stop the service.

DebugA("service running");
WaitForSingleObject(ghSvcStopEvent, INFINITE);

ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
}

//
// Purpose:
//   Sets the current service status and reports it to the SCM.
//
// Parameters:
//   dwCurrentState - The current state (see SERVICE_STATUS)
//   dwWin32ExitCode - The system error code
//   dwWaitHint - Estimated time for pending operation,
//     in milliseconds
//
// Return value:
//   None
//
VOID ReportSvcStatus( DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;

// Fill in the SERVICE_STATUS structure.

gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;

if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

if ( (dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED) )
gSvcStatus.dwCheckPoint = 0;
else gSvcStatus.dwCheckPoint = dwCheckPoint++;

// Report the status of the service to the SCM.
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
}

//
// Purpose:
//   Called by SCM whenever a control code is sent to the service
//   using the ControlService function.
//
// Parameters:
//   dwCtrl - control code
//
// Return value:
//   None
//
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
{
// Handle the requested control code.

switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);

// Signal the service to stop.

SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);

return;

case SERVICE_CONTROL_INTERROGATE:
break;

default:
break;
}

}

//
// Purpose:
//   Logs messages to the event log
//
// Parameters:
//   szFunction - name of function that failed
//
// Return value:
//   None
//
// Remarks:
//   The service must have an entry in the Application event log.
//
VOID SvcReportEvent(LPTSTR szFunction)
{
HANDLE hEventSource;
LPCTSTR lpszStrings[2];
TCHAR Buffer[80];

hEventSource = RegisterEventSource(NULL, SVCNAME);

if( NULL != hEventSource )
{
StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());

lpszStrings[0] = SVCNAME;
lpszStrings[1] = Buffer;

ReportEvent(hEventSource,        // event log handle
EVENTLOG_ERROR_TYPE, // event type
0,                   // event category
SVC_ERROR,           // event identifier
NULL,                // no security identifier
2,                   // size of lpszStrings array
0,                   // no binary data
lpszStrings,         // array of strings
NULL);               // no binary data

DeregisterEventSource(hEventSource);
}
}
svcconfig.cpp

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <stdio.h>

#pragma comment(lib, "advapi32.lib")

TCHAR szCommand[10];
TCHAR szSvcName[80];

VOID __stdcall DisplayUsage(void);

VOID __stdcall DoQuerySvc(void);
VOID __stdcall DoUpdateSvcDesc(void);
VOID __stdcall DoDisableSvc(void);
VOID __stdcall DoEnableSvc(void);
VOID __stdcall DoDeleteSvc(void);

//
// Purpose:
//   Entry point function. Executes specified command from user.
//
// Parameters:
//   Command-line syntax is: svcconfig [command] [service_path]
//
// Return value:
//   None
//
void __cdecl _tmain(int argc, TCHAR *argv[])
{
printf("\n");
if( argc != 3 )
{
printf("ERROR:\tIncorrect number of arguments\n\n");
DisplayUsage();
return;
}

StringCchCopy(szCommand, 10, argv[1]);
StringCchCopy(szSvcName, 80, argv[2]);

if (lstrcmpi( szCommand, TEXT("query")) == 0 )
DoQuerySvc();
else if (lstrcmpi( szCommand, TEXT("describe")) == 0 )
DoUpdateSvcDesc();
else if (lstrcmpi( szCommand, TEXT("disable")) == 0 )
DoDisableSvc();
else if (lstrcmpi( szCommand, TEXT("enable")) == 0 )
DoEnableSvc();
else if (lstrcmpi( szCommand, TEXT("delete")) == 0 )
DoDeleteSvc();
else
{
_tprintf(TEXT("Unknown command (%s)\n\n"), szCommand);
DisplayUsage();
}
}

VOID __stdcall DisplayUsage()
{
printf("Description:\n");
printf("\tCommand-line tool that configures a service.\n\n");
printf("Usage:\n");
printf("\tsvcconfig [command] [service_name]\n\n");
printf("\t[command]\n");
printf("\t  query\n");
printf("\t  describe\n");
printf("\t  disable\n");
printf("\t  enable\n");
printf("\t  delete\n");
}

//
// Purpose:
//   Retrieves and displays the current service configuration.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoQuerySvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPQUERY_SERVICE_CONFIG lpsc;
LPSERVICE_DESCRIPTION lpsd;
DWORD dwBytesNeeded, cbBufSize, dwError;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,          // SCM database
szSvcName,             // name of service
SERVICE_QUERY_CONFIG); // need query config access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Get the configuration information.

if( !QueryServiceConfig(
schService,
NULL,
0,
&dwBytesNeeded))
{
dwError = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER == dwError )
{
cbBufSize = dwBytesNeeded;
lpsc = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LMEM_FIXED, cbBufSize);
}
else
{
printf("QueryServiceConfig failed (%d)", dwError);
goto cleanup;
}
}

if( !QueryServiceConfig(
schService,
lpsc,
cbBufSize,
&dwBytesNeeded) )
{
printf("QueryServiceConfig failed (%d)", GetLastError());
goto cleanup;
}

if( !QueryServiceConfig2(
schService,
SERVICE_CONFIG_DESCRIPTION,
NULL,
0,
&dwBytesNeeded))
{
dwError = GetLastError();
if( ERROR_INSUFFICIENT_BUFFER == dwError )
{
cbBufSize = dwBytesNeeded;
lpsd = (LPSERVICE_DESCRIPTION) LocalAlloc(LMEM_FIXED, cbBufSize);
}
else
{
printf("QueryServiceConfig2 failed (%d)", dwError);
goto cleanup;
}
}

if (! QueryServiceConfig2(
schService,
SERVICE_CONFIG_DESCRIPTION,
(LPBYTE) lpsd,
cbBufSize,
&dwBytesNeeded) )
{
printf("QueryServiceConfig2 failed (%d)", GetLastError());
goto cleanup;
}

// Print the configuration information.

_tprintf(TEXT("%s configuration: \n"), szSvcName);
_tprintf(TEXT("  Type: 0x%x\n"), lpsc->dwServiceType);
_tprintf(TEXT("  Start Type: 0x%x\n"), lpsc->dwStartType);
_tprintf(TEXT("  Error Control: 0x%x\n"), lpsc->dwErrorControl);
_tprintf(TEXT("  Binary path: %s\n"), lpsc->lpBinaryPathName);
_tprintf(TEXT("  Account: %s\n"), lpsc->lpServiceStartName);

if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, TEXT("")) != 0)
_tprintf(TEXT("  Description: %s\n"), lpsd->lpDescription);
if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, TEXT("")) != 0)
_tprintf(TEXT("  Load order group: %s\n"), lpsc->lpLoadOrderGroup);
if (lpsc->dwTagId != 0)
_tprintf(TEXT("  Tag ID: %d\n"), lpsc->dwTagId);
if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT("")) != 0)
_tprintf(TEXT("  Dependencies: %s\n"), lpsc->lpDependencies);

LocalFree(lpsc);
LocalFree(lpsd);

cleanup:
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Disables the service.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoDisableSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,            // SCM database
szSvcName,               // name of service
SERVICE_CHANGE_CONFIG);  // need change config access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Change the service start type.

if (! ChangeServiceConfig(
schService,        // handle of service
SERVICE_NO_CHANGE, // service type: no change
SERVICE_DISABLED,  // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL,              // binary path: no change
NULL,              // load order group: no change
NULL,              // tag ID: no change
NULL,              // dependencies: no change
NULL,              // account name: no change
NULL,              // password: no change
NULL) )            // display name: no change
{
printf("ChangeServiceConfig failed (%d)\n", GetLastError());
}
else printf("Service disabled successfully.\n");

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Enables the service.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoEnableSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,            // SCM database
szSvcName,               // name of service
SERVICE_CHANGE_CONFIG);  // need change config access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Change the service start type.

if (! ChangeServiceConfig(
schService,            // handle of service
SERVICE_NO_CHANGE,     // service type: no change
SERVICE_DEMAND_START,  // service start type
SERVICE_NO_CHANGE,     // error control: no change
NULL,                  // binary path: no change
NULL,                  // load order group: no change
NULL,                  // tag ID: no change
NULL,                  // dependencies: no change
NULL,                  // account name: no change
NULL,                  // password: no change
NULL) )                // display name: no change
{
printf("ChangeServiceConfig failed (%d)\n", GetLastError());
}
else printf("Service enabled successfully.\n");

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Updates the service description to "This is a test description".
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoUpdateSvcDesc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_DESCRIPTION sd;
LPTSTR szDesc = TEXT("This is a test description");

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,            // SCM database
szSvcName,               // name of service
SERVICE_CHANGE_CONFIG);  // need change config access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Change the service description.

sd.lpDescription = szDesc;

if( !ChangeServiceConfig2(
schService,                 // handle to service
SERVICE_CONFIG_DESCRIPTION, // change: description
&sd) )                      // new description
{
printf("ChangeServiceConfig2 failed\n");
}
else printf("Service description updated successfully.\n");

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Deletes a service from the SCM database
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoDeleteSvc()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
SERVICE_STATUS ssStatus;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,       // SCM database
szSvcName,          // name of service
DELETE);            // need delete access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Delete the service.

if (! DeleteService(schService) )
{
printf("DeleteService failed (%d)\n", GetLastError());
}
else printf("Service deleted successfully\n");

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}


svccontrol.cpp

#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <aclapi.h>
#include <stdio.h>

#pragma comment(lib, "advapi32.lib")

TCHAR szCommand[10];
TCHAR szSvcName[80];

SC_HANDLE schSCManager;
SC_HANDLE schService;

VOID __stdcall DisplayUsage(void);

VOID __stdcall DoStartSvc(void);
VOID __stdcall DoUpdateSvcDacl(void);
VOID __stdcall DoStopSvc(void);

BOOL __stdcall StopDependentServices(void);

//
// Purpose:
//   Entry point function. Executes specified command from user.
//
// Parameters:
//   Command-line syntax is: svccontrol [command] [service_name]
//
// Return value:
//   None
//
void _tmain(int argc, TCHAR *argv[])
{
printf("\n");
if( argc != 3 )
{
printf("ERROR: Incorrect number of arguments\n\n");
DisplayUsage();
return;
}

StringCchCopy(szCommand, 10, argv[1]);
StringCchCopy(szSvcName, 80, argv[2]);

if (lstrcmpi( szCommand, TEXT("start")) == 0 )
DoStartSvc();
else if (lstrcmpi( szCommand, TEXT("dacl")) == 0 )
DoUpdateSvcDacl();
else if (lstrcmpi( szCommand, TEXT("stop")) == 0 )
DoStopSvc();
else
{
_tprintf(TEXT("Unknown command (%s)\n\n"), szCommand);
DisplayUsage();
}
}

VOID __stdcall DisplayUsage()
{
printf("Description:\n");
printf("\tCommand-line tool that controls a service.\n\n");
printf("Usage:\n");
printf("\tsvccontrol [command] [service_name]\n\n");
printf("\t[command]\n");
printf("\t  start\n");
printf("\t  dacl\n");
printf("\t  stop\n");
}

//
// Purpose:
//   Starts the service if possible.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoStartSvc()
{
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwOldCheckPoint;
DWORD dwStartTickCount;
DWORD dwWaitTime;
DWORD dwBytesNeeded;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // servicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,         // SCM database
szSvcName,            // name of service
SERVICE_ALL_ACCESS);  // full access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Check the status in case the service is not stopped.

if (!QueryServiceStatusEx(
schService,                     // handle to service
SC_STATUS_PROCESS_INFO,         // information level
(LPBYTE) &ssStatus,             // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) )              // size needed if buffer is too small
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}

// Check if the service is already running. It would be possible
// to stop the service here, but for simplicity this example just returns.

if(ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
{
printf("Cannot start the service because it is already running\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}

// Save the tick count and initial checkpoint.

dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;

// Wait for the service to stop before attempting to start it.

while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
{
// Do not wait longer than the wait hint. A good interval is
// one-tenth of the wait hint but not less than 1 second
// and not more than 10 seconds.

dwWaitTime = ssStatus.dwWaitHint / 10;

if( dwWaitTime < 1000 )
dwWaitTime = 1000;
else if ( dwWaitTime > 10000 )
dwWaitTime = 10000;

Sleep( dwWaitTime );

// Check the status until the service is no longer stop pending.

if (!QueryServiceStatusEx(
schService,                     // handle to service
SC_STATUS_PROCESS_INFO,         // information level
(LPBYTE) &ssStatus,             // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) )              // size needed if buffer is too small
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}

if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
{
// Continue to wait and check.

dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
}
else
{
if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
{
printf("Timeout waiting for service to stop\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
}
}

// Attempt to start the service.

if (!StartService(
schService,  // handle to service
0,           // number of arguments
NULL) )      // no arguments
{
printf("StartService failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}
else printf("Service start pending...\n");

// Check the status until the service is no longer start pending.

if (!QueryServiceStatusEx(
schService,                     // handle to service
SC_STATUS_PROCESS_INFO,         // info level
(LPBYTE) &ssStatus,             // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) )              // if buffer too small
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return;
}

// Save the tick count and initial checkpoint.

dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;

while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
{
// Do not wait longer than the wait hint. A good interval is
// one-tenth the wait hint, but no less than 1 second and no
// more than 10 seconds.

dwWaitTime = ssStatus.dwWaitHint / 10;

if( dwWaitTime < 1000 )
dwWaitTime = 1000;
else if ( dwWaitTime > 10000 )
dwWaitTime = 10000;

Sleep( dwWaitTime );

// Check the status again.

if (!QueryServiceStatusEx(
schService,             // handle to service
SC_STATUS_PROCESS_INFO, // info level
(LPBYTE) &ssStatus,             // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) )              // if buffer too small
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
break;
}

if ( ssStatus.dwCheckPoint > dwOldCheckPoint )
{
// Continue to wait and check.

dwStartTickCount = GetTickCount();
dwOldCheckPoint = ssStatus.dwCheckPoint;
}
else
{
if(GetTickCount()-dwStartTickCount > ssStatus.dwWaitHint)
{
// No progress made within the wait hint.
break;
}
}
}

// Determine whether the service is running.

if (ssStatus.dwCurrentState == SERVICE_RUNNING)
{
printf("Service started successfully.\n");
}
else
{
printf("Service not started. \n");
printf("  Current State: %d\n", ssStatus.dwCurrentState);
printf("  Exit Code: %d\n", ssStatus.dwWin32ExitCode);
printf("  Check Point: %d\n", ssStatus.dwCheckPoint);
printf("  Wait Hint: %d\n", ssStatus.dwWaitHint);
}

CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

//
// Purpose:
//   Updates the service DACL to grant start, stop, delete, and read
//   control access to the Guest account.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoUpdateSvcDacl()
{
EXPLICIT_ACCESS      ea;
SECURITY_DESCRIPTOR  sd;
PSECURITY_DESCRIPTOR psd            = NULL;
PACL                 pacl           = NULL;
PACL                 pNewAcl        = NULL;
BOOL                 bDaclPresent   = FALSE;
BOOL                 bDaclDefaulted = FALSE;
DWORD                dwError        = 0;
DWORD                dwSize         = 0;
DWORD                dwBytesNeeded  = 0;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service

schService = OpenService(
schSCManager,              // SCManager database
szSvcName,                 // name of service
READ_CONTROL | WRITE_DAC); // access

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Get the current security descriptor.

if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION,
&psd,           // using NULL does not work on all versions
0,
&dwBytesNeeded))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
dwSize = dwBytesNeeded;
psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, dwSize);
if (psd == NULL)
{
// Note: HeapAlloc does not support GetLastError.
printf("HeapAlloc failed\n");
goto dacl_cleanup;
}

if (!QueryServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
{
printf("QueryServiceObjectSecurity failed (%d)\n", GetLastError());
goto dacl_cleanup;
}
}
else
{
printf("QueryServiceObjectSecurity failed (%d)\n", GetLastError());
goto dacl_cleanup;
}
}

// Get the DACL.

if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
&bDaclDefaulted))
{
printf("GetSecurityDescriptorDacl failed(%d)\n", GetLastError());
goto dacl_cleanup;
}

// Build the ACE.

BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
SET_ACCESS, NO_INHERITANCE);

dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
if (dwError != ERROR_SUCCESS)
{
printf("SetEntriesInAcl failed(%d)\n", dwError);
goto dacl_cleanup;
}

// Initialize a new security descriptor.

if (!InitializeSecurityDescriptor(&sd,
SECURITY_DESCRIPTOR_REVISION))
{
printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
goto dacl_cleanup;
}

// Set the new DACL in the security descriptor.

if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
{
printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
goto dacl_cleanup;
}

// Set the new DACL for the service object.

if (!SetServiceObjectSecurity(schService,
DACL_SECURITY_INFORMATION, &sd))
{
printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
goto dacl_cleanup;
}
else printf("Service DACL updated successfully\n");

dacl_cleanup:
CloseServiceHandle(schSCManager);
CloseServiceHandle(schService);

if(NULL != pNewAcl)
LocalFree((HLOCAL)pNewAcl);
if(NULL != psd)
HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
}

//
// Purpose:
//   Stops the service.
//
// Parameters:
//   None
//
// Return value:
//   None
//
VOID __stdcall DoStopSvc()
{
SERVICE_STATUS_PROCESS ssp;
DWORD dwStartTime = GetTickCount();
DWORD dwBytesNeeded;
DWORD dwTimeout = 30000; // 30-second time-out
DWORD dwWaitTime;

// Get a handle to the SCM database.

schSCManager = OpenSCManager(
NULL,                    // local computer
NULL,                    // ServicesActive database
SC_MANAGER_ALL_ACCESS);  // full access rights

if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}

// Get a handle to the service.

schService = OpenService(
schSCManager,         // SCM database
szSvcName,            // name of service
SERVICE_STOP |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS);

if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}

// Make sure the service is not already stopped.

if ( !QueryServiceStatusEx(
schService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
goto stop_cleanup;
}

if ( ssp.dwCurrentState == SERVICE_STOPPED )
{
printf("Service is already stopped.\n");
goto stop_cleanup;
}

// If a stop is pending, wait for it.

while ( ssp.dwCurrentState == SERVICE_STOP_PENDING )
{
printf("Service stop pending...\n");

// Do not wait longer than the wait hint. A good interval is
// one-tenth of the wait hint but not less than 1 second
// and not more than 10 seconds.

dwWaitTime = ssp.dwWaitHint / 10;

if( dwWaitTime < 1000 )
dwWaitTime = 1000;
else if ( dwWaitTime > 10000 )
dwWaitTime = 10000;

Sleep( dwWaitTime );

if ( !QueryServiceStatusEx(
schService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
goto stop_cleanup;
}

if ( ssp.dwCurrentState == SERVICE_STOPPED )
{
printf("Service stopped successfully.\n");
goto stop_cleanup;
}

if ( GetTickCount() - dwStartTime > dwTimeout )
{
printf("Service stop timed out.\n");
goto stop_cleanup;
}
}

// If the service is running, dependencies must be stopped first.

StopDependentServices();

// Send a stop code to the service.

if ( !ControlService(
schService,
SERVICE_CONTROL_STOP,
(LPSERVICE_STATUS) &ssp ) )
{
printf( "ControlService failed (%d)\n", GetLastError() );
goto stop_cleanup;
}

// Wait for the service to stop.

while ( ssp.dwCurrentState != SERVICE_STOPPED )
{
Sleep( ssp.dwWaitHint );
if ( !QueryServiceStatusEx(
schService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
{
printf( "QueryServiceStatusEx failed (%d)\n", GetLastError() );
goto stop_cleanup;
}

if ( ssp.dwCurrentState == SERVICE_STOPPED )
break;

if ( GetTickCount() - dwStartTime > dwTimeout )
{
printf( "Wait timed out\n" );
goto stop_cleanup;
}
}
printf("Service stopped successfully\n");

stop_cleanup:
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}

BOOL __stdcall StopDependentServices()
{
DWORD i;
DWORD dwBytesNeeded;
DWORD dwCount;

LPENUM_SERVICE_STATUS   lpDependencies = NULL;
ENUM_SERVICE_STATUS     ess;
SC_HANDLE               hDepService;
SERVICE_STATUS_PROCESS  ssp;

DWORD dwStartTime = GetTickCount();
DWORD dwTimeout = 30000; // 30-second time-out

// Pass a zero-length buffer to get the required buffer size.
if ( EnumDependentServices( schService, SERVICE_ACTIVE,
lpDependencies, 0, &dwBytesNeeded, &dwCount ) )
{
// If the Enum call succeeds, then there are no dependent
// services, so do nothing.
return TRUE;
}
else
{
if ( GetLastError() != ERROR_MORE_DATA )
return FALSE; // Unexpected error

// Allocate a buffer for the dependencies.
lpDependencies = (LPENUM_SERVICE_STATUS) HeapAlloc(
GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded );

if ( !lpDependencies )
return FALSE;

__try {
// Enumerate the dependencies.
if ( !EnumDependentServices( schService, SERVICE_ACTIVE,
lpDependencies, dwBytesNeeded, &dwBytesNeeded,
&dwCount ) )
return FALSE;

for ( i = 0; i < dwCount; i++ )
{
ess = *(lpDependencies + i);
// Open the service.
hDepService = OpenService( schSCManager,
ess.lpServiceName,
SERVICE_STOP | SERVICE_QUERY_STATUS );

if ( !hDepService )
return FALSE;

__try {
// Send a stop code.
if ( !ControlService( hDepService,
SERVICE_CONTROL_STOP,
(LPSERVICE_STATUS) &ssp ) )
return FALSE;

// Wait for the service to stop.
while ( ssp.dwCurrentState != SERVICE_STOPPED )
{
Sleep( ssp.dwWaitHint );
if ( !QueryServiceStatusEx(
hDepService,
SC_STATUS_PROCESS_INFO,
(LPBYTE)&ssp,
sizeof(SERVICE_STATUS_PROCESS),
&dwBytesNeeded ) )
return FALSE;

if ( ssp.dwCurrentState == SERVICE_STOPPED )
break;

if ( GetTickCount() - dwStartTime > dwTimeout )
return FALSE;
}
}
__finally
{
// Always release the service handle.
CloseServiceHandle( hDepService );
}
}
}
__finally
{
// Always free the enumeration buffer.
HeapFree( GetProcessHeap(), 0, lpDependencies );
}
}
return TRUE;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: