xref: /reactos/base/services/tcpsvcs/qotd.c (revision 3f976713)
1 /*
2  * PROJECT:     ReactOS simple TCP/IP services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/services/tcpsvcs/qotd.c
5  * PURPOSE:     Sends a random quote to the client
6  * COPYRIGHT:   Copyright 2005 - 2008 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "tcpsvcs.h"
11 
12 #include <stdlib.h>
13 
14 static WCHAR szFilePath[] = L"\\drivers\\etc\\quotes";
15 
16 static BOOL
17 SendQuote(SOCKET sock, char* Quote)
18 {
19     INT strSize = strlen(Quote);
20     if (send(sock, Quote, strSize, 0) == SOCKET_ERROR)
21         return FALSE;
22 
23     return TRUE;
24 }
25 
26 static BOOL
27 RetrieveQuote(SOCKET sock)
28 {
29     HANDLE hFile;
30     WCHAR szFullPath[MAX_PATH + 20];
31     DWORD dwBytesRead;
32     LPSTR lpQuotes;
33     LPSTR lpStr;
34     INT quoteNum;
35     INT NumQuotes = 0;
36     INT i;
37 
38     if(!GetSystemDirectoryW(szFullPath, MAX_PATH))
39     {
40         LogEvent(L"QOTD: Getting system path failed", GetLastError(), 0, LOG_FILE);
41         return FALSE;
42     }
43     wcscat(szFullPath, szFilePath);
44 
45 
46     LogEvent(L"QOTD: Opening quotes file", 0, 0, LOG_FILE);
47     hFile = CreateFileW(szFullPath,
48                         GENERIC_READ,
49                         0,
50                         NULL,
51                         OPEN_EXISTING,
52                         FILE_ATTRIBUTE_NORMAL,
53                         NULL);
54     if (hFile == INVALID_HANDLE_VALUE)
55     {
56         LogEvent(L"QOTD: Error opening quotes file", GetLastError(), 0, LOG_FILE);
57     }
58     else
59     {
60         DWORD dwSize = GetFileSize(hFile, NULL);
61         lpQuotes = (LPSTR)HeapAlloc(GetProcessHeap(), 0, dwSize + 1);
62         if (!lpQuotes)
63         {
64             CloseHandle(hFile);
65             return FALSE;
66         }
67 
68         ReadFile(hFile,
69                  lpQuotes,
70                  dwSize,
71                  &dwBytesRead,
72                  NULL);
73         CloseHandle(hFile);
74 
75         lpQuotes[dwSize] = 0;
76 
77         if (dwBytesRead != dwSize)
78         {
79             HeapFree(GetProcessHeap(), 0, lpQuotes);
80             return FALSE;
81         }
82 
83         lpStr = lpQuotes;
84         while (*lpStr)
85         {
86             if (*lpStr == '%')
87                 NumQuotes++;
88             lpStr++;
89         }
90 
91         /* pick a random quote */
92         srand((unsigned int) GetTickCount());
93         quoteNum = rand() % NumQuotes;
94 
95         /* retrieve the full quote */
96         lpStr = lpQuotes;
97         for (i = 1; i <= quoteNum; i++)
98         {
99             /* move past preceding quote */
100             lpStr++;
101 
102             if (i == quoteNum)
103             {
104                 LPSTR lpStart = lpStr;
105 
106                 while (*lpStr != '%' && *lpStr != '\0')
107                     lpStr++;
108 
109                 *lpStr = 0;
110 
111                 /* send the quote */
112                 if (!SendQuote(sock, lpStart))
113                     LogEvent(L"QOTD: Error sending data", 0, 0, LOG_FILE);
114                 break;
115             }
116             else
117             {
118                 while (*lpStr != '%' && *lpStr != '\0')
119                     lpStr++;
120 
121                 /* move past % and RN */
122                 lpStr += 2;
123             }
124         }
125 
126         HeapFree(GetProcessHeap(), 0, lpQuotes);
127         return TRUE;
128     }
129 
130     return FALSE;
131 }
132 
133 
134 DWORD WINAPI
135 QotdHandler(VOID* sock_)
136 {
137     SOCKET sock = (SOCKET)sock_;
138     DWORD retVal = 0;
139 
140     if (!RetrieveQuote(sock))
141     {
142         LogEvent(L"QOTD: Error retrieving quote", 0, 0, LOG_FILE);
143         retVal = 1;
144     }
145 
146     LogEvent(L"QOTD: Shutting connection down", 0, 0, LOG_FILE);
147     if (ShutdownConnection(sock, FALSE))
148     {
149         LogEvent(L"QOTD: Connection is down", 0, 0, LOG_FILE);
150     }
151     else
152     {
153         LogEvent(L"QOTD: Connection shutdown failed", 0, 0, LOG_FILE);
154         LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
155         retVal = 1;
156     }
157 
158     LogEvent(L"QOTD: Terminating thread", 0, 0, LOG_FILE);
159     ExitThread(retVal);
160 }
161