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 } 263