xref: /reactos/base/services/tcpsvcs/log.c (revision d5399189)
1 /*
2  * PROJECT:     ReactOS simple TCP/IP services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/services/tcpsvcs/log.c
5  * PURPOSE:     Logging functionality for the service
6  * COPYRIGHT:   Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "tcpsvcs.h"
11 
12 #define DEBUG
13 
14 static LPWSTR lpEventSource = L"tcpsvcs";
15 static LPCWSTR lpLogFileName = L"C:\\tcpsvcs_log.log";
16 static HANDLE hLogFile = NULL;
17 
18 static OVERLAPPED olWrite;
19 
20 
21 // needs work
22 static VOID
23 LogToEventLog(LPCWSTR lpMsg,
24               DWORD errNum,
25               DWORD exitCode,
26               UINT flags)
27 {
28     HANDLE hEventLog;
29 
30     hEventLog = RegisterEventSourceW(NULL, lpEventSource);
31     if (hEventLog)
32     {
33         ReportEventW(hEventLog,
34                      (flags & LOG_ERROR) ? EVENTLOG_ERROR_TYPE : EVENTLOG_SUCCESS,
35                      0,
36                      0,
37                      NULL,
38                      1,
39                      0,
40                      &lpMsg,
41                      NULL);
42 
43         CloseEventLog(hEventLog);
44     }
45 }
46 
47 static BOOL
48 OpenLogFile()
49 {
50     hLogFile = CreateFileW(lpLogFileName,
51                            GENERIC_WRITE,
52                            FILE_SHARE_READ,
53                            NULL,
54                            OPEN_ALWAYS,
55                            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
56                            NULL);
57     if (hLogFile  == INVALID_HANDLE_VALUE)
58     {
59         hLogFile = NULL;
60         return FALSE;
61     }
62 
63     return TRUE;
64 }
65 
66 static VOID
67 LogToFile(LPCWSTR lpMsg,
68           DWORD errNum,
69           DWORD exitCode,
70           UINT flags)
71 {
72     LPWSTR lpFullMsg = NULL;
73     SIZE_T msgLen;
74 
75     msgLen = wcslen(lpMsg) + 1;
76 
77     if (flags & LOG_ERROR)
78     {
79         LPWSTR lpSysMsg;
80         DWORD eMsgLen;
81 
82         eMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
83                                  NULL,
84                                  errNum,
85                                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
86                                  (LPWSTR)&lpSysMsg,
87                                  0,
88                                  NULL);
89 
90         msgLen = msgLen + eMsgLen + 40;
91 
92         lpFullMsg = HeapAlloc(GetProcessHeap(),
93                               0,
94                               msgLen * sizeof(TCHAR));
95         if (lpFullMsg)
96         {
97             _snwprintf(lpFullMsg,
98                        msgLen,
99                        L"%s : %s\tErrNum = %lu ExitCode = %lu\r\n",
100                        lpMsg,
101                        lpSysMsg,
102                        errNum,
103                        exitCode);
104         }
105 
106         LocalFree(lpSysMsg);
107 
108     }
109     else
110     {
111         msgLen += 2;
112 
113         lpFullMsg = HeapAlloc(GetProcessHeap(),
114                               0,
115                               msgLen * sizeof(TCHAR));
116         if (lpFullMsg)
117         {
118             _snwprintf(lpFullMsg,
119                        msgLen,
120                       L"%s\r\n",
121                       lpMsg);
122         }
123     }
124 
125     /* Make sure the length in bytes doesn't overflow a DWORD */
126     msgLen = wcslen(lpFullMsg);
127     if (msgLen > (MAXDWORD / sizeof(WCHAR)))
128     {
129         RaiseException(EXCEPTION_INT_OVERFLOW, 0, 0, NULL);
130     }
131 
132     if (lpFullMsg)
133     {
134         DWORD bytesWritten;
135         DWORD dwRet;
136         BOOL bRet;
137 
138         bRet = WriteFile(hLogFile,
139                          lpFullMsg,
140                          (DWORD)msgLen * sizeof(WCHAR),
141                          &bytesWritten,
142                          &olWrite);
143         if (!bRet)
144         {
145             if (GetLastError() != ERROR_IO_PENDING)
146             {
147                 bRet = FALSE;
148             }
149             else
150             {
151                 // Write is pending
152                 dwRet = WaitForSingleObject(olWrite.hEvent, INFINITE);
153 
154                  switch (dwRet)
155                  {
156                     // event has been signaled
157                     case WAIT_OBJECT_0:
158                     {
159                          bRet = GetOverlappedResult(hLogFile,
160                                                     &olWrite,
161                                                     &bytesWritten,
162                                                     FALSE);
163                          break;
164                     }
165 
166                     default:
167                          // An error has occurred in WaitForSingleObject.
168                          // This usually indicates a problem with the
169                          // OVERLAPPED structure's event handle.
170                          bRet = FALSE;
171                          break;
172                  }
173             }
174         }
175 
176         if (!bRet || bytesWritten == 0)
177         {
178             LogToEventLog(L"Failed to write to log file",
179                           GetLastError(),
180                           0,
181                           LOG_EVENTLOG | LOG_ERROR);
182         }
183 
184         HeapFree(GetProcessHeap(),
185                  0,
186                  lpFullMsg);
187     }
188 
189     if (exitCode > 0)
190         ExitProcess(exitCode);
191 }
192 
193 
194 
195 VOID
196 LogEvent(LPCWSTR lpMsg,
197          DWORD errNum,
198          DWORD exitCode,
199          UINT flags)
200 {
201 #ifdef DEBUG
202     if (flags & LOG_FILE || flags & LOG_ERROR)
203         LogToFile(lpMsg, errNum, exitCode, flags);
204 #endif
205     if (flags & LOG_EVENTLOG)
206         LogToEventLog(lpMsg, errNum, exitCode, flags);
207 }
208 
209 BOOL
210 InitLogging()
211 {
212 #ifdef DEBUG
213     BOOL bRet = FALSE;
214 
215     ZeroMemory(&olWrite, sizeof(OVERLAPPED));
216     olWrite.Offset = 0xFFFFFFFF;
217     olWrite.OffsetHigh = 0xFFFFFFFF;
218     olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
219     if (olWrite.hEvent)
220     {
221         DeleteFileW(lpLogFileName);
222 
223         if (OpenLogFile())
224         {
225             WCHAR wcBom = 0xFEFF;
226             DWORD bytesWritten;
227 
228             bRet = WriteFile(hLogFile,
229                              &wcBom,
230                              sizeof(WCHAR),
231                              &bytesWritten,
232                              &olWrite);
233             if (!bRet)
234             {
235                 if (GetLastError() != ERROR_IO_PENDING)
236                 {
237                     LogToEventLog(L"Failed to write to log file",
238                                   GetLastError(),
239                                   0,
240                                   LOG_EVENTLOG | LOG_ERROR);
241                 }
242                 else
243                 {
244                     bRet = TRUE;
245                 }
246             }
247         }
248     }
249 
250     return bRet;
251 #else
252     return TRUE;
253 #endif
254 }
255 
256 VOID
257 UninitLogging()
258 {
259     if (hLogFile)
260     {
261         FlushFileBuffers(hLogFile);
262         CloseHandle(hLogFile);
263     }
264 
265     if (olWrite.hEvent)
266     {
267         CloseHandle(olWrite.hEvent);
268     }
269 }
270