Author: gedmurphy
Date: Mon Mar 31 09:41:06 2008
New Revision: 32793
URL:
http://svn.reactos.org/svn/reactos?rev=32793&view=rev
Log:
I wrote a quick skeleton service this morning, thought it might be useful to someone.
Added:
trunk/rosapps/skel_service/
trunk/rosapps/skel_service/ServiceMain.c (with props)
trunk/rosapps/skel_service/log.c (with props)
trunk/rosapps/skel_service/myservice.h (with props)
Added: trunk/rosapps/skel_service/ServiceMain.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rosapps/skel_service/ServiceMain.c…
==============================================================================
--- trunk/rosapps/skel_service/ServiceMain.c (added)
+++ trunk/rosapps/skel_service/ServiceMain.c [iso-8859-1] Mon Mar 31 09:41:06 2008
@@ -1,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(a)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;
+}
Propchange: trunk/rosapps/skel_service/ServiceMain.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rosapps/skel_service/log.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rosapps/skel_service/log.c?rev=327…
==============================================================================
--- trunk/rosapps/skel_service/log.c (added)
+++ trunk/rosapps/skel_service/log.c [iso-8859-1] Mon Mar 31 09:41:06 2008
@@ -1,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(a)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
+}
Propchange: trunk/rosapps/skel_service/log.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rosapps/skel_service/myservice.h
URL:
http://svn.reactos.org/svn/reactos/trunk/rosapps/skel_service/myservice.h?r…
==============================================================================
--- trunk/rosapps/skel_service/myservice.h (added)
+++ trunk/rosapps/skel_service/myservice.h [iso-8859-1] Mon Mar 31 09:41:06 2008
@@ -1,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();
Propchange: trunk/rosapps/skel_service/myservice.h
------------------------------------------------------------------------------
svn:eol-style = native