ReactOS  0.4.11-dev-946-g431643b
tcpsvcs.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS simple TCP/IP services
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: base/services/tcpsvcs/tcpsvcs.c
5  * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services
6  * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "tcpsvcs.h"
11 
12 #include <winsvc.h>
13 
14 static WCHAR ServiceName[] = L"tcpsvcs";
15 
16 volatile BOOL bShutdown = FALSE;
17 volatile BOOL bPause = FALSE;
18 
19 typedef struct _ServiceInfo
20 {
24 
25 static SERVICES
27 {
28  {ECHO_PORT, L"Echo", EchoHandler},
29  {DISCARD_PORT, L"Discard", DiscardHandler},
30  {DAYTIME_PORT, L"Daytime", DaytimeHandler},
31  {QOTD_PORT, L"QOTD", QotdHandler},
32  {CHARGEN_PORT, L"Chargen", ChargenHandler}
33 };
34 
35 
36 static VOID
37 UpdateStatus(PSERVICEINFO pServInfo,
38  DWORD NewStatus,
39  DWORD Check)
40 {
41  WCHAR szSet[50];
42 
43  if (Check > 0)
44  pServInfo->servStatus.dwCheckPoint += Check;
45  else
46  pServInfo->servStatus.dwCheckPoint = Check;
47 
48  if (NewStatus > 0)
49  pServInfo->servStatus.dwCurrentState = NewStatus;
50 
51  _snwprintf(szSet,
52  49,
53  L"Service state 0x%lx, CheckPoint %lu",
54  pServInfo->servStatus.dwCurrentState,
55  pServInfo->servStatus.dwCheckPoint);
56  LogEvent(szSet, 0, 0, LOG_FILE);
57 
58  if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus))
59  LogEvent(L"Cannot set service status", GetLastError(), 0, LOG_ALL);
60 }
61 
62 
63 static BOOL
64 CreateServers(PSERVICEINFO pServInfo)
65 {
68  WSADATA wsaData;
69  WCHAR buf[256];
70  INT i;
71  DWORD RetVal;
72 
73  if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
74  {
75  swprintf(buf, L"WSAStartup() failed : %lu\n", RetVal);
76  LogEvent(buf, 0, 100, LOG_ALL);
77  return FALSE;
78  }
79 
80  UpdateStatus(pServInfo, 0, 1);
81 
82  LogEvent(L"\nCreating server Threads", 0, 0, LOG_FILE);
83 
84  /* Create worker threads. */
85  for (i = 0; i < NUM_SERVICES; i++)
86  {
87  swprintf(buf, L"Creating thread for %s server", Services[i].lpName);
88  LogEvent(buf, 0, 0, LOG_FILE);
89 
90  hThread[i] = CreateThread(NULL,
91  0,
93  &Services[i],
94  0,
95  &dwThreadId[i]);
96 
97  if (hThread[i] == NULL)
98  {
99  swprintf(buf, L"\nError creating %s server thread\n", Services[i].lpName);
100  LogEvent(buf, GetLastError(), 0, LOG_ALL);
101  return FALSE;
102  }
103 
104  UpdateStatus(pServInfo, 0, 1);
105  }
106 
107  LogEvent(L"Setting service status to running", 0, 0, LOG_FILE);
108  UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
109 
110  /* Wait until all threads have terminated. */
111  WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
112 
113  for (i = 0; i < NUM_SERVICES; i++)
114  {
115  if (hThread[i] != NULL)
116  CloseHandle(hThread[i]);
117  }
118 
119  LogEvent(L"Detaching Winsock2", 0, 0, LOG_FILE);
120  WSACleanup();
121 
122  return TRUE;
123 }
124 
125 VOID WINAPI
127  DWORD dwEventType,
128  LPVOID lpEventData,
129  LPVOID lpContext)
130 {
131  PSERVICEINFO pServInfo = (PSERVICEINFO)lpContext;
132 
133  switch (dwControl)
134  {
137  LogEvent(L"\nSetting the service to SERVICE_STOP_PENDING", 0, 0, LOG_FILE);
139  pServInfo->servStatus.dwWin32ExitCode = 0;
140  pServInfo->servStatus.dwWaitHint = 5000;
141  UpdateStatus(pServInfo, SERVICE_STOP_PENDING, 1);
142  break;
143 
144  case SERVICE_CONTROL_PAUSE: /* not yet implemented */
145  LogEvent(L"Setting the service to SERVICE_PAUSED", 0, 0, LOG_FILE);
147  UpdateStatus(pServInfo, SERVICE_PAUSED, 0);
148  break;
149 
151  LogEvent(L"Setting the service to SERVICE_RUNNING", 0, 0, LOG_FILE);
152  InterlockedExchange((LONG *)&bPause, FALSE);
153  UpdateStatus(pServInfo, SERVICE_RUNNING, 0);
154  break;
155 
157  SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus);
158  break;
159 
160  default:
161  if (dwControl > 127 && dwControl < 256) /* user defined */
162  LogEvent(L"User defined control code", 0, 0, LOG_FILE);
163  else
164  LogEvent(L"ERROR: Bad control code", 0, 0, LOG_FILE);
165  break;
166  }
167 }
168 
169 VOID WINAPI
171 {
172  SERVICEINFO servInfo;
173 
174  LogEvent(L"Entering ServiceMain.", 0, 0, LOG_FILE);
175 
181  servInfo.servStatus.dwCheckPoint = 0;
182  servInfo.servStatus.dwWaitHint = 2 * CS_TIMEOUT;
183 
184  LogEvent(L"Registering service control handler", 0, 0, LOG_FILE);
187  &servInfo);
188  if (!servInfo.hStatus)
189  LogEvent(L"Failed to register service", GetLastError(), 100, LOG_ALL);
190 
191  UpdateStatus(&servInfo, SERVICE_START_PENDING, 1);
192 
193  if (!CreateServers(&servInfo))
194  {
195  LogEvent(L"Error creating servers", GetLastError(), 1, LOG_ALL);
197  UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
198  return;
199  }
200 
201  LogEvent(L"Service threads shut down. Set SERVICE_STOPPED status", 0, 0, LOG_FILE);
202  UpdateStatus(&servInfo, SERVICE_STOPPED, 0);
203 
204  LogEvent(L"Leaving ServiceMain\n", 0, 0, LOG_FILE);
205 }
206 
207 
208 int _tmain (int argc, LPTSTR argv [])
209 {
211  {
213  {NULL, NULL }
214  };
215 
216  if (InitLogging())
217  {
218  if (!StartServiceCtrlDispatcherW(ServiceTable))
219  LogEvent(L"failed to start the service control dispatcher", GetLastError(), 101, LOG_ALL);
220 
221  UninitLogging();
222  }
223 
224  return 0;
225 }
volatile BOOL bShutdown
Definition: tcpsvcs.c:16
static int argc
Definition: ServiceArgs.c:12
static WCHAR ServiceName[]
Definition: tcpsvcs.c:14
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define LOG_ALL
Definition: tcpsvcs.h:17
DWORD dwCurrentState
Definition: winsvc.h:100
volatile BOOL bPause
Definition: tcpsvcs.c:17
#define MAKEWORD(a, b)
Definition: typedefs.h:247
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
VOID WINAPI ServerCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
Definition: tcpsvcs.c:126
BOOL InitLogging()
Definition: log.c:210
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define SERVICE_PAUSED
Definition: winsvc.h:27
#define CHARGEN_PORT
Definition: tcpsvcs.h:24
#define SERVICE_ACCEPT_STOP
Definition: winsvc.h:28
INT WSAAPI WSACleanup(VOID)
Definition: startup.c:60
_In_ LPCSTR lpName
Definition: winbase.h:2729
#define ERROR_SERVICE_SPECIFIC_ERROR
Definition: winerror.h:617
SERVICE_STATUS servStatus
Definition: tcpsvcs.c:21
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define SERVICE_START_PENDING
Definition: winsvc.h:22
DWORD dwServiceSpecificExitCode
Definition: winsvc.h:103
DWORD WINAPI QotdHandler(VOID *sock_)
Definition: qotd.c:135
SERVICE_STATUS_HANDLE hStatus
Definition: tcpsvcs.c:22
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
BOOL WINAPI StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW *lpServiceStartTable)
Definition: sctrl.c:1094
int32_t INT
Definition: typedefs.h:56
static char ** argv
Definition: ServiceArgs.c:11
CHAR * LPTSTR
Definition: xmlstorage.h:192
BOOL WINAPI SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus, LPSERVICE_STATUS lpServiceStatus)
Definition: sctrl.c:957
GLenum GLclampf GLint i
Definition: glfuncs.h:14
DWORD dwCheckPoint
Definition: winsvc.h:104
#define SERVICE_STOPPED
Definition: winsvc.h:21
int Check()
Definition: movefile.cpp:196
long LONG
Definition: pedump.c:60
#define SERVICE_RUNNING
Definition: winsvc.h:24
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:112
static SERVICES Services[NUM_SERVICES]
Definition: tcpsvcs.c:26
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
int _snwprintf(wchar_t *buffer, size_t count, const wchar_t *format,...)
smooth NULL
Definition: ftsmooth.c:416
static BOOL CreateServers(PSERVICEINFO pServInfo)
Definition: tcpsvcs.c:64
DWORD WINAPI DiscardHandler(VOID *sock_)
Definition: discard.c:44
#define DAYTIME_PORT
Definition: tcpsvcs.h:22
#define SERVICE_CONTROL_INTERROGATE
Definition: winsvc.h:39
#define SERVICE_WIN32_OWN_PROCESS
Definition: cmtypes.h:960
#define SERVICE_ACCEPT_PAUSE_CONTINUE
Definition: winsvc.h:29
#define ECHO_PORT
Definition: tcpsvcs.h:20
static SERVICE_STATUS_HANDLE(WINAPI *pRegisterServiceCtrlHandlerExA)(LPCSTR
DWORD WINAPI ChargenHandler(VOID *sock_)
Definition: chargen.c:96
VOID UninitLogging()
Definition: log.c:263
#define SERVICE_ACCEPT_SHUTDOWN
Definition: winsvc.h:30
#define NUM_SERVICES
Definition: tcpsvcs.h:26
unsigned int BOOL
Definition: ntddk_ex.h:94
struct _ServiceInfo * PSERVICEINFO
DWORD(WINAPI * LPHANDLER_FUNCTION_EX)(DWORD, DWORD, LPVOID, LPVOID)
Definition: winsvc.h:191
DWORD dwWaitHint
Definition: winsvc.h:105
#define swprintf(buf, format,...)
Definition: sprintf.c:56
DWORD dwWin32ExitCode
Definition: winsvc.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD dwServiceType
Definition: winsvc.h:99
#define QOTD_PORT
Definition: tcpsvcs.h:23
#define SERVICE_CONTROL_PAUSE
Definition: winsvc.h:37
DWORD dwThreadId
Definition: fdebug.c:31
static const WCHAR L[]
Definition: oid.c:1087
SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName, LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext)
Definition: sctrl.c:773
#define WINAPI
Definition: msvc.h:20
#define InterlockedExchange
Definition: armddk.h:54
static SERVICE_TABLE_ENTRYW ServiceTable[2]
Definition: eventlog.c:24
#define DISCARD_PORT
Definition: tcpsvcs.h:21
DWORD WINAPI EchoHandler(VOID *sock_)
Definition: echo.c:69
DWORD dwControlsAccepted
Definition: winsvc.h:101
struct _ServiceInfo SERVICEINFO
VOID LogEvent(LPCWSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags)
Definition: log.c:196
static VOID UpdateStatus(PSERVICEINFO pServInfo, DWORD NewStatus, DWORD Check)
Definition: tcpsvcs.c:37
#define SERVICE_CONTROL_CONTINUE
Definition: winsvc.h:38
int _tmain(int argc, LPTSTR argv [])
Definition: tcpsvcs.c:208
HANDLE hThread
Definition: wizard.c:27
DWORD WINAPI DaytimeHandler(VOID *Sock_)
Definition: daytime.c:29
#define SERVICE_CONTROL_STOP
Definition: winsvc.h:36
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define INFINITE
Definition: serial.h:102
VOID WINAPI ServiceMain(DWORD argc, LPWSTR argv[])
Definition: tcpsvcs.c:170
#define SERVICE_STOP_PENDING
Definition: winsvc.h:23
#define CS_TIMEOUT
Definition: tcpsvcs.h:27
DWORD WINAPI StartServer(LPVOID lpParam)
Definition: skelserver.c:165
#define SERVICE_CONTROL_SHUTDOWN
Definition: winsvc.h:40