Introduction
Write a service isn't allways easy, specialy when you have a lot of existing code to deal with. The OSR_Service toolkit is a set of C files you can include into your C/C++ projects to write window services functionalities in few lines.
The ServiceStart function
The ServiceStart function start the service. It may be called at the begin of the application.
OSR_ERROR OSR_CALL ServiceStart(OSR_SERVICE_PARAMS * Params)
Parameters
Params
Pointer to the OSR_SEVICE_PARAMS
structure the contains the servis start parameters and preferences.
Return Values
If the function succeeds, the return value is OSR_SUCCESS.
Remarks
Ideally, this function must be called in the main function (
WinMain
) before the the code the application may execute when the service is running.
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
OSR_SERVICE_PARAMS params;
params.ServiceDependencies[0] = 0;
params.ServiceDependencies[1] = 0;
strcpy((char *)params.ServiceLogin,".\\Administrateur");
strcpy((char *)params.ServicePassword,"AdminPassword");
strcpy((char *)params.ServiceName,"OSR_SAPMPLE_SERVICE");
strcpy((char *)params.ServiceNameDisplay,"OSR sample service");
params.ServiceAcceptedCommands = SERVICE_ACCEPT_STOP|
SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_SHUTDOWN;
params.ServiceStartType = SERVICE_DEMAND_START;
if(strcmp(lpCmdLine,"install") == 0)
{
ServiceInstall(¶ms);
}
else
{
if(strcmp(lpCmdLine,"uninstall") == 0)
{
ServiceUninstall(¶ms);
}
else
{
ServiceStart(¶ms);
while(!stop_request)
{
printf("I'm a running service\n");
Sleep(1000);
}
}
}
return 0;
}
The OSR_APP_XXX Functions
Four callback functions must be wrote by the user to handle the service messages. This functions are :
int OSR_CALL OSR_APP_START(int step);
int OSR_CALL OSR_APP_STOP(int step);
int OSR_CALL OSR_APP_PAUSE(int step);
int OSR_CALL OSR_APP_CONTINUE(int step);
int OSR_CALL OSR_APP_SHUTDOWN(int step);
When the service receives a message form the service manager, requisting for a new status (eg. the service is running, and we want to stop it), the OSR_APP_STOP
is called one time. According to the returned value by this function, the function will be called as long as is necesary to complete the stop process.
Explanation
As decribed in the fig 1., a service has 3 major states (
STOPED
,
RUNNING
,
PAUSED
) and 4 pending states (
START PENDING
,
PAUSE PENDING
,
CONTINUE PENDING
,
STOP PENDING
) .
fig1. service states
The major states are states requested by a service manager (eg. stop the service), and the pending states are transitory states between 2 major states. A way to the application to say to the service manager "Ok! I'm doing the required things to stop the application, please wait".
Parameters
step
The step is an incremential value sent to the function every time the function is called under the same status change.
Return Values
The function can return 3 values
Value |
Meaning |
OSR_SERVICE_WAIT
|
The init process is not completed, the service stay in a pending state, and this function will be called again and the step value increased.
|
OSR_SERVICE_DONE
|
The init process is completed. The service can be in the requested state.
|
OSR_SERVICE_ABORT
|
The init process can't be done, or fail. The status can't be changed. |
Remarks
All these functions must be return a result to allow the status update.
For the OSR_APP_START function, you may launch a new thread to run something after the start initialization.
Here a simple start process in 3 steps.
int OSR_CALL OSR_APP_START(int step)
{
switch(step)
{
case 0:
OpenLogFile();
return OSR_SERVICE_WAIT
break;
case 1:
InitSocket();
return OSR_SERVICE_WAIT;
break;
case 2:
return OSR_SERVICE_DONE;
break;
}
The OSR_SERVICE_PARAMS structure
typedef struct _OSR_SERVICE_PARAMS
{
UCHAR ServiceName[STR_CHAR32];
UCHAR ServiceNameDisplay[STR_CHAR32];
UCHAR ServiceDependencies[STR_CHAR64];
U32BIT ServiceStartType;
UCHAR ServiceLogin[STR_CHAR32];
UCHAR ServicePassword[STR_CHAR32];
U32BIT ServiceAcceptedCommands;
}OSR_SERVICE_PARAMS;
Members
ServiceName
Null-terminated string that names the service. "\" and "/" characters are invalid in the service name.
ServiceNameDisplay
Null-terminated string that is to be used by user interface programs to identify the service.
ServiceDependencies
Double null-terminated array of null-separated names of services or load ordering groups that the system must start before this service. Specify NULL if no dependencies are required.
- "NetworkService\0LogService\0\0" means NetworkService and LogService may be started before allow your service to start.
- "\0\0" means no dependencied are defined.
ServiceStartType
Specifies when to start the service. You must specify one of the following start types
Value |
Meaning |
SERVICE_AUTO_START
|
Specifies a service to be started automatically by the service control manager during system startup.
|
SERVICE_DEMAND_START
|
Specifies a service to be started by the service control manager when a process calls the StartService function.
|
SERVICE_DISABLED |
Specifies a service that can no longer be started. |
ServiceLogin
Null-terminated string that names the service. You must use an account name in the form DomainName\UserName. Because the account belongs to the built-in domain, you can specify .\UserName. You also must specify the LocalSystem account. If you specify an empty string ("\0") LocalSystem account is used.
ServicePassword
Null-terminated string that contains the password to the account name specified by the ServiceLogin parameter. If the string is empty, the service has no password.
Using the sample
This project is provided with a sample project who demostrate how to integrate the osr_service code in "real" code. The sample code include a precompiled binary - for X86 win32 platforms - who run in this way.
sample_service [install|uninstall] to install or remove the service from the service manager. For your convenience I build it with the system account, ie. no change is require for a first try.
The sample, and basicaly all the osr_service functions run in a debug mode, who log all the errors using the OutputDebugString log method. To display the logs you must use a tool like
DebugView from the SysInternals guys (
www.sysinternals.com). This tool is free.