I wrote a quick skeleton service this morning, thought it might be useful to someone.

svn path=/trunk/; revision=32793
This commit is contained in:
Ged Murphy 2008-03-31 14:41:06 +00:00
parent bae8253dc7
commit 317b7559ff
3 changed files with 414 additions and 0 deletions

View file

@ -0,0 +1,199 @@
/*
* PROJECT: ReactOS services
* LICENSE: GPL - See COPYING in the top level directory
* FILE:
* PURPOSE: skeleton service
* COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "myservice.h"
volatile BOOL bShutDown = FALSE;
volatile BOOL bPause = FALSE;
LPTSTR ServiceName = _T("skel_service");
typedef struct _ServiceInfo
{
SERVICE_STATUS servStatus;
SERVICE_STATUS_HANDLE hStatus;
} SERVICEINFO, *PSERVICEINFO;
/********* To be moved to new file **********/
typedef struct _ServiceData
{
INT val1;
INT val2;
} SERVICEDATA, *PSERVICEDATA;
DWORD WINAPI ThreadProc(LPVOID lpParam)
{
while (!bShutDown)
Sleep(1000);
return 0;
}
/*******************************************/
VOID
UpdateStatus(PSERVICEINFO pServInfo,
DWORD NewStatus,
DWORD Check)
{
TCHAR szSet[50];
if (Check > 0)
pServInfo->servStatus.dwCheckPoint += Check;
else
pServInfo->servStatus.dwCheckPoint = Check;
if (NewStatus > 0)
pServInfo->servStatus.dwCurrentState = NewStatus;
_sntprintf(szSet, 49, _T("Setting service to 0x%lu, CheckPoint %lu"), NewStatus, pServInfo->servStatus.dwCheckPoint);
LogEvent(szSet, 0, 0, LOG_FILE);
if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus))
LogEvent(_T("Cannot set service status"), GetLastError(), 0, LOG_ALL);
return;
}
INT
CreateServiceThread(PSERVICEINFO pServInfo)
{
HANDLE hThread;
PSERVICEDATA servData;
UpdateStatus(pServInfo, 0, 1);
LogEvent(_T("Creating service thread"), 0, 0, LOG_FILE);
hThread = CreateThread(NULL,
0,
ThreadProc,
&servData,
0,
NULL);
if (!hThread)
{
LogEvent(_T("Failed to start service thread"), GetLastError(), 101, LOG_ALL);
}
UpdateStatus(pServInfo, 0, 1);
LogEvent(_T("setting service status to running"), 0, 0, LOG_FILE);
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
WaitForSingleObject(hThread, INFINITE);
if (hThread)
CloseHandle(hThread);
return 0;
}
VOID WINAPI
ServerCtrlHandler(DWORD dwControl,
DWORD dwEventType,
LPVOID lpEventData,
LPVOID lpContext)
{
PSERVICEINFO pServInfo = (PSERVICEINFO)lpContext;
switch (dwControl)
{
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
LogEvent(_T("\nSetting the service to SERVICE_STOP_PENDING"), 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bShutDown, TRUE);
pServInfo->servStatus.dwWin32ExitCode = 0;
pServInfo->servStatus.dwWaitHint = 0;
UpdateStatus(pServInfo, SERVICE_STOP_PENDING, 1);
break;
case SERVICE_CONTROL_PAUSE:
LogEvent(_T("Setting the service to SERVICE_PAUSED"), 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bPause, TRUE);
UpdateStatus(pServInfo, SERVICE_PAUSED, 0);
break;
case SERVICE_CONTROL_CONTINUE:
LogEvent(_T("Setting the service to SERVICE_RUNNING"), 0, 0, LOG_FILE);
InterlockedExchange((LONG *)&bPause, FALSE);
UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
if (dwControl > 127 && dwControl < 256) /* user defined */
LogEvent(_T("User defined control code"), 0, 0, LOG_FILE);
else
LogEvent(_T("ERROR: Bad control code"), 0, 0, LOG_FILE);
break;
}
return;
}
VOID WINAPI
ServiceMain(DWORD argc, LPTSTR argv[])
{
SERVICEINFO servInfo;
LogEvent(_T("Entering ServiceMain"), 0, 0, LOG_FILE);
servInfo.servStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
servInfo.servStatus.dwCurrentState = SERVICE_STOPPED;
servInfo.servStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
servInfo.servStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
servInfo.servStatus.dwServiceSpecificExitCode = 0;
servInfo.servStatus.dwCheckPoint = 0;
servInfo.servStatus.dwWaitHint = 1000;
LogEvent(_T("Registering service control handler"), 0, 0, LOG_FILE);
servInfo.hStatus = RegisterServiceCtrlHandlerEx(ServiceName, ServerCtrlHandler, &servInfo);
if (!servInfo.hStatus)
LogEvent(_T("Failed to register service"), GetLastError(), 100, LOG_ALL);
UpdateStatus(&servInfo, SERVICE_START_PENDING, 1);
if (CreateServiceThread(&servInfo) != 0)
{
servInfo.servStatus.dwServiceSpecificExitCode = 1;
UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
return;
}
LogEvent(_T("Service thread shut down. Set SERVICE_STOPPED status"), 0, 0, LOG_FILE);
UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
LogEvent(_T("Leaving ServiceMain"), 0, 0, LOG_FILE);
return;
}
int _tmain(int argc, LPTSTR argv[])
{
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{ServiceName, ServiceMain},
{NULL, NULL }
};
InitLogging();
if (!StartServiceCtrlDispatcher(ServiceTable))
LogEvent(_T("failed to start the service control dispatcher"), GetLastError(), 101, LOG_ALL);
return 0;
}

194
rosapps/skel_service/log.c Normal file
View file

@ -0,0 +1,194 @@
/*
* PROJECT: ReactOS services
* LICENSE: GPL - See COPYING in the top level directory
* FILE:
* PURPOSE: skeleton service
* COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
*
*/
#include "myservice.h"
static LPTSTR lpEventSource = _T("Skeleton service");
static LPTSTR lpLogFileName = _T("C:\\skel_service.log");
static HANDLE hLogFile;
// needs work
static VOID
LogToEventLog(LPCTSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
HANDLE hEventLog;
hEventLog = RegisterEventSource(NULL, lpEventSource);
if (hEventLog)
{
ReportEvent(hEventLog,
(flags & LOG_ERROR) ? EVENTLOG_ERROR_TYPE : EVENTLOG_SUCCESS,
0,
0,
NULL,
1,
0,
&lpMsg,
NULL);
CloseEventLog(hEventLog);
}
}
static BOOL
OpenLogFile()
{
hLogFile = CreateFile(lpLogFileName,
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hLogFile == INVALID_HANDLE_VALUE)
return FALSE;
return TRUE;
}
static BOOL
LogToFile(LPCTSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
LPTSTR lpFullMsg = NULL;
DWORD msgLen;
if (!OpenLogFile())
return FALSE;
msgLen = _tcslen(lpMsg) + 1;
if (flags & LOG_ERROR)
{
LPVOID lpSysMsg;
DWORD eMsgLen;
eMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
errNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpSysMsg,
0,
NULL);
msgLen = msgLen + eMsgLen + 26;
lpFullMsg = HeapAlloc(GetProcessHeap(),
0,
msgLen * sizeof(TCHAR));
if (lpFullMsg)
{
_sntprintf(lpFullMsg,
msgLen,
_T("%s %s ErrNum = %lu ExitCode = %lu\r\n"),
lpMsg,
lpSysMsg,
errNum,
exitCode);
}
LocalFree(lpSysMsg);
}
else
{
msgLen += 2;
lpFullMsg = HeapAlloc(GetProcessHeap(),
0,
msgLen * sizeof(TCHAR));
if (lpFullMsg)
{
_sntprintf(lpFullMsg,
msgLen,
_T("%s\r\n"),
lpMsg);
}
}
if (lpFullMsg)
{
DWORD bytesWritten;
SetFilePointer(hLogFile, 0, NULL, FILE_END);
WriteFile(hLogFile,
lpFullMsg,
msgLen * sizeof(TCHAR),
&bytesWritten,
NULL);
if (bytesWritten == 0)
{
LogToEventLog(_T("Failed to write to log file"),
GetLastError(),
0,
LOG_EVENTLOG | LOG_ERROR);
}
HeapFree(GetProcessHeap(),
0,
lpFullMsg);
}
CloseHandle(hLogFile);
if (exitCode > 0)
ExitProcess(exitCode);
}
VOID
LogEvent(LPCTSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags)
{
#ifdef DEBUG
if (flags & LOG_FILE)
LogToFile(lpMsg, errNum, exitCode, flags);
#endif
if (flags & LOG_EVENTLOG)
LogToEventLog(lpMsg, errNum, exitCode, flags);
}
VOID
InitLogging()
{
WCHAR wcBom = 0xFEFF;
DeleteFile(lpLogFileName);
#ifdef _UNICODE
if (OpenLogFile())
{
DWORD bytesWritten;
WriteFile(hLogFile,
&wcBom,
sizeof(WCHAR),
&bytesWritten,
NULL);
if (bytesWritten == 0)
{
LogToEventLog(_T("Failed to write to log file"),
GetLastError(),
0,
LOG_EVENTLOG | LOG_ERROR);
}
CloseHandle(hLogFile);
}
#endif
}

View file

@ -0,0 +1,21 @@
#include <windows.h>
#include <tchar.h>
#define DEBUG 1
#define LOG_FILE 1
#define LOG_EVENTLOG 2
#define LOG_ERROR 4
#define LOG_ALL (LOG_FILE | LOG_EVENTLOG | LOG_ERROR)
extern volatile BOOL bShutDown;
extern volatile BOOL bPause;
VOID
LogEvent(LPCTSTR lpMsg,
DWORD errNum,
DWORD exitCode,
UINT flags);
VOID
InitLogging();