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