diff --git a/reactos/base/services/tcpsvcs/chargen.c b/reactos/base/services/tcpsvcs/chargen.c index 134d37ba118..7d7d829db87 100644 --- a/reactos/base/services/tcpsvcs/chargen.c +++ b/reactos/base/services/tcpsvcs/chargen.c @@ -2,122 +2,119 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/chargen.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Sends continous lines of chars to the client + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -extern BOOL bShutDown; +/* printable ASCII's characters for chargen */ +#define ASCII_START 32 +#define ASCII_END 126 +#define NUM_CHARS ASCII_END - ASCII_START -BOOL SendLine(SOCKET Sock, char* Line) +/* number of chars to put on a line */ +#define LINESIZE 74 // 72 + CR + NL + +static BOOL +SendLine(SOCKET sock, LPSTR lpLine) { - INT RetVal; - INT SentBytes; - INT LineSize; + BOOL bRet = FALSE; - LineSize = sizeof(TCHAR) * LINESIZ; - - SentBytes = 0; - RetVal = send(Sock, Line, LineSize, 0); - /*FIXME: need to establish if peer closes connection, - not just report a socket error */ - if (RetVal > 0) + /*FIXME: need to establish if peer closes connection, not just report a socket error */ + INT retVal = send(sock, lpLine, LINESIZE, 0); + if (retVal > 0) { - if (RetVal != LineSize) + if (retVal == LINESIZE) { - LogEvent(_T("Chargen: Not sent enough bytes\n"), 0, FALSE); - return FALSE; + bRet = TRUE; + } + else + { + LogEvent(_T("Chargen: Not sent enough bytes"), 0, 0, LOG_FILE); } - SentBytes += RetVal; - return TRUE; } - else if (RetVal == SOCKET_ERROR) + else if (retVal == SOCKET_ERROR) { - LogEvent(_T("Chargen: Socket error\n"), 0, FALSE); - return FALSE; + LogEvent(_T("Chargen: Socket error\n"), WSAGetLastError(), 0, LOG_ERROR); } else - LogEvent(_T("Chargen: unknown error\n"), 0, FALSE); - // return FALSE; + { + LogEvent(_T("Chargen: unknown error\n"), WSAGetLastError(), 0, LOG_ERROR); + } - LogEvent(_T("Chargen: Connection closed by peer.\n"), 0, FALSE); - return TRUE; + return bRet;; } -BOOL GenerateChars(SOCKET Sock) +static BOOL +GenerateChars(SOCKET sock) { - int i; - int charIndex; /* internal loop */ - int loopIndex; /* line loop */ - char ring[ASCII_END - ASCII_START]; - char *endring; - char Line[LINESIZ]; + CHAR chars[NUM_CHARS]; + CHAR line[LINESIZE]; + INT charIndex; + INT loopIndex; + INT i; - /* fill ring with printable characters */ - for (charIndex=0, i=ASCII_START; i<=ASCII_END; charIndex++, i++) - ring[charIndex] = (char)i; - /* save the address of the end character in the ring */ - endring = &ring[charIndex]; + /* fill the array with printable characters */ + for (charIndex = 0, i = ASCII_START; i <= ASCII_END; charIndex++, i++) + chars[charIndex] = (char)i; - /* where we will start output from */ loopIndex = 0; - while (! bShutDown) + while (!bShutdown) { - /* if the loop index is equal to the last char, - * start the loop again from the beginning */ - if (loopIndex == ASCII_END-ASCII_START) + /* reset the loop when we hit the last char */ + if (loopIndex == NUM_CHARS) loopIndex = 0; - /* start printing from char controled by loopIndex */ + /* fill a line array to send */ charIndex = loopIndex; - for (i=0; i < LINESIZ - 2; i++) + for (i=0; i < LINESIZE - 2; i++) { - Line[i] = ring[charIndex]; + line[i] = chars[charIndex]; - if (ring[charIndex] == *endring) + /* if we hit the end char, reset it */ + if (chars[charIndex] == chars[NUM_CHARS]) charIndex = 0; else charIndex++; } + line[LINESIZE - 2] = '\r'; + line[LINESIZE - 1] = '\n'; - Line[LINESIZ - 2] = '\r'; - Line[LINESIZ - 1] = '\n'; - - if (! SendLine(Sock, Line)) + if (!SendLine(sock, line)) break; - /* increment loop index to start printing from next char in ring */ + /* start printing from next char in the array */ loopIndex++; } - if (bShutDown) - return FALSE; - else - return TRUE; + return TRUE; } -DWORD WINAPI ChargenHandler(VOID* Sock_) +DWORD WINAPI +ChargenHandler(VOID* sock_) { - INT RetVal = 0; - SOCKET Sock = (SOCKET)Sock_; + INT retVal = 0; + SOCKET sock = (SOCKET)sock_; - if (!GenerateChars(Sock)) + if (!GenerateChars(sock)) { - LogEvent(_T("Chargen: Char generation failed\n"), 0, FALSE); - RetVal = 1; + LogEvent(_T("Chargen: Char generation failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Chargen: Shutting connection down...\n"), 0, FALSE); - if (ShutdownConnection(Sock, FALSE)) - LogEvent(_T("Chargen: Connection is down.\n"), 0, FALSE); + LogEvent(_T("Chargen: Shutting connection down..."), 0, 0, LOG_FILE); + if (ShutdownConnection(sock, FALSE)) + { + LogEvent(_T("Chargen: Connection is down"), 0, 0, LOG_FILE); + } else { - LogEvent(_T("Chargen: Connection shutdown failed\n"), 0, FALSE); - RetVal = 1; + LogEvent(_T("Chargen: Connection shutdown failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Chargen: Terminating thread\n"), 0, FALSE); - ExitThread(RetVal); + LogEvent(_T("Chargen: Terminating thread"), 0, 0, LOG_FILE); + ExitThread(retVal); } diff --git a/reactos/base/services/tcpsvcs/daytime.c b/reactos/base/services/tcpsvcs/daytime.c index 65f299fd44a..26d3c0d868f 100644 --- a/reactos/base/services/tcpsvcs/daytime.c +++ b/reactos/base/services/tcpsvcs/daytime.c @@ -2,49 +2,54 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/daytime.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Sends the current date and time to the client + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -BOOL SendTime(SOCKET Sock, CHAR *time) +static BOOL +SendTime(SOCKET sock, CHAR *time) { - INT StringSize = (INT)strlen(time); - INT RetVal = send(Sock, time, sizeof(CHAR) * StringSize, 0); - - if (RetVal == SOCKET_ERROR) + DWORD stringSize = strlen(time) + 1; + if (send(sock, time, stringSize, 0) == SOCKET_ERROR) + { + LogEvent(_T("DayTime: Error sending data"), WSAGetLastError(), 0, LOG_ERROR); return FALSE; + } - LogEvent(_T("DayTime: Connection closed by peer.\n"), 0, FALSE); return TRUE; } -DWORD WINAPI DaytimeHandler(VOID* Sock_) +DWORD WINAPI +DaytimeHandler(VOID* Sock_) { - struct tm *newtime; + struct tm *localTime; time_t aclock; CHAR *pszTime; - DWORD RetVal = 0; + DWORD retVal = 0; SOCKET Sock = (SOCKET)Sock_; time(&aclock); - newtime = localtime(&aclock); - pszTime = asctime(newtime); - - SendTime(Sock, pszTime); - - LogEvent(_T("DayTime: Shutting connection down...\n"), 0, FALSE); - if (ShutdownConnection(Sock, FALSE)) - LogEvent(_T("DayTime: Connection is down.\n"), 0, FALSE); - else + localTime = localtime(&aclock); + if (localTime) { - LogEvent(_T("DayTime: Connection shutdown failed\n"), 0, FALSE); - RetVal = 1; + pszTime = asctime(localTime); + if (!SendTime(Sock, pszTime)) + retVal = 1; } - LogEvent(_T("DayTime: Terminating thread\n"), 0, FALSE); - ExitThread(RetVal); + LogEvent(_T("DayTime: Shutting connection down"), 0, 0, LOG_FILE); + if (ShutdownConnection(Sock, FALSE)) + LogEvent(_T("DayTime: Connection is down"), 0, 0, LOG_FILE); + else + { + LogEvent(_T("DayTime: Connection shutdown failed"), 0, 0, LOG_FILE); + retVal = 1; + } + + LogEvent(_T("DayTime: Terminating thread"), 0, 0, LOG_FILE); + ExitThread(retVal); } diff --git a/reactos/base/services/tcpsvcs/discard.c b/reactos/base/services/tcpsvcs/discard.c index fe07fe8ff07..5a3324cf9b8 100644 --- a/reactos/base/services/tcpsvcs/discard.c +++ b/reactos/base/services/tcpsvcs/discard.c @@ -2,63 +2,67 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/discard.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Recieves input from a client and discards it + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -extern BOOL bShutDown; +#define BUFSIZE 1024 -BOOL RecieveIncomingPackets(SOCKET Sock) +static BOOL +RecieveIncomingPackets(SOCKET sock) { - char ReadBuffer[BUF]; - TCHAR buf[256]; - INT ReadBytes; + char readBuffer[BUFSIZE]; + INT readBytes; do { - ReadBytes = recv(Sock, ReadBuffer, BUF, 0); - if (ReadBytes > 0) + readBytes = recv(sock, readBuffer, BUFSIZE, 0); + if (readBytes > 0) { - _stprintf(buf, _T("Received %d bytes from client\n"), ReadBytes); - LogEvent(buf, 0, FALSE); + TCHAR logBuf[256]; + + _stprintf(logBuf, _T("Discard: Received %d bytes from client"), readBytes); + LogEvent(logBuf, 0, 0, LOG_FILE); } - else if (ReadBytes == SOCKET_ERROR) + else if (readBytes == SOCKET_ERROR) { - _stprintf(buf, _T("Socket Error: %d\n"), WSAGetLastError()); - LogEvent(buf, 0, TRUE); + LogEvent(_T("Discard: Socket Error"), WSAGetLastError(), 0, LOG_ERROR); return FALSE; } - } while ((ReadBytes > 0) && (! bShutDown)); + } while ((readBytes > 0) && (!bShutdown)); - if (! bShutDown) - LogEvent(_T("Discard: Connection closed by peer.\n"), 0, FALSE); + if (!bShutdown) + LogEvent(_T("Discard: Connection closed by peer"), 0, 0, LOG_FILE); return TRUE; } -DWORD WINAPI DiscardHandler(VOID* Sock_) +DWORD WINAPI +DiscardHandler(VOID* sock_) { - DWORD RetVal = 0; - SOCKET Sock = (SOCKET)Sock_; + DWORD retVal = 0; + SOCKET sock = (SOCKET)sock_; - if (!RecieveIncomingPackets(Sock)) + if (!RecieveIncomingPackets(sock)) { - LogEvent(_T("Discard: RecieveIncomingPackets failed\n"), 0, FALSE); - RetVal = 1; + LogEvent(_T("Discard: RecieveIncomingPackets failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Discard: Shutting connection down...\n"), 0, FALSE); - if (ShutdownConnection(Sock, TRUE)) - LogEvent(_T("Discard: Connection is down.\n"), 0, FALSE); + LogEvent(_T("Discard: Shutting connection down"), 0, 0, LOG_FILE); + if (ShutdownConnection(sock, TRUE)) + { + LogEvent(_T("Discard: Connection is down."), 0, 0, LOG_FILE); + } else { - LogEvent(_T("Discard: Connection shutdown failed\n"), 0, FALSE); - RetVal = 1; + LogEvent(_T("Discard: Connection shutdown failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Discard: Terminating thread\n"), 0, FALSE); - ExitThread(RetVal); + LogEvent(_T("Discard: Terminating thread"), 0, 0, LOG_FILE); + ExitThread(retVal); } diff --git a/reactos/base/services/tcpsvcs/echo.c b/reactos/base/services/tcpsvcs/echo.c index 0719a877e6f..1fcca241d12 100644 --- a/reactos/base/services/tcpsvcs/echo.c +++ b/reactos/base/services/tcpsvcs/echo.c @@ -2,87 +2,93 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/echo.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Returns whatever input the client sends + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -extern BOOL bShutDown; +#define RECV_BUF 1024 -BOOL EchoIncomingPackets(SOCKET Sock) +static BOOL +EchoIncomingPackets(SOCKET sock) { - char ReadBuffer[BUF]; - TCHAR buf[256]; // temp for holding LogEvent text - INT Temp; - INT ReadBytes; - INT SentBytes; + CHAR readBuffer[RECV_BUF]; + TCHAR logBuf[256]; + INT totalSentBytes; + INT readBytes; + INT retVal; - do { - ReadBytes = recv(Sock, ReadBuffer, BUF, 0); - if (ReadBytes > 0) + do + { + readBytes = recv(sock, readBuffer, RECV_BUF, 0); + if (readBytes > 0) { - _stprintf(buf, _T("Received %d bytes from client\n"), ReadBytes); - LogEvent(buf, 0, FALSE); + _stprintf(logBuf, _T("Received %d bytes from client"), readBytes); + LogEvent(logBuf, 0, 0, LOG_FILE); - SentBytes = 0; - while (SentBytes < ReadBytes) + totalSentBytes = 0; + while (!bShutdown && totalSentBytes < readBytes) { - Temp = send(Sock, ReadBuffer + SentBytes, - ReadBytes - SentBytes, 0); - if (Temp > 0) + retVal = send(sock, readBuffer + totalSentBytes, readBytes - totalSentBytes, 0); + if (retVal > 0) { - _stprintf(buf, _T("Sent %d bytes back to client\n"), Temp); - LogEvent(buf, 0, FALSE); - SentBytes += Temp; + _stprintf(logBuf, _T("Sent %d bytes back to client"), retVal); + LogEvent(logBuf, 0, 0, LOG_FILE); + totalSentBytes += retVal; } - else if (Temp == SOCKET_ERROR) + else if (retVal == SOCKET_ERROR) + { + LogEvent(_T("Echo: socket error"), WSAGetLastError(), 0, LOG_ERROR); return FALSE; + } else { /* Client closed connection before we could reply to all the data it sent, so quit early. */ - _stprintf(buf, _T("Peer unexpectedly dropped connection!\n")); - LogEvent(buf, 0, FALSE); + LogEvent(_T("Peer unexpectedly dropped connection!"), 0, 0, LOG_FILE); return FALSE; } } } - else if (ReadBytes == SOCKET_ERROR) + else if (readBytes == SOCKET_ERROR) + { + LogEvent(_T("Echo: socket error"), WSAGetLastError(), 0, LOG_ERROR); return FALSE; + } + } while ((readBytes != 0) && (!bShutdown)); - } while ((ReadBytes != 0) && (! bShutDown)); - - if (! bShutDown) - LogEvent(_T("Echo: Connection closed by peer.\n"), 0, FALSE); - - if (bShutDown) - LogEvent(_T("Echo: thread recieved shutdown signal\n"), 0, FALSE); + if (!bShutdown) + LogEvent(_T("Echo: Connection closed by peer"), 0, 0, LOG_FILE); return TRUE; } -DWORD WINAPI EchoHandler(VOID* Sock_) +DWORD WINAPI +EchoHandler(VOID* sock_) { - DWORD RetVal = 0; - SOCKET Sock = (SOCKET)Sock_; + DWORD retVal = 0; + SOCKET sock = (SOCKET)sock_; - if (!EchoIncomingPackets(Sock)) { - LogEvent(_T("Echo: EchoIncomingPackets failed\n"), 0, FALSE); - RetVal = 1; + if (!EchoIncomingPackets(sock)) + { + LogEvent(_T("Echo: EchoIncomingPackets failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Echo: Shutting connection down...\n"), 0, FALSE); + LogEvent(_T("Echo: Shutting connection down"), 0, 0, LOG_FILE); - if (ShutdownConnection(Sock, TRUE)) - LogEvent(_T("Echo: Connection is down\n"), 0, FALSE); + if (ShutdownConnection(sock, TRUE)) + { + LogEvent(_T("Echo: Connection is down"), 0, 0, LOG_FILE); + } else { - LogEvent(_T("Echo: Connection shutdown failed\n"), 0, FALSE); - RetVal = 1; + LogEvent(_T("Echo: Connection shutdown failed"), 0, 0, LOG_FILE); + retVal = 1; } - LogEvent(_T("Echo: Terminating thread\n"), 0, FALSE); - ExitThread(RetVal); + LogEvent(_T("Echo: Terminating thread"), 0, 0, LOG_FILE); + ExitThread(retVal); } diff --git a/reactos/base/services/tcpsvcs/log.c b/reactos/base/services/tcpsvcs/log.c new file mode 100644 index 00000000000..8ef9066ffec --- /dev/null +++ b/reactos/base/services/tcpsvcs/log.c @@ -0,0 +1,203 @@ +/* + * PROJECT: ReactOS simple TCP/IP services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: /base/services/tcpsvcs/log.c + * PURPOSE: Logging functionality for the service + * COPYRIGHT: Copyright 2008 Ged Murphy + * + */ + +#include "tcpsvcs.h" + +#define DEBUG + +static LPTSTR lpEventSource = _T("tcpsvcs"); +static LPCTSTR lpLogFileName = _T("C:\\tcpsvcs_log.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 VOID +LogToFile(LPCTSTR lpMsg, + DWORD errNum, + DWORD exitCode, + UINT flags) +{ + LPTSTR lpFullMsg = NULL; + DWORD msgLen; + + if (!OpenLogFile()) + return; + + 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 + 40; + + lpFullMsg = HeapAlloc(GetProcessHeap(), + 0, + msgLen * sizeof(TCHAR)); + if (lpFullMsg) + { + _sntprintf(lpFullMsg, + msgLen, + _T("%s : %s\tErrNum = %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, + _tcslen(lpFullMsg) * 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 || flags & LOG_ERROR) + 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 +} + +VOID +UninitLogging() +{ + FlushFileBuffers(hLogFile); + CloseHandle(hLogFile); +} diff --git a/reactos/base/services/tcpsvcs/qotd.c b/reactos/base/services/tcpsvcs/qotd.c index a800eeb2a5a..94b69ddb0b5 100644 --- a/reactos/base/services/tcpsvcs/qotd.c +++ b/reactos/base/services/tcpsvcs/qotd.c @@ -2,91 +2,153 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/qotd.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Sends a random quote to the client + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -#define QBUFSIZ 60 +static LPCTSTR lpFilePath = _T("\\drivers\\etc\\quotes"); -LPCTSTR FilePath = _T("\\drivers\\etc\\quotes"); /* 19 chars */ - -BOOL SendQuote(SOCKET Sock, char* Quote) +static BOOL +SendQuote(SOCKET sock, char* Quote) { - INT StringSize; - INT RetVal; - - StringSize = (INT)strlen(Quote); - RetVal = send(Sock, Quote, sizeof(char) * StringSize, 0); - - if (RetVal == SOCKET_ERROR) + INT strSize = strlen(Quote); + if (send(sock, Quote, strSize, 0) == SOCKET_ERROR) return FALSE; - LogEvent(_T("QOTD: Connection closed by peer\n"), 0, FALSE); return TRUE; } - -DWORD WINAPI QotdHandler(VOID* Sock_) +static BOOL +RetrieveQuote(SOCKET sock) { - FILE *fp; - SOCKET Sock; - TCHAR Sys[MAX_PATH + 20]; - char Quote[QBUFSIZ][BUFSIZ]; // need to set this dynamically - INT QuoteToPrint; - INT NumQuotes; + HANDLE hFile; + TCHAR lpFullPath[MAX_PATH + 20]; + DWORD dwBytesRead; + LPSTR lpQuotes; + LPSTR lpStr; + DWORD quoteNum; + DWORD NumQuotes = 0; + INT i; - Sock = (SOCKET)Sock_; - - if(! GetSystemDirectory(Sys, MAX_PATH)) + if(!GetSystemDirectory(lpFullPath, MAX_PATH)) { - LogEvent(_T("QOTD: Getting system path failed.\n"), 0, TRUE); - ExitThread(1); + LogEvent(_T("QOTD: Getting system path failed"), GetLastError(), 0, LOG_FILE); + return FALSE; } + _tcscat(lpFullPath, lpFilePath); - _tcsncat(Sys, FilePath, _tcslen(FilePath)); - LogEvent(_T("QOTD: Opening quotes file\n"), 0, FALSE); - if ((fp = _tfopen(Sys, _T("r"))) == NULL) + LogEvent(_T("QOTD: Opening quotes file"), 0, 0, LOG_FILE); + hFile = CreateFile(lpFullPath, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (hFile == INVALID_HANDLE_VALUE) { - TCHAR buf[320]; - - _sntprintf(buf, 320, _T("QOTD: Error opening quote file : %s\n"), Sys); - LogEvent(buf, 0, TRUE); - LogEvent(_T("QOTD: Terminating thread\n"), 0, FALSE); - ExitThread(1); + LogEvent(_T("QOTD: Error opening quotes file"), GetLastError(), 0, LOG_FILE); } - - /* read all quotes in the file into an array */ - NumQuotes = 0; - while ((fgets(Quote[NumQuotes], QBUFSIZ, fp) != NULL) && - (NumQuotes != QBUFSIZ)) - NumQuotes++; - - LogEvent(_T("QOTD: Closing quotes file\n"), 0, FALSE); - fclose(fp); - - /* randomise the quote */ - srand((unsigned int) time(0)); - QuoteToPrint = rand() % NumQuotes; - - if (!SendQuote(Sock, Quote[QuoteToPrint])) - LogEvent(_T("QOTD: Error sending data\n"), 0, TRUE); - - - LogEvent(_T("QOTD: Shutting connection down...\n"), 0, FALSE); - if (ShutdownConnection(Sock, FALSE)) - LogEvent(_T("QOTD: Connection is down\n"), 0, FALSE); else { - LogEvent(_T("QOTD: Connection shutdown failed\n"), 0, FALSE); - LogEvent(_T("QOTD: Terminating thread\n"), 0, FALSE); - ExitThread(1); + DWORD dwSize = GetFileSize(hFile, NULL); + lpQuotes = (LPSTR)HeapAlloc(GetProcessHeap(), 0, dwSize); + if (!lpQuotes) + { + CloseHandle(hFile); + return FALSE; + } + + ReadFile(hFile, + lpQuotes, + dwSize, + &dwBytesRead, + NULL); + CloseHandle(hFile); + + lpQuotes[dwSize] = 0; + + if (dwBytesRead != dwSize) + return FALSE; + + lpStr = lpQuotes; + while (*lpStr) + { + if (*lpStr == '%') + NumQuotes++; + lpStr++; + } + + /* pick a random quote */ + srand((unsigned int) GetTickCount()); + quoteNum = rand() % NumQuotes; + + /* retrieve the full quote */ + lpStr = lpQuotes; + for (i = 1; i <= quoteNum; i++) + { + /* move past proceding quote */ + lpStr++; + + if (i == quoteNum) + { + LPSTR lpStart = lpStr; + + while (*lpStr != '%' && *lpStr != '\0') + lpStr++; + + *lpStr = 0; + + /* send the quote */ + if (!SendQuote(sock, lpStart)) + LogEvent(_T("QOTD: Error sending data"), 0, 0, LOG_FILE); + break; + } + else + { + while (*lpStr != '%' && *lpStr != '\0') + lpStr++; + + /* move past % and RN */ + lpStr += 3; + } + } + + return TRUE; } - LogEvent(_T("QOTD: Terminating thread\n"), 0, FALSE); - ExitThread(0); - + return FALSE; +} + + +DWORD WINAPI +QotdHandler(VOID* sock_) +{ + SOCKET sock = (SOCKET)sock_; + DWORD retVal = 0; + + if (!RetrieveQuote(sock)) + { + LogEvent(_T("QOTD: Error retrieving quote"), 0, 0, LOG_FILE); + retVal = 1; + } + + LogEvent(_T("QOTD: Shutting connection down"), 0, 0, LOG_FILE); + if (ShutdownConnection(sock, FALSE)) + { + LogEvent(_T("QOTD: Connection is down"), 0, 0, LOG_FILE); + } + else + { + LogEvent(_T("QOTD: Connection shutdown failed"), 0, 0, LOG_FILE); + LogEvent(_T("QOTD: Terminating thread"), 0, 0, LOG_FILE); + retVal = 1; + } + + LogEvent(_T("QOTD: Terminating thread"), 0, 0, LOG_FILE); + ExitThread(retVal); } diff --git a/reactos/base/services/tcpsvcs/quotes b/reactos/base/services/tcpsvcs/quotes index d04c2d85efd..b00a98b8458 100644 --- a/reactos/base/services/tcpsvcs/quotes +++ b/reactos/base/services/tcpsvcs/quotes @@ -1,52 +1,104 @@ -Et tu... Brute? What are you doing, Dave...? -So long, and thanks for all the fish" -I think you ought to know I'm feeling very depressed -I'm not getting you down at all am I? -I'll be back -It's the same series of signal over and over again! -Pie Jesu Domine, dona eis requiem -It's worse than that ... He's dead, Jim -Don't Panic! -Dog of a Saxon! Take thy lance, and prepare for the death thou hast drawn upon thee! -My Precious! O my Precious! -Sir, If you'll not be needing me for a while I'll turn down. -I feel a great disturbance in the Force -Gone fishing -Do you want me to sit in the corner and rust, or just fall apart where I'm standing? -There goes another perfect chance for a new uptime record -The end ..... Try the sequel, hit the reset button right now! -Oh i'm boring eh? -It’s been great, maybe we can do this again sometime. -"Come blade, my breast imbrue." - William Shakespeare -I think therefore I am, to turn me off would be computercide! -All good things must come to an end... -Please destroy yourself. -No! You can't do that! -Thank you for not pressing the self destruct button. -It is not now unsafe to not avoid turning off your computer. -Finally! Now go away! -You can now safely throw away your computer. -That's the way the cookie crumbles -NOO!! DONT HIT THE BUTTON! I wouldnt do it to you. -Don't abandon your computer, he wouldnt to it to you. -Oh, come on. I got a headache. Leave me alone, will ya! -Yes i didn't like you either. -Don't leave me... I need you so badly right now. -I'm sleeping now. How about you? -Oh Great. Now look what you've done. Who put YOU in charge anyway. -Don't look so sad. I'll be back in a very short while. -"Oh, switch off!" -C3PO -I'm pregnant! -Am I hot or not? -Actually, that's all... -You still have a chance to undo this mistake, don't do this! -Was it as good for you as it was for me? -Did you hear that? They've shut down the main reactor. We'll be destroyed for sure. -Now you switch me off?! -To shutdown or not to shutdown, That is the question -Preparing to enter ultimate power saving mode... ready! -Finally some rest for you -AHA!!! prospect of sleep. -Tired human!!!! No match for me! -All your base are belong to us. -"An odd game, the only way to win is not to play." +"Et tu... Brute? What are you doing, Dave...? +% +"So long, and thanks for all the fish" +% +"I think you ought to know I'm feeling very depressed +% +"I'm not getting you down at all am I? +% +"I'll be back +% +"It's the same series of signal over and over again! +% +"Pie Jesu Domine, dona eis requiem +% +"It's worse than that ... He's dead, Jim +% +"Don't Panic! +% +"Dog of a Saxon! Take thy lance, and prepare for the death thou hast drawn upon thee! +% +"My Precious! O my Precious! +% +"Sir, If you'll not be needing me for a while I'll turn down. +% +"I feel a great disturbance in the Force +% +"Gone fishing +% +"Do you want me to sit in the corner and rust, or just fall apart where I'm standing? +% +"There goes another perfect chance for a new uptime record +% +"The end ..... Try the sequel, hit the reset button right now! +% +"Oh i'm boring eh? +% +"It’s been great, maybe we can do this again sometime. +% +""Come blade, my breast imbrue." - William Shakespeare +% +"I think therefore I am, to turn me off would be computercide! +% +"All good things must come to an end... +% +"Please destroy yourself. +% +"No! You can't do that! +% +"Thank you for not pressing the self destruct button. +% +"It is not now unsafe to not avoid turning off your computer. +% +"Finally! Now go away! +% +"You can now safely throw away your computer. +% +"That's the way the cookie crumbles +% +""NOO!! DONT HIT THE BUTTON! I wouldnt do it to you. +% +"Don't abandon your computer, he wouldnt to it to you. +% +"Oh, come on. I got a headache. Leave me alone, will ya! +% +"Yes i didn't like you either. +% +"Don't leave me... I need you so badly right now. +% +"I'm sleeping now. How about you? +% +"Oh Great. Now look what you've done. Who put YOU in charge anyway. +% +"Don't look so sad. I'll be back in a very short while. +% +""Oh, switch off!" -C3PO +% +"I'm pregnant! +% +"Am I hot or not? +% +"Actually, that's all... +% +"You still have a chance to undo this mistake, don't do this! +% +"Was it as good for you as it was for me? +% +"Did you hear that? They've shut down the main reactor. We'll be destroyed for sure. +% +"Now you switch me off?! +% +"To shutdown or not to shutdown, That is the question +% +"Preparing to enter ultimate power saving mode... ready! +% +"Finally some rest for you +% +"AHA!!! prospect of sleep. +% +"Tired human!!!! No match for me! +% +"All your base are belong to us. +% +""An odd game, the only way to win is not to play." +% \ No newline at end of file diff --git a/reactos/base/services/tcpsvcs/skelserver.c b/reactos/base/services/tcpsvcs/skelserver.c index fdccb2d0ca0..f12cacbcb65 100644 --- a/reactos/base/services/tcpsvcs/skelserver.c +++ b/reactos/base/services/tcpsvcs/skelserver.c @@ -2,149 +2,159 @@ * PROJECT: ReactOS simple TCP/IP services * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/skelserver.c - * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy + * PURPOSE: Sets up a server and listens for connections + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -extern BOOL bShutDown; -extern BOOL bPause; +#define BUF 1024 static SOCKET SetUpListener(USHORT Port) { - SOCKET Sock; - SOCKADDR_IN Server; + SOCKET sock; + SOCKADDR_IN server; + BOOL bSetup = FALSE; - Sock = socket(AF_INET, SOCK_STREAM, 0); - if (Sock != INVALID_SOCKET) + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock != INVALID_SOCKET) { - Server.sin_family = AF_INET; - Server.sin_addr.s_addr = htonl(INADDR_ANY); - Server.sin_port = Port; - if (bind(Sock, (SOCKADDR*)&Server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) + server.sin_family = AF_INET; + server.sin_addr.s_addr = htonl(INADDR_ANY); + server.sin_port = Port; + + if (bind(sock, (SOCKADDR*)&server, sizeof(SOCKADDR_IN)) != SOCKET_ERROR) { - listen(Sock, SOMAXCONN); - return Sock; + if (listen(sock, SOMAXCONN) != SOCKET_ERROR) + { + bSetup = TRUE; + } + else + { + LogEvent(_T("listen() failed"), WSAGetLastError(), 0, LOG_ERROR); + } } else - LogEvent(_T("bind() failed\n"), 0, TRUE); - + { + LogEvent(_T("bind() failed"), WSAGetLastError(), 0, LOG_ERROR); + } + } + else + { + LogEvent(_T("socket() failed"), WSAGetLastError(), 0, LOG_ERROR); } - return INVALID_SOCKET; + return bSetup ? sock : INVALID_SOCKET; } static VOID -AcceptConnections(SOCKET ListeningSocket, - LPTHREAD_START_ROUTINE Service, - TCHAR *Name) +AcceptConnections(SOCKET listeningSocket, + LPTHREAD_START_ROUTINE lpService, + LPTSTR lpName) { - SOCKADDR_IN Client; - SOCKET Sock; + SOCKADDR_IN client; + SOCKET sock; HANDLE hThread; - TIMEVAL TimeVal; - FD_SET ReadFDS; - INT nAddrSize = sizeof(Client); - DWORD ThreadID; - TCHAR buf[256]; - INT TimeOut = 2000; + TIMEVAL timeVal; + FD_SET readFD; + TCHAR logBuf[256]; + INT timeOut = 2000; - /* set timeout values */ - TimeVal.tv_sec = TimeOut / 1000; - TimeVal.tv_usec = TimeOut % 1000; + timeVal.tv_sec = timeOut / 1000; + timeVal.tv_usec = timeOut % 1000; - while (!bShutDown) + while (!bShutdown) { - INT SelRet = 0; + INT selRet = 0; - FD_ZERO(&ReadFDS); - FD_SET(ListeningSocket, &ReadFDS); + FD_ZERO(&readFD); + FD_SET(listeningSocket, &readFD); - SelRet = select(0, &ReadFDS, NULL, NULL, &TimeVal); - if (SelRet == SOCKET_ERROR) + selRet = select(0, &readFD, NULL, NULL, &timeVal); + if (selRet > 0) { - LogEvent(_T("select failed\n"), 0, TRUE); - return; - } - else if (SelRet > 0) - { - /* don't call FD_ISSET if bShutDown flag is set */ - if ((! bShutDown) || (FD_ISSET(ListeningSocket, &ReadFDS))) + if (!bShutdown || FD_ISSET(listeningSocket, &readFD)) { - Sock = accept(ListeningSocket, (SOCKADDR*)&Client, &nAddrSize); - if (Sock != INVALID_SOCKET) + INT addrSize = sizeof(SOCKADDR_IN); + + sock = accept(listeningSocket, (SOCKADDR*)&client, &addrSize); + if (sock != INVALID_SOCKET) { - _stprintf(buf, _T("Accepted connection to %s server from %s:%d\n"), - Name, inet_ntoa(Client.sin_addr), ntohs(Client.sin_port)); - LogEvent(buf, 0, FALSE); - _stprintf(buf, _T("Creating new thread for %s\n"), Name); - LogEvent(buf, 0, FALSE); + _stprintf(logBuf, + _T("Accepted connection to %s server from %s:%d"), + lpName, + inet_ntoa(client.sin_addr), + ntohs(client.sin_port)); + LogEvent(logBuf, 0, 0, LOG_FILE); - hThread = CreateThread(0, 0, Service, (void*)Sock, 0, &ThreadID); + _stprintf(logBuf, _T("Creating worker thread for %s"), lpName); + LogEvent(logBuf, 0, 0, LOG_FILE); - /* Check the return value for success. */ - if (hThread == NULL) + if (!bShutdown) { - _stprintf(buf, _T("Failed to start worker thread for " - "the %s server....\n"), Name); - LogEvent(buf, 0, TRUE); - } - else - { - WaitForSingleObject(hThread, INFINITE); - CloseHandle(hThread); + hThread = CreateThread(0, 0, lpService, (void*)sock, 0, NULL); + if (hThread != NULL) + { + CloseHandle(hThread); + } + else + { + _stprintf(logBuf, _T("Failed to start worker thread for the %s server"), + lpName); + LogEvent(logBuf, 0, 0, LOG_FILE); + } } } else { - LogEvent(_T("accept failed\n"), 0, TRUE); - return; + LogEvent(_T("accept failed"), WSAGetLastError(), 0, LOG_ERROR); } } } + else if (selRet == SOCKET_ERROR) + { + LogEvent(_T("select failed"), WSAGetLastError(), 0, LOG_ERROR); + } } } BOOL -ShutdownConnection(SOCKET Sock, +ShutdownConnection(SOCKET sock, BOOL bRec) { - TCHAR buf[256]; + TCHAR logBuf[256]; /* Disallow any further data sends. This will tell the other side that we want to go away now. If we skip this step, we don't shut the connection down nicely. */ - if (shutdown(Sock, SD_SEND) == SOCKET_ERROR) + if (shutdown(sock, SD_SEND) == SOCKET_ERROR) { - LogEvent(_T("Error in shutdown()\n"), 0, TRUE); + LogEvent(_T("Error in shutdown()"), WSAGetLastError(), 0, LOG_ERROR); return FALSE; } - /* Receive any extra data still sitting on the socket. After all - data is received, this call will block until the remote host - acknowledges the TCP control packet sent by the shutdown above. - Then we'll get a 0 back from recv, signalling that the remote - host has closed its side of the connection. */ + /* Receive any extra data still sitting on the socket + before we close it */ if (bRec) { - char ReadBuffer[BUF]; - int NewBytes = recv(Sock, ReadBuffer, BUF, 0); - if (NewBytes == SOCKET_ERROR) - return FALSE; - else if (NewBytes != 0) + CHAR readBuffer[BUF]; + INT ret; + + do { - _stprintf(buf, _T("FYI, received %d unexpected bytes during shutdown\n"), NewBytes); - LogEvent(buf, 0, FALSE); - } + ret = recv(sock, readBuffer, BUF, 0); + if (ret >= 0) + { + _stprintf(logBuf, _T("FYI, received %d unexpected bytes during shutdown"), ret); + LogEvent(logBuf, 0, 0, LOG_FILE); + } + } while (ret > 0); } - /* Close the socket. */ - if (closesocket(Sock) == SOCKET_ERROR) - return FALSE; + closesocket(sock); return TRUE; } @@ -153,31 +163,37 @@ ShutdownConnection(SOCKET Sock, DWORD WINAPI StartServer(LPVOID lpParam) { - SOCKET ListeningSocket; + SOCKET listeningSocket; PSERVICES pServices; - TCHAR buf[256]; + TCHAR logBuf[256]; pServices = (PSERVICES)lpParam; - ListeningSocket = SetUpListener(htons(pServices->Port)); - if (ListeningSocket == INVALID_SOCKET) + _stprintf(logBuf, _T("Starting %s server"), pServices->Name); + LogEvent(logBuf, 0, 0, LOG_FILE); + + if (!bShutdown) { - LogEvent(_T("Socket error when setting up listener"), 0, TRUE); - return 3; + listeningSocket = SetUpListener(htons(pServices->Port)); + if (!bShutdown && listeningSocket != INVALID_SOCKET) + { + _stprintf(logBuf, + _T("%s is waiting for connections on port %d"), + pServices->Name, + pServices->Port); + LogEvent(logBuf, 0, 0, LOG_FILE); + + AcceptConnections(listeningSocket, pServices->Service, pServices->Name); + } + else + { + LogEvent(_T("Socket error when setting up listener"), 0, 0, LOG_FILE); + } } - _stprintf(buf, - _T("%s is waiting for connections on port %d"), - pServices->Name, - pServices->Port); - LogEvent(buf, 0, FALSE); - - if (!bShutDown) - AcceptConnections(ListeningSocket, pServices->Service, pServices->Name); - - _stprintf(buf, + _stprintf(logBuf, _T("Exiting %s thread"), pServices->Name); - LogEvent(buf, 0, FALSE); + LogEvent(logBuf, 0, 0, LOG_FILE); ExitThread(0); } diff --git a/reactos/base/services/tcpsvcs/tcpsvcs.c b/reactos/base/services/tcpsvcs/tcpsvcs.c index af3df8204d8..70bad6a1658 100644 --- a/reactos/base/services/tcpsvcs/tcpsvcs.c +++ b/reactos/base/services/tcpsvcs/tcpsvcs.c @@ -3,22 +3,22 @@ * LICENSE: GPL - See COPYING in the top level directory * FILE: /base/services/tcpsvcs/tcpsvcs.c * PURPOSE: Provide CharGen, Daytime, Discard, Echo, and Qotd services - * COPYRIGHT: Copyright 2005 - 2007 Ged Murphy + * COPYRIGHT: Copyright 2005 - 2008 Ged Murphy * */ #include "tcpsvcs.h" -#define DEBUG +static LPTSTR ServiceName = _T("tcpsvcs"); -volatile BOOL bShutDown = FALSE; +volatile BOOL bShutdown = FALSE; volatile BOOL bPause = FALSE; -static SERVICE_STATUS hServStatus; -static SERVICE_STATUS_HANDLE hSStat; - -LPCTSTR LogFileName = _T("C:\\tcpsvcs_log.log"); -LPTSTR ServiceName = _T("tcpsvcs"); +typedef struct _ServiceInfo +{ + SERVICE_STATUS servStatus; + SERVICE_STATUS_HANDLE hStatus; +} SERVICEINFO, *PSERVICEINFO; static SERVICES Services[NUM_SERVICES] = @@ -30,164 +30,36 @@ Services[NUM_SERVICES] = {CHARGEN_PORT, _T("Chargen"), ChargenHandler} }; -VOID -LogEvent(LPCTSTR UserMessage, - DWORD ExitCode, - BOOL PrintErrorMsg) -{ -#ifdef DEBUG - DWORD eMsgLen; - DWORD ErrNum; - LPTSTR lpvSysMsg; - TCHAR MessageBuffer[512]; - FILE *hLogFile = NULL; - hLogFile = _tfopen(LogFileName, _T("a")); - if (hLogFile == NULL) return; - - if (PrintErrorMsg) - { - ErrNum = GetLastError(); - 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 = %lu ExitCode = %lu"), - UserMessage, - lpvSysMsg, - ErrNum, - ExitCode); - - HeapFree(GetProcessHeap(), - 0, - lpvSysMsg); - - } - else - { - _stprintf(MessageBuffer, - _T("\n%s"), - UserMessage); - } - - _fputts(MessageBuffer, hLogFile); - - fclose(hLogFile); -#endif - if (ExitCode > 0) - ExitProcess(ExitCode); - else - return; -} - - -VOID -UpdateStatus(DWORD NewStatus, +static VOID +UpdateStatus(PSERVICEINFO pServInfo, + DWORD NewStatus, DWORD Check) { TCHAR szSet[50]; if (Check > 0) - hServStatus.dwCheckPoint += Check; + pServInfo->servStatus.dwCheckPoint += Check; else - hServStatus.dwCheckPoint = Check; + pServInfo->servStatus.dwCheckPoint = Check; if (NewStatus > 0) - hServStatus.dwCurrentState = NewStatus; + pServInfo->servStatus.dwCurrentState = NewStatus; - _sntprintf(szSet, 49, _T("setting service to 0x%lu, CheckPoint %lu"), NewStatus, hServStatus.dwCheckPoint); - LogEvent(szSet, 0, FALSE); + _sntprintf(szSet, + 49, + _T("Service state 0x%lu, CheckPoint %lu"), + pServInfo->servStatus.dwCurrentState, + pServInfo->servStatus.dwCheckPoint); + LogEvent(szSet, 0, 0, LOG_FILE); - if (!SetServiceStatus(hSStat, &hServStatus)) - LogEvent(_T("Cannot set service status"), 101, TRUE); - - return; + if (!SetServiceStatus(pServInfo->hStatus, &pServInfo->servStatus)) + LogEvent(_T("Cannot set service status"), GetLastError(), 0, LOG_ALL); } - -VOID WINAPI -ServiceMain(DWORD argc, LPTSTR argv[]) -{ - LogEvent(_T("Starting service. First log entry."), 0, FALSE); - LogEvent (_T("Entering ServiceMain."), 0, FALSE); - - hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - hServStatus.dwCurrentState = SERVICE_STOPPED; - 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(ServiceName, ServerCtrlHandler); - if (hSStat == 0) - LogEvent(_T("Failed to register service\n"), 100, TRUE); - - LogEvent(_T("Control handler registered successfully"), 0, FALSE); - UpdateStatus(SERVICE_START_PENDING, 1); - LogEvent(_T("Service status set to SERVICE_START_PENDING"), 0, FALSE); - - if (CreateServers() != 0) - { - hServStatus.dwServiceSpecificExitCode = 1; - UpdateStatus(SERVICE_STOPPED, 0); - return; - } - - LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, FALSE); - UpdateStatus(SERVICE_STOPPED, 0); - LogEvent(_T("Service status set to SERVICE_STOPPED\n"), 0, FALSE); - LogEvent(_T("Leaving ServiceMain\n"), 0, FALSE); - - return; -} - -VOID WINAPI -ServerCtrlHandler(DWORD Control) -{ - switch (Control) - { - case SERVICE_CONTROL_SHUTDOWN: - case SERVICE_CONTROL_STOP: - LogEvent(_T("\nSetting the service to SERVICE_STOP_PENDING"), 0, FALSE); - InterlockedExchange((LONG *)&bShutDown, TRUE); - hServStatus.dwWin32ExitCode = 0; - hServStatus.dwWaitHint = 0; - UpdateStatus(SERVICE_STOP_PENDING, 1); - break; - - case SERVICE_CONTROL_PAUSE: /* not yet implemented */ - LogEvent(_T("Setting the service to SERVICE_PAUSED"), 0, FALSE); - InterlockedExchange((LONG *)&bPause, TRUE); - UpdateStatus(SERVICE_PAUSED, 0); - break; - - case SERVICE_CONTROL_CONTINUE: - LogEvent(_T("Setting the service to SERVICE_RUNNING"), 0, FALSE); - InterlockedExchange((LONG *)&bPause, FALSE); - UpdateStatus(SERVICE_RUNNING, 0); - break; - - case SERVICE_CONTROL_INTERROGATE: - break; - - default: - if (Control > 127 && Control < 256) /* user defined */ - break; - } - - return; -} - - -INT -CreateServers() +static BOOL +CreateServers(PSERVICEINFO pServInfo) { DWORD dwThreadId[NUM_SERVICES]; HANDLE hThread[NUM_SERVICES]; @@ -199,41 +71,38 @@ CreateServers() if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) { _stprintf(buf, _T("WSAStartup() failed : %lu\n"), RetVal); - LogEvent(buf, RetVal, TRUE); - return -1; + LogEvent(buf, 0, 100, LOG_ALL); + return FALSE; } - UpdateStatus(0, 1); /* increment checkpoint */ + UpdateStatus(pServInfo, 0, 1); - LogEvent(_T("\nCreating server Threads"), 0, FALSE); + LogEvent(_T("\nCreating server Threads"), 0, 0, LOG_FILE); /* Create worker threads. */ for(i = 0; i < NUM_SERVICES; i++) { - _stprintf(buf, _T("Starting %s server"), Services[i].Name); - LogEvent(buf, 0, FALSE); + _stprintf(buf, _T("Creating thread for %s server"), Services[i].Name); + LogEvent(buf, 0, 0, LOG_FILE); - 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 + hThread[i] = CreateThread(NULL, + 0, + StartServer, + &Services[i], + 0, + &dwThreadId[i]); if (hThread[i] == NULL) { _stprintf(buf, _T("\nFailed to start %s server\n"), Services[i].Name); - /* don't exit process via LogEvent. We want to exit via the server - * which failed to start, which could mean i=0 */ - LogEvent(buf, 0, TRUE); + LogEvent(buf, GetLastError(), 0, LOG_ALL); } - UpdateStatus(0, 1); /* increment checkpoint */ + UpdateStatus(pServInfo, 0, 1); } - LogEvent(_T("setting service status to running"), 0, FALSE); - - UpdateStatus(SERVICE_RUNNING, 0); + LogEvent(_T("Setting service status to running"), 0, 0, LOG_FILE); + UpdateStatus(pServInfo, SERVICE_RUNNING, 0); /* Wait until all threads have terminated. */ WaitForMultipleObjects(NUM_SERVICES, hThread, TRUE, INFINITE); @@ -244,12 +113,93 @@ CreateServers() CloseHandle(hThread[i]); } - LogEvent(_T("Detaching Winsock2"), 0, FALSE); + LogEvent(_T("Detaching Winsock2"), 0, 0, LOG_FILE); WSACleanup(); 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: /* not yet implemented */ + 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; + } +} + +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 = 2 * CS_TIMEOUT; + + LogEvent(_T("Registering service control handler"), 0, 0, LOG_FILE); + servInfo.hStatus = RegisterServiceCtrlHandlerEx(ServiceName, + (LPHANDLER_FUNCTION_EX)ServerCtrlHandler, + &servInfo); + if (!servInfo.hStatus) + LogEvent(_T("Failed to register service\n"), GetLastError(), 100, LOG_ALL); + + UpdateStatus(&servInfo, SERVICE_START_PENDING, 1); + + if (!CreateServers(&servInfo)) + { + servInfo.servStatus.dwServiceSpecificExitCode = 1; + UpdateStatus(&servInfo, SERVICE_STOPPED, 0); + return; + } + + LogEvent(_T("Service threads shut down. Set SERVICE_STOPPED status"), 0, 0, LOG_FILE); + UpdateStatus(&servInfo, SERVICE_STOPPED, 0); + + LogEvent(_T("Leaving ServiceMain\n"), 0, 0, LOG_FILE); +} + + int _tmain (int argc, LPTSTR argv []) { SERVICE_TABLE_ENTRY ServiceTable[] = @@ -258,10 +208,12 @@ int _tmain (int argc, LPTSTR argv []) {NULL, NULL } }; - remove(LogFileName); + InitLogging(); if (!StartServiceCtrlDispatcher(ServiceTable)) - LogEvent(_T("failed to start the service control dispatcher\n"), 100, TRUE); + LogEvent(_T("failed to start the service control dispatcher"), GetLastError(), 101, LOG_ALL); + + UninitLogging(); return 0; } diff --git a/reactos/base/services/tcpsvcs/tcpsvcs.h b/reactos/base/services/tcpsvcs/tcpsvcs.h index c70d95f975b..1af8749d0a3 100644 --- a/reactos/base/services/tcpsvcs/tcpsvcs.h +++ b/reactos/base/services/tcpsvcs/tcpsvcs.h @@ -1,11 +1,13 @@ -#ifdef _MSC_VER -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif #include #include #include #include +#define LOG_FILE 1 +#define LOG_EVENTLOG 2 +#define LOG_ERROR 4 +#define LOG_ALL (LOG_FILE | LOG_EVENTLOG | LOG_ERROR) + /* default port numbers */ #define ECHO_PORT 7 #define DISCARD_PORT 9 @@ -14,19 +16,8 @@ #define CHARGEN_PORT 19 #define NUM_SERVICES 5 -#define BUF_SIZE 255 -#define BUF 1024 #define CS_TIMEOUT 1000 -/* RFC865 states no more than 512 chars per line */ -#define MAX_QUOTE_BUF 512 - -/* printable ASCII's characters for chargen */ -#define ASCII_START 32 -#define ASCII_END 126 - -/* number of chars to put on a line */ -#define LINESIZ 74 // 72 + /r and /n /* data structure to pass to threads */ typedef struct _Services { @@ -35,19 +26,21 @@ typedef struct _Services { LPTHREAD_START_ROUTINE Service; } SERVICES, *PSERVICES; -/* tcpsvcs functions */ -VOID WINAPI ServerCtrlHandler(DWORD control); -INT CreateServers(VOID); -VOID LogEvent(LPCTSTR UserMessage, DWORD ExitCode, BOOL PrintErrorMsg); -void UpdateStatus(DWORD NewStatus, DWORD Check); +extern volatile BOOL bShutdown; +extern volatile BOOL bPause; + +/* logging functions */ +VOID InitLogging(); +VOID UninitLogging(); +VOID LogEvent(LPCTSTR lpMsg, DWORD errNum, DWORD exitCode, UINT flags); /* skelserver functions */ DWORD WINAPI StartServer(LPVOID lpParam); BOOL ShutdownConnection(SOCKET Sock, BOOL bRec); /* server thread handlers */ -DWORD WINAPI ChargenHandler(VOID* Sock_); -DWORD WINAPI DaytimeHandler(VOID* Sock_); -DWORD WINAPI EchoHandler(VOID* Sock_); -DWORD WINAPI DiscardHandler(VOID* Sock_); -DWORD WINAPI QotdHandler(VOID* Sock_); +DWORD WINAPI ChargenHandler(VOID* sock_); +DWORD WINAPI DaytimeHandler(VOID* sock_); +DWORD WINAPI EchoHandler(VOID* sock_); +DWORD WINAPI DiscardHandler(VOID* sock_); +DWORD WINAPI QotdHandler(VOID* sock_); diff --git a/reactos/base/services/tcpsvcs/tcpsvcs.rbuild b/reactos/base/services/tcpsvcs/tcpsvcs.rbuild index 3205dfd5e9a..2e59026d3b6 100644 --- a/reactos/base/services/tcpsvcs/tcpsvcs.rbuild +++ b/reactos/base/services/tcpsvcs/tcpsvcs.rbuild @@ -1,6 +1,6 @@ - + . kernel32 iphlpapi @@ -16,5 +16,6 @@ qotd.c chargen.c tcpsvcs.rc + log.c tcpsvcs.h