Add tcpsvcs to the services directory.
[reactos.git] / reactos / services / tcpsvcs / tcpsvcs.c
diff --git a/reactos/services/tcpsvcs/tcpsvcs.c b/reactos/services/tcpsvcs/tcpsvcs.c
new file mode 100644 (file)
index 0000000..014fcde
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ *  ReactOS Services
+ *  Copyright (C) 2005 ReactOS Team
+ *
+ * LICENCE:     GPL - See COPYING in the top level directory
+ * PROJECT:     ReactOS simple TCP/IP services
+ * FILE:        apps/utils/net/tcpsvcs/tcpsvcs.c
+ * PURPOSE:     Provide CharGen, Daytime, Discard, Echo, and Qotd services
+ * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
+ * REVISIONS:
+ *   GM 04/10/05 Created
+ *
+ */
+/*
+ * TODO:
+ * - Start tcpsvcs as a service.
+ * - write debugging function and print all dbg info via that.
+ *
+ */
+#include <stdio.h>
+#include <winsock2.h>
+#include <tchar.h>
+#include "tcpsvcs.h"
+
+#if 0
+/*
+ * globals
+ */
+static SERVICE_STATUS hServStatus;
+static SERVICE_STATUS_HANDLE hSStat;
+FILE *hLogFile;
+BOOL bLogEvents = TRUE;
+BOOL ShutDown, PauseFlag;
+LPCTSTR LogFileName = "tcpsvcs_log.log";
+
+static SERVICE_TABLE_ENTRY
+ServiceTable[2] =
+{
+    {_T("tcpsvcs"), ServiceMain},
+    {NULL, NULL}
+};
+#endif
+
+static SERVICES
+Services[NUM_SERVICES] =
+{
+    {ECHO_PORT, _T("Echo"), EchoHandler},
+    {DISCARD_PORT, _T("Discard"), DiscardHandler},
+    {DAYTIME_PORT, _T("Daytime"), DaytimeHandler},
+    {QOTD_PORT, _T("QOTD"), QotdHandler},
+    {CHARGEN_PORT, _T("Chargen"), ChargenHandler}
+};
+
+
+int main(void)
+{
+    DWORD dwThreadId[NUM_SERVICES];
+    HANDLE hThread[NUM_SERVICES];
+    WSADATA wsaData;
+    DWORD RetVal;
+    INT i;
+    
+    if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
+    {
+        _tprintf(_T("WSAStartup() failed : %lu\n"), RetVal);
+        return -1;
+    }
+
+    /* Create MAX_THREADS worker threads. */
+    for( i=0; i<NUM_SERVICES; i++ )
+    {
+        _tprintf(_T("Starting %s server....\n"), Services[i].Name);
+
+        hThread[i] = CreateThread(
+            NULL,              // default security attributes
+            0,                 // use default stack size
+            StartServer,       // thread function
+            &Services[i],     // argument to thread function
+            0,                 // use default creation flags
+            &dwThreadId[i]);   // returns the thread identifier
+
+        /* Check the return value for success. */
+        if (hThread[i] == NULL)
+        {
+            _tprintf(_T("Failed to start %s server....\n"), Services[i].Name);
+            //ExitProcess(i);
+        }
+    }
+
+    /* Wait until all threads have terminated. */
+    WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
+
+    /* Close all thread handles upon completion. */
+    for(i=0; i<NUM_SERVICES; i++)
+    {
+        CloseHandle(hThread[i]);
+    }
+    return 0;
+}
+
+
+
+/* code to run tcpsvcs as a service through services.msc */
+#if 0
+int
+main(int argc, char *argv[])
+{
+    //DPRINT("tcpsvcs: main() started. See tcpsvcs_log.txt for info\n");
+
+    if (!StartServiceCtrlDispatcher(ServiceTable))
+        _tprintf(_T("failed to start the service control dispatcher\n"));
+
+    //DPRINT("tcpsvcs: main() done\n");
+
+    return 0;
+}
+
+
+static VOID WINAPI
+ServiceMain(DWORD argc, LPTSTR argv[])
+{
+    DWORD i;
+
+    hLogFile = fopen(LogFileName, _T("w+"));
+    if (hLogFile == NULL)
+        return;
+        
+    LogEvent(_T("Entering ServiceMain"), 0, FALSE);
+
+    hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+    hServStatus.dwCurrentState = SERVICE_START_PENDING;
+    hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
+        SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE;
+    hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+    hServStatus.dwServiceSpecificExitCode = 0;
+    hServStatus.dwCheckPoint = 0;
+    hServStatus.dwWaitHint = 2*CS_TIMEOUT;
+    
+    hSStat = RegisterServiceCtrlHandler("tcpsvcs", ServerCtrlHandler);
+    if (hSStat == 0)
+        LogEvent(_T("Failed to register service\n"), 100, TRUE);
+
+       LogEvent(_T("Control handler registered successfully"), 0, FALSE);
+       SetServiceStatus (hSStat, &hServStatus);
+       LogEvent(_T("Service status set to SERVICE_START_PENDING"), 0, FALSE);
+
+    if (CreateServers() != 0)
+    {
+        hServStatus.dwCurrentState = SERVICE_STOPPED;
+        hServStatus.dwServiceSpecificExitCode = 1;
+        SetServiceStatus(hSStat, &hServStatus);
+        return;
+    }
+    
+       LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, FALSE);
+       /*  We will only return here when the ServiceSpecific function
+               completes, indicating system shutdown. */
+       UpdateStatus (SERVICE_STOPPED, 0);
+       LogEvent(_T("Service status set to SERVICE_STOPPED"), 0, FALSE);
+       fclose(hLogFile);  /*  Clean up everything, in general */
+       return;
+
+}
+
+VOID WINAPI
+ServerCtrlHandler(DWORD Control)
+{
+    switch (Control)
+    {
+        case SERVICE_CONTROL_SHUTDOWN: /* fall through */
+        case SERVICE_CONTROL_STOP:
+            ShutDown = TRUE;
+            UpdateStatus(SERVICE_STOP_PENDING, -1);
+            break;
+        case SERVICE_CONTROL_PAUSE:
+            PauseFlag = TRUE;
+            break;
+        case SERVICE_CONTROL_CONTINUE:
+            PauseFlag = FALSE;
+            break;
+        case SERVICE_CONTROL_INTERROGATE:
+            break;
+        default:
+            if (Control > 127 && Control < 256) /* user defined */
+            break;
+    }
+    UpdateStatus(-1, -1); /* increment checkpoint */
+    return;
+}
+
+
+void UpdateStatus (int NewStatus, int Check)
+/*  Set a new service status and checkpoint (either specific value or increment) */
+{
+       if (Check < 0 ) hServStatus.dwCheckPoint++;
+       else                    hServStatus.dwCheckPoint = Check;
+       if (NewStatus >= 0) hServStatus.dwCurrentState = NewStatus;
+       if (!SetServiceStatus (hSStat, &hServStatus))
+               LogEvent (_T("Cannot set service status"), 101, TRUE);
+       return;
+}
+
+INT
+CreateServers()
+{
+    DWORD dwThreadId[NUM_SERVICES];
+    HANDLE hThread[NUM_SERVICES];
+    INT i;
+    
+    UpdateStatus(-1, -1); /* increment checkpoint */
+
+    /* Create MAX_THREADS worker threads. */
+    for( i=0; i<NUM_SERVICES; i++ )
+    {
+        _tprintf(_T("Starting %s server....\n"), Services[i].Name);
+
+        hThread[i] = CreateThread(
+            NULL,              // default security attributes
+            0,                 // use default stack size
+            StartServer,       // thread function
+            &Services[i],     // argument to thread function
+            0,                 // use default creation flags
+            &dwThreadId[i]);   // returns the thread identifier
+
+        /* Check the return value for success. */
+        if (hThread[i] == NULL)
+        {
+            _tprintf(_T("Failed to start %s server....\n"), Services[i].Name);
+            ExitProcess(i);
+        }
+    }
+
+    /* Wait until all threads have terminated. */
+    WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE);
+
+    /* Close all thread handles upon completion. */
+    for(i=0; i<NUM_SERVICES; i++)
+    {
+        CloseHandle(hThread[i]);
+    }
+    return 0;
+}
+
+
+/*     LogEvent is similar to the ReportError function used elsewhere
+       For a service, however, we ReportEvent rather than write to standard
+       error. Eventually, this function should go into the utility
+       library.  */
+VOID
+LogEvent (LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg)
+{
+       DWORD eMsgLen, ErrNum = GetLastError ();
+       LPTSTR lpvSysMsg;
+       TCHAR MessageBuffer[512];
+
+       if (PrintErrorMsg) {
+               eMsgLen = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                       FORMAT_MESSAGE_FROM_SYSTEM, NULL,
+                       ErrNum, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPTSTR)&lpvSysMsg, 0, NULL);
+
+               _stprintf (MessageBuffer, _T("\n%s %s ErrNum = %d. ExitCode = %d."),
+                       UserMessage, lpvSysMsg, ErrNum, ExitCode);
+               HeapFree (GetProcessHeap (), 0, lpvSysMsg);
+       } else {
+               _stprintf (MessageBuffer, _T("\n%s ExitCode = %d."),
+                       UserMessage, ExitCode);
+       }
+
+       fputs (MessageBuffer, hLogFile);
+
+       if (ExitCode > 0)
+               ExitProcess (ExitCode);
+       else
+               return;
+}
+
+#endif