[DCOMLAUNCH] Add a DcomLaunch service stub
[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 WCHAR szLogFileName[MAX_PATH];
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(szLogFileName,
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 if (!GetEnvironmentVariableW(L"SystemDrive", szLogFileName, ARRAYSIZE(szLogFileName)))
216 {
217 StringCchCopyW(szLogFileName, ARRAYSIZE(szLogFileName), L"C:");
218 }
219 StringCchCatW(szLogFileName, ARRAYSIZE(szLogFileName), L"\\tcpsvcs_log.log");
220
221 ZeroMemory(&olWrite, sizeof(OVERLAPPED));
222 olWrite.Offset = 0xFFFFFFFF;
223 olWrite.OffsetHigh = 0xFFFFFFFF;
224 olWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
225 if (olWrite.hEvent)
226 {
227 DeleteFileW(szLogFileName);
228
229 if (OpenLogFile())
230 {
231 WCHAR wcBom = 0xFEFF;
232 DWORD bytesWritten;
233
234 bRet = WriteFile(hLogFile,
235 &wcBom,
236 sizeof(WCHAR),
237 &bytesWritten,
238 &olWrite);
239 if (!bRet)
240 {
241 if (GetLastError() != ERROR_IO_PENDING)
242 {
243 LogToEventLog(L"Failed to write to log file",
244 GetLastError(),
245 0,
246 LOG_EVENTLOG | LOG_ERROR);
247 }
248 else
249 {
250 bRet = TRUE;
251 }
252 }
253 }
254 }
255
256 return bRet;
257 #else
258 return TRUE;
259 #endif
260 }
261
262 VOID
263 UninitLogging()
264 {
265 if (hLogFile)
266 {
267 FlushFileBuffers(hLogFile);
268 CloseHandle(hLogFile);
269 }
270
271 if (olWrite.hEvent)
272 {
273 CloseHandle(olWrite.hEvent);
274 }
275 }