* Sync up to trunk head (r65481).
[reactos.git] / base / services / tcpsvcs / log.c
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 DWORD msgLen;
74
75 msgLen = wcslen(lpMsg) + 1;
76
77 if (flags & LOG_ERROR)
78 {
79 LPVOID 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 (LPTSTR)&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 if (lpFullMsg)
126 {
127 DWORD bytesWritten;
128 DWORD dwRet;
129 BOOL bRet;
130
131 bRet = WriteFile(hLogFile,
132 lpFullMsg,
133 wcslen(lpFullMsg) * sizeof(WCHAR),
134 &bytesWritten,
135 &olWrite);
136 if (!bRet)
137 {
138 if (GetLastError() != ERROR_IO_PENDING)
139 {
140 bRet = FALSE;
141 }
142 else
143 {
144 // Write is pending
145 dwRet = WaitForSingleObject(olWrite.hEvent, INFINITE);
146
147 switch (dwRet)
148 {
149 // event has been signaled
150 case WAIT_OBJECT_0:
151 {
152 bRet = GetOverlappedResult(hLogFile,
153 &olWrite,
154 &bytesWritten,
155 FALSE);
156 break;
157 }
158
159 default:
160 // An error has occurred in WaitForSingleObject.
161 // This usually indicates a problem with the
162 // OVERLAPPED structure's event handle.
163 bRet = FALSE;
164 break;
165 }
166 }
167 }
168
169 if (!bRet || bytesWritten == 0)
170 {
171 LogToEventLog(L"Failed to write to log file",
172 GetLastError(),
173 0,
174 LOG_EVENTLOG | LOG_ERROR);
175 }
176
177 HeapFree(GetProcessHeap(),
178 0,
179 lpFullMsg);
180 }
181
182 if (exitCode > 0)
183 ExitProcess(exitCode);
184 }
185
186
187
188 VOID
189 LogEvent(LPCWSTR lpMsg,
190 DWORD errNum,
191 DWORD exitCode,
192 UINT flags)
193 {
194 #ifdef DEBUG
195 if (flags & LOG_FILE || flags & LOG_ERROR)
196 LogToFile(lpMsg, errNum, exitCode, flags);
197 #endif
198 if (flags & LOG_EVENTLOG)
199 LogToEventLog(lpMsg, errNum, exitCode, flags);
200 }
201
202 BOOL
203 InitLogging()
204 {
205 #ifdef DEBUG
206 BOOL bRet = FALSE;
207
208 ZeroMemory(&olWrite, sizeof(OVERLAPPED));
209 olWrite.Offset = 0xFFFFFFFF;
210 olWrite.OffsetHigh = 0xFFFFFFFF;
211 olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
212 if (olWrite.hEvent)
213 {
214 DeleteFileW(lpLogFileName);
215
216 if (OpenLogFile())
217 {
218 WCHAR wcBom = 0xFEFF;
219 DWORD bytesWritten;
220
221 bRet = WriteFile(hLogFile,
222 &wcBom,
223 sizeof(WCHAR),
224 &bytesWritten,
225 &olWrite);
226 if (!bRet)
227 {
228 if (GetLastError() != ERROR_IO_PENDING)
229 {
230 LogToEventLog(L"Failed to write to log file",
231 GetLastError(),
232 0,
233 LOG_EVENTLOG | LOG_ERROR);
234 }
235 else
236 {
237 bRet = TRUE;
238 }
239 }
240 }
241 }
242
243 return bRet;
244 #else
245 return TRUE;
246 #endif
247 }
248
249 VOID
250 UninitLogging()
251 {
252 if (hLogFile)
253 {
254 FlushFileBuffers(hLogFile);
255 CloseHandle(hLogFile);
256 }
257
258 if (olWrite.hEvent)
259 {
260 CloseHandle(olWrite.hEvent);
261 }
262 }