/********************************************************************/ /** Copyright(c) 1992 Microsoft Corporation. **/ /********************************************************************/ // // // Filename: event.c // // Description: // // History: // August 26,1992. Stefan Solomon Created original version. // August 27,1995. Abolade Gbadegesin Modified to support Unicode. // See trace.h for notes on how // this file is used to support // both ANSI and Unicode. // // #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#define STRSAFE_LIB #include #define ROUTER_SERVICE RRAS_SERVICE_NAME HINSTANCE g_hDll; #if defined(UNICODE) || defined(_UNICODE) #define STRING_NULL UNICODE_NULL #define UNICODE_STRING_TAG L'S' #define ANSI_STRING_TAG L's' #define TCHAR_STRING_TAG L't' #define DECIMAL_TAG L'd' #define IPADDRESS_TAG L'I' #else #define STRING_NULL '\0' #define UNICODE_STRING_TAG 'S' #define ANSI_STRING_TAG 's' #define TCHAR_STRING_TAG 't' #define DECIMAL_TAG 'd' #define IPADDRESS_TAG 'I' #endif #define PRINT_IPADDR(x) \ ((x)&0x000000ff),(((x)&0x0000ff00)>>8),(((x)&0x00ff0000)>>16),(((x)&0xff000000)>>24) // // // Function: LogError // // Descr: // // VOID APIENTRY LogError( IN DWORD dwMessageId, IN DWORD cNumberOfSubStrings, IN LPTSTR *plpszSubStrings, IN DWORD dwErrorCode ) { HANDLE hLog; PSID pSidUser = NULL; hLog = RegisterEventSource(NULL, ROUTER_SERVICE ); if (hLog == NULL) return; if ( dwErrorCode == NO_ERROR ) { // // No error codes were specified // ReportEvent( hLog, EVENTLOG_ERROR_TYPE, 0, // event category dwMessageId, pSidUser, (WORD)cNumberOfSubStrings, 0, plpszSubStrings, (PVOID)NULL ); } else { // // Log the error code specified // ReportEvent( hLog, EVENTLOG_ERROR_TYPE, 0, // event category dwMessageId, pSidUser, (WORD)cNumberOfSubStrings, sizeof(DWORD), plpszSubStrings, (PVOID)&dwErrorCode ); } DeregisterEventSource( hLog ); } // // // Function: LogEvent // // Descr: // // VOID APIENTRY LogEvent( IN DWORD wEventType, IN DWORD dwMessageId, IN DWORD cNumberOfSubStrings, IN LPTSTR *plpszSubStrings ) { HANDLE hLog; PSID pSidUser = NULL; // Audit enabled hLog = RegisterEventSource( NULL, ROUTER_SERVICE ); if (hLog == NULL) return; ReportEvent( hLog, (WORD)wEventType, // success/failure audit 0, // event category dwMessageId, pSidUser, (WORD)cNumberOfSubStrings, 0, plpszSubStrings, (PVOID)NULL); DeregisterEventSource( hLog ); } //---------------------------------------------------------------------------- // Function: RouterLogRegister // // Returns a HANDLE which can be passed to RouterLogEvent // to log events from the specified source. //---------------------------------------------------------------------------- HANDLE RouterLogRegister( LPCTSTR lpszSource ) { return RegisterEventSource(NULL, lpszSource); } //---------------------------------------------------------------------------- // Function: RouterLogDeregister // // Closes a HANDLE created by RouterLogRegister //---------------------------------------------------------------------------- VOID RouterLogDeregister( HANDLE hLogHandle ) { if(NULL != hLogHandle) { DeregisterEventSource(hLogHandle); } } //---------------------------------------------------------------------------- // Function: RouterLogEvent // // Logs an event using a HANDLE created by RouterLogRegister. //---------------------------------------------------------------------------- VOID RouterLogEvent( IN HANDLE hLogHandle, IN DWORD dwEventType, IN DWORD dwMessageId, IN DWORD dwSubStringCount, IN LPTSTR *plpszSubStringArray, IN DWORD dwErrorCode ) { if(NULL == hLogHandle) { return; } if (dwErrorCode == NO_ERROR) { ReportEvent( hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, (WORD)dwSubStringCount, 0, plpszSubStringArray, (PVOID)NULL ); } else { ReportEvent( hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, (WORD)dwSubStringCount, sizeof(DWORD), plpszSubStringArray, (PVOID)&dwErrorCode ); } } VOID RouterLogEventEx( IN HANDLE hLogHandle, IN DWORD dwEventType, IN DWORD dwErrorCode, IN DWORD dwMessageId, IN LPCTSTR ptszFormat, ... ) { va_list vlArgList; if(NULL == hLogHandle) { return; } va_start(vlArgList, ptszFormat); RouterLogEventValistEx( hLogHandle, dwEventType, dwErrorCode, dwMessageId, ptszFormat, vlArgList ); va_end(vlArgList); } VOID RouterLogEventValistEx( IN HANDLE hLogHandle, IN DWORD dwEventType, IN DWORD dwErrorCode, IN DWORD dwMessageId, IN LPCTSTR ptszFormat, IN va_list vlArgList ) /*++ Routine Description This function logs an event, but also parses out the insert strings Locks None Arguments hLogHandle Handle from RegisterLogRegister() dwEventType EVENTLOG_{ERROR|WARNING|INFORMATION}_TYPE dwErrorCode The error code to report dwMessageId The ID of the message string ptszFormat A string specifying the format of the following insert values. The type of the value is dictated by the format string. The format string consists of a series of % There MUST BE NOTHING ELSE - no escape characters, no nothing. Valid are: S: Unicode string s: ANSII string t: TCHAR string d: integer I: IP Address in network order Return Value None --*/ { PWCHAR rgpwszInsertArray[20]; LPCTSTR ptszTemp; WORD wNumInsert; ULONG i, ulDecIndex, ulFormatLen; DWORD dwErr=NO_ERROR, dwNumAllocStrings=0; PWCHAR pszAllocArray[20]; HRESULT hrResult; // // 22 is enough to hold 2^64 // There can be max 20 insert strings // WCHAR rgpwszDecString[20][22]; if (ptszFormat==NULL) ptszFormat = TEXT(""); if(NULL == hLogHandle) { return; } // // First make sure that the format list doesnt specify more than // 20 characters // ptszTemp = ptszFormat; ulFormatLen = _tcslen(ptszFormat); wNumInsert = 0; ulDecIndex = 0; i = 0; // // We will only walk the first 20 format specifiers // while((i < ulFormatLen) && (wNumInsert < 20)) { if(*ptszTemp == __TEXT('%')) { // // Ok so this could be a good specifier - check the next character // i++; ptszTemp++; switch(*ptszTemp) { case UNICODE_STRING_TAG: { rgpwszInsertArray[wNumInsert] = va_arg(vlArgList, PWCHAR); wNumInsert++; break; } case ANSI_STRING_TAG: { PCHAR pszString; PWCHAR pwszWideString; ULONG ulLenNumChars;//nu pszString = va_arg(vlArgList, PCHAR); ulLenNumChars = strlen(pszString); if(ulLenNumChars) { pwszWideString = HeapAlloc(GetProcessHeap(), 0, (ulLenNumChars+1) * sizeof(WCHAR)); if (!pwszWideString) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } pszAllocArray[dwNumAllocStrings++] = pwszWideString; MultiByteToWideChar(CP_ACP, 0, pszString, -1, pwszWideString, ulLenNumChars+1); rgpwszInsertArray[wNumInsert] = pwszWideString; } else { // // L"" will be on our stack, but it cant go away // rgpwszInsertArray[wNumInsert] = L""; } wNumInsert++; break; } case TCHAR_STRING_TAG: { #if defined(UNICODE) || defined(_UNICODE) rgpwszInsertArray[wNumInsert] = va_arg(vlArgList, PWCHAR); #else PCHAR pszString; PWCHAR pwszWideString; ULONG ulLenNumChars; pszString = va_arg(vlArgList, PCHAR); ulLenNumChars = strlen(pszString); if(ulLenNumChars) { pwszWideString = HeapAlloc(GetProcessHeap(), 0, (ulLenNumChars+1) * sizeof(WCHAR)); if (!pwszWideString) { dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } pszAllocArray[dwNumAllocStrings++] = pwszWideString; if (MultiByteToWideChar(CP_ACP, 0, pszString, -1, pwszWideString, ulLenNumChars+1) == 0) { dwErr = GetLastError(); break; } rgpwszInsertArray[wNumInsert] = pwszWideString; } else { // // L"" will be on our stack, but it cant go away // rgpwszInsertArray[wNumInsert] = L""; } #endif wNumInsert++; break; } case DECIMAL_TAG: { hrResult = StringCchPrintfW(&(rgpwszDecString[ulDecIndex][0]), 21, L"%d", va_arg(vlArgList, int)); if (FAILED(hrResult)){ dwErr = HRESULT_CODE(hrResult); break; } rgpwszInsertArray[wNumInsert] = &(rgpwszDecString[ulDecIndex][0]); ulDecIndex++; wNumInsert++; break; } case IPADDRESS_TAG: { DWORD dwAddr; dwAddr = va_arg(vlArgList, int); hrResult = StringCchPrintfW(&(rgpwszDecString[ulDecIndex][0]), 21, L"%d.%d.%d.%d", PRINT_IPADDR(dwAddr)); if (FAILED(hrResult)){ dwErr = HRESULT_CODE(hrResult); break; } rgpwszInsertArray[wNumInsert] = &(rgpwszDecString[ulDecIndex][0]); ulDecIndex++; wNumInsert++; break; } } } // // Scan next character // ptszTemp++; i++; } if (dwErr == NO_ERROR) { if (dwErrorCode == NO_ERROR) { ReportEventW(hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, wNumInsert, 0, rgpwszInsertArray, (PVOID)NULL); } else { ReportEventW(hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, wNumInsert, sizeof(DWORD), rgpwszInsertArray, (PVOID)&dwErrorCode); } } // free the strings while (dwNumAllocStrings--) { HeapFree(GetProcessHeap(), 0, pszAllocArray[dwNumAllocStrings]); } } //---------------------------------------------------------------------------- // Function: RouterLogEventData // // Logs an event using a HANDLE created by RouterLogRegister. // Allows caller to include data in the eventlog message. //---------------------------------------------------------------------------- VOID RouterLogEventData( IN HANDLE hLogHandle, IN DWORD dwEventType, IN DWORD dwMessageId, IN DWORD dwSubStringCount, IN LPTSTR *plpszSubStringArray, IN DWORD dwDataBytes, IN LPBYTE lpDataBytes ) { // plpszSubStringArray can be null. if(NULL == hLogHandle) { return; } ReportEvent( hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, (WORD)dwSubStringCount, dwDataBytes, plpszSubStringArray, (PVOID)lpDataBytes ); } //---------------------------------------------------------------------------- // Function: RouterLogEventString // // Logs an event using a HANDLE created by RouterLogRegister. // Allows caller to include an error code string into the log //---------------------------------------------------------------------------- VOID RouterLogEventString( IN HANDLE hLogHandle, IN DWORD dwEventType, IN DWORD dwMessageId, IN DWORD dwSubStringCount, IN LPTSTR *plpszSubStringArray, IN DWORD dwErrorCode, IN DWORD dwErrorIndex ){ DWORD dwRetCode; DWORD dwIndex; DWORD dwSubStringIndex = 0; LPTSTR plpszStringArray[20]; if(NULL == hLogHandle) { return; } if (dwSubStringCount >= 21 || dwErrorIndex>dwSubStringCount) return; dwSubStringCount++; for ( dwIndex = 0; dwIndex < dwSubStringCount; dwIndex++ ) { if ( dwIndex == dwErrorIndex ) { dwRetCode = RouterGetErrorString( dwErrorCode, &plpszStringArray[dwIndex] ); if ( dwRetCode != NO_ERROR ) { //RTASSERT( dwRetCode == NO_ERROR ); return; } } else { plpszStringArray[dwIndex] = plpszSubStringArray[dwSubStringIndex++]; } } ReportEvent( hLogHandle, (WORD)dwEventType, 0, dwMessageId, NULL, (WORD)dwSubStringCount, sizeof(DWORD), plpszStringArray, (PVOID)&dwErrorCode ); LocalFree( plpszStringArray[dwErrorIndex] ); } //---------------------------------------------------------------------------- // Function: RouterGetErrorString // // Given an error code from raserror.h mprerror.h or winerror.h will return // a string associated with it. The caller is required to free the string // by calling LocalFree. //---------------------------------------------------------------------------- DWORD RouterGetErrorString( IN DWORD dwError, OUT LPTSTR * lplpszErrorString ) { DWORD dwRetCode = NO_ERROR; DWORD dwBufferSize; if ( ( ( dwError >= RASBASE ) && ( dwError <= RASBASEEND ) ) || ( ( dwError >= ROUTEBASE ) && ( dwError <= ROUTEBASEEND ) ) || ( ( dwError >= ROUTER_LOG_BASE) && (dwError <= ROUTER_LOG_BASEEND))) { // make sure that load library is called only once if (InterlockedCompareExchangePointer( &g_hDll, INVALID_HANDLE_VALUE, NULL) == NULL) { g_hDll = LoadLibrary( TEXT("mprmsg.dll") ); if(g_hDll == NULL) { return( GetLastError() ); } } while (*((HINSTANCE volatile *)&g_hDll)==INVALID_HANDLE_VALUE) Sleep(500); if (g_hDll==NULL) return ERROR_CAN_NOT_COMPLETE; dwRetCode = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER, g_hDll, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)lplpszErrorString, 0, NULL ); } else { dwRetCode = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)lplpszErrorString, 0, NULL ); } if ( dwRetCode == 0 ) { return( GetLastError() ); } else { return( NO_ERROR ); } }