Windows service: start and initialize C Win32 program example
#include <windows.h>
#include <stdio.h>
SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;
void SvcDebugOut(LPSTR String, DWORD Status);
void WINAPI MyServiceCtrlHandler(DWORD opcode);
void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv);
DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError);
void main(void)
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{L"TIntSvr", (LPSERVICE_MAIN_FUNCTIONW)MyServiceStart}, {NULL, NULL}
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
SvcDebugOut("StartServiceCtrlDispatcher() failed", GetLastError());
}
else
printf("StartServiceCtrlDispatcher() is OK\n");
}
VOID WINAPI MyServiceCtrlHandler(DWORD Opcode)
{
DWORD status;
switch(Opcode)
{
case SERVICE_CONTROL_PAUSE:
// Do whatever it takes to pause here.
MyServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
// Do whatever it takes to continue here.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
// Do whatever it takes to stop here.
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus(MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus() error", status);
}
SvcDebugOut("Leaving Telnet service", 0);
return;
case SERVICE_CONTROL_INTERROGATE:
// Fall through to send current status.
break;
default:
SvcDebugOut("Unrecognized opcode", Opcode);
}
// Send current status.
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus() error", status);
}
return;
}
void WINAPI MyServiceStart(DWORD argc, LPTSTR *argv)
{
DWORD status;
DWORD specificError;
MyServiceStatus.dwServiceType = SERVICE_WIN32;
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
// If the function succeeds, the return value is a service status handle. If the function fails, the return value is zero.
MyServiceStatusHandle = RegisterServiceCtrlHandler(
L"TIntSvr",
MyServiceCtrlHandler); // function pointer
if (MyServiceStatusHandle == 0)
{
SvcDebugOut("RegisterServiceCtrlHandler() failed", GetLastError());
return;
}
else
printf("RegisterServiceCtrlHandler() is OK\n");
// Initialization code goes here.
status = MyServiceInitialization(argc, argv, &specificError);
// Handle error condition
if (status != NO_ERROR)
{
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
MyServiceStatus.dwWin32ExitCode = status;
MyServiceStatus.dwServiceSpecificExitCode = specificError;
SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus);
return;
}
// Initialization complete - report running status.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus))
{
status = GetLastError();
SvcDebugOut("SetServiceStatus() error", status);
}
else
printf("SetServiceStatus() is OK\n");
// This is where the service does its work.
SvcDebugOut("Returning the Main Thread", 0);
return;
}
// Stub initialization function.
DWORD MyServiceInitialization(DWORD argc, LPTSTR *argv, DWORD *specificError)
{
// Just dummy
argv;
argc;
specificError;
return 0;
}
VOID SvcDebugOut(LPSTR String, DWORD Status)
{
CHAR Buffer[1024];
if (strlen(String) < 1000)
{
sprintf_s(Buffer, sizeof(Buffer), String, Status);
// Check the output window at the bottom if you debug this program
OutputDebugStringA(Buffer);
// Or redirect to the standard output...
printf("The error message: %s, the error code: %ld\n", Buffer, Status);
}
}
Output example:
The error message: StartServiceCtrlDispatcher() failed, the error code: 1063
Press any key to continue . . .
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT - (1063) The service process could not connect to the service controller
This is not a complete working example. Please refer to : Windows Services Programming with Win32 for a complete working example.
Compiler: Visual C++ Express Edition 2005
Compiled on Platform: Windows XP Pro SP2
Target platform: none, just for learning and fun
Header file: Standard and Windows
Additional library: Windows Platform SDK
Additional project setting: Set project to be compiled as C. Click Project menu->your_project_name Properties->Configuration Properties->C/C++->Advanced->Compiled As: Compiled as C Code (/TC)
Other info: non-CLR or unmanaged. Need to add Advapi32.lib (Advapi32.dll) to the project. Click the Project menu->Select the your_project_name Properties... sub menu->Expand the Configuration Properties folder on the left pane->Expand the Linker subfolder->Select the Input subfolder->Select the Additional Dependencies field on the right pane->Click the ... at the end of the field->Type in 'Advapi32.lib' in the empty pane->Click the OK button->Click the OK button second time to close the project Properties dialog.
To do: The Windows service Win32 programming: start and initialize
To show: Windows processes and services