- •Contents of the Report
- •Introduction
- •1. Algorithm of the service program
- •2. Algorithms of the service management program
- •3. Algorithm of the client program
- •4. Implementation of service program
- •5. Implementation of service management program
- •6. Implementation of client program
- •Appendix a Source code of service program
- •Appendix b Source code of scm_console program
- •Appendix c Source code of client program
6. Implementation of client program
SetNamedPipeHandleState - sets the read mode and the blocking mode of the specified named pipe [msdn].
date_time – gets data from user, checks it, sends to service and gets reply
SetNamedPipeHandleState - sets the read mode and the blocking mode of the specified named pipe [msdn].
_tmain - interacts with user.
Conclusion
During the course project were developed three programs: the windows service program, service control program and client program that sends the request to the service program which has to perform the determination of command line of service and transfer this obtained string with all parameters to the client program via the named pipe. The service program is started from service control program and waits fro the request from the client until this client sends the request. The service control program can determine the state of service program, start it, continue it after stop instruction, stop the service program, determine the dependencies of service program, restart the service program.
References
Solomon, D.A. and Russinovich M.E. (2000). Inside Microsoft Windows 2000. Microsoft Press
Microsoft Corporation MSDN Library
Richter, J. and Clark J.D. (2000). Programming Server-Side Applications for Microsoft Windows 2000. Microsoft Press
Appendix a Source code of service program
AD. 091501.06/67833.
Pages______
Donetsk – 2010
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#ifdef UNICODE
#define tcin wcin
#else
#define tcin cin
#endif
#define BUFSIZE 16
//global vars
SERVICE_STATUS sStatus; //Service Status structure
SERVICE_STATUS_HANDLE hsSstatus; //Service Status Handler
BOOL bServWork; //Main service loop condition, if TRUE - service works
HANDLE hPauseEvent; //Pause Service Event
HANDLE hPipe; //Pipe handler
SYSTEMTIME st; //System Time Structure
LPTSTR lPipename = _T("\\\\.\\pipe\\mypipe");//Pipe Name
char lSet[100] = "The command line : "; //Msg1
char lFail[100] = "!!! The answer is unsuccessful !!!";
//prototype for funcs
VOID SvcDebugOut(LPSTR String, DWORD Status);//DbgOutput
VOID WINAPI StartServiceq (DWORD argc, LPTSTR *argv); //Main Service Function
VOID WINAPI ServiceControlHandler (DWORD opcode); //Service Control Handler for some events( pause, stop, etc..)
//main function, call service dispatcher
int main(int argc, char **argv)//*_TCHAR* argv[]*/)
{
//new
int i=0;
if (argc!=0)
{
for (i=0;i<argc;i++)
{
strcat(lSet," ");
strcat(lSet,argv[i]);
}
}
else
{
strcat(lSet,"Empty command line");
}
//new
SERVICE_TABLE_ENTRY dispTable[] =
{
{ "serv_cs06g_v17",StartServiceq },
{ NULL,NULL }
};
if (!StartServiceCtrlDispatcher(dispTable))
{
SvcDebugOut(" [MY_SERVICE] StartServiceCtrlDispatcher error = %d\n", GetLastError());
}
return 0;
}
//DEBUG OutPut
VOID SvcDebugOut(LPSTR String, DWORD Status)
{
CHAR Buffer[1024];
if (strlen(String) < 1000)
{
sprintf(Buffer, String, Status);
OutputDebugStringA(Buffer);
}
}
//startService func, initialization and main service func
VOID WINAPI StartServiceq (DWORD argc, LPTSTR *argv)
{
DWORD status = 0;
sStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
sStatus.dwCurrentState = SERVICE_START_PENDING;
sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;
sStatus.dwWin32ExitCode = 0;
sStatus.dwServiceSpecificExitCode = 0;
sStatus.dwCheckPoint = 0;
sStatus.dwWaitHint = 0;
hPauseEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
hsSstatus = RegisterServiceCtrlHandler("serv_cs06g_v17",ServiceControlHandler);
if (hsSstatus == (SERVICE_STATUS_HANDLE)0)
{
SvcDebugOut(" [MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
return;
}
// Initialization code goes here.
//pipe initialization
hPipe = CreateNamedPipe(lPipename, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
BUFSIZE, BUFSIZE, NMPWAIT_USE_DEFAULT_WAIT, NULL);
// if errors
if (hPipe == INVALID_HANDLE_VALUE)
{
SvcDebugOut(" [MY_SERVICE] CreateNamedPipe FAILED\n", GetLastError());
status = 1;
}
SvcDebugOut(" [MY_SERVICE] CreateNamedPipe SUCCESSED\n", GetLastError());
//pipe init end
// Handle error condition
if (status != NO_ERROR)
{
sStatus.dwCurrentState = SERVICE_STOPPED;
sStatus.dwCheckPoint = 0;
sStatus.dwWaitHint = 0;
sStatus.dwWin32ExitCode = status;
sStatus.dwServiceSpecificExitCode = status;
SetServiceStatus (hsSstatus, &sStatus);
return;
}
sStatus.dwCurrentState = SERVICE_RUNNING;
sStatus.dwCheckPoint = 0;
sStatus.dwWaitHint = 0;
if (!SetServiceStatus (hsSstatus, &sStatus))
{
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",status);
}
bServWork = TRUE;
// Task for service .......
while(bServWork)
{
WaitForSingleObject(hPauseEvent, INFINITE);
BOOL bConnected = FALSE, bReaded = FALSE, bSet = FALSE, bSended = FALSE;
DWORD dwRead = -1;
DWORD dwWrite = -1;
SvcDebugOut("CreateNamedPipe",0);
if (hPipe == INVALID_HANDLE_VALUE)
{
hPipe = CreateNamedPipe(lPipename, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE|PIPE_READMODE_MESSAGE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES,
BUFSIZE, BUFSIZE, NMPWAIT_USE_DEFAULT_WAIT, NULL);
}
SvcDebugOut("wait for connection",0);
bConnected = ConnectNamedPipe(hPipe, NULL);
if (bConnected)
{
bConnected = FALSE;
SvcDebugOut("Connected",0);
bReaded = ReadFile(hPipe,request,BUFSIZE,&dwRead,NULL);
if (bReaded)
{
SvcDebugOut("breaded = TRUE",0);
bSet = SetSystemTime(&st);
SvcDebugOut("bset",0);
if (bSet)
{
SvcDebugOut(" [MY_SERVICE] SetSystemTime() done \n",0);
//send message to client !DONE
bSended = WriteFile(hPipe,lSet,strlen(lSet),&dwWrite,NULL);
FlushFileBuffers(hPipe);
}
else
{
SvcDebugOut(" [MY_SERVICE] SetSystemTime() FAILED \n",0);
//send message to client !FAILED
bSended = WriteFile(hPipe,lFail,strlen(lFail),&dwWrite,NULL);
FlushFileBuffers(hPipe);
}
if (bSended)
{
SvcDebugOut(" [MY_SERVICE] !FAILED/!DONE sended to client \n",0);
}
}
SvcDebugOut("CloseHandle(hPipe)",0);
}// if(bCOnnected)
CloseHandle(hPipe);
hPipe = INVALID_HANDLE_VALUE;
}
CloseHandle(hPauseEvent);
//exit process
SvcDebugOut(" [MY_SERVICE] Returning the Main Thread \n",0);
return;
}
//service control handler, controlling main service func
VOID WINAPI ServiceControlHandler (DWORD dwSCHStatus)
{
DWORD dwStatus;
switch(dwSCHStatus)
{
case SERVICE_CONTROL_PAUSE:
// if pause.
SvcDebugOut("service_control_pause",0);
ResetEvent(hPauseEvent);
sStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
// if cont
SvcDebugOut("service_control_cont_running",0);
SetEvent(hPauseEvent);
sStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
// if stop
SvcDebugOut("service_control_stop",0);
bServWork = FALSE;
sStatus.dwWin32ExitCode = 0;
sStatus.dwCurrentState = SERVICE_STOPPED;
sStatus.dwCheckPoint = 0;
sStatus.dwWaitHint = 0;
hPipe = INVALID_HANDLE_VALUE;
//pipe delete end
if (!SetServiceStatus (hsSstatus,&sStatus))
{
dwStatus = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",dwStatus);
}
SvcDebugOut(" [MY_SERVICE] Leaving MyService \n",0);
SvcDebugOut("bServWork = FALSE",0);
return ;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
SvcDebugOut(" [MY_SERVICE] Unrecognized opcode %ld\n",dwSCHStatus);
}
// Send current status.
if (!SetServiceStatus (hsSstatus, &sStatus))
{
dwStatus = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",dwStatus);
}
}