/*++ Copyright (c) 1996 Microsoft Corporation Module Name: errlog.c Abstract: Routines to handle error log information Author: Jin Huang (jinhuang) 9-Nov-1996 Revision History: --*/ #include "headers.h" #include "serverp.h" #include #include #pragma hdrstop #define SCESRV_LOG_PATH L"\\security\\logs\\scesrv.log" extern HINSTANCE MyModuleHandle; HANDLE Thread hMyLogFile=INVALID_HANDLE_VALUE; BOOL ScepCheckLogging( IN INT ErrLevel, IN DWORD rc ); SCESTATUS ScepSetVerboseLog( IN INT dbgLevel ) { DWORD dValue; if ( dbgLevel > 0 ) { gDebugLevel = dbgLevel; } else { // // load value from registry // if ( ScepRegQueryIntValue( HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, L"DebugLevel", &dValue ) == SCESTATUS_SUCCESS ) gDebugLevel = (INT)dValue; else gDebugLevel = 1; } return(SCESTATUS_SUCCESS); } SCESTATUS ScepEnableDisableLog( IN BOOL bOnOff ) { bLogOn = bOnOff; if ( INVALID_HANDLE_VALUE != hMyLogFile ) { CloseHandle( hMyLogFile ); } // // Reset the LogFileName buffer and return // hMyLogFile = INVALID_HANDLE_VALUE; return(SCESTATUS_SUCCESS); } SCESTATUS ScepLogInitialize( IN PCWSTR logname ) /* ++ Routine Description: Open the log file specified and save the name and its handle in global variables. Arguments: logname - log file name Return value: SCESTATUS error code -- */ { DWORD rc=NO_ERROR; if ( !bLogOn ) { return(rc); } if ( logname && wcslen(logname) > 3 ) { hMyLogFile = CreateFile(logname, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ( INVALID_HANDLE_VALUE != hMyLogFile ) { DWORD dwBytesWritten; SetFilePointer (hMyLogFile, 0, NULL, FILE_BEGIN); CHAR TmpBuf[3]; TmpBuf[0] = (CHAR)0xFF; TmpBuf[1] = (CHAR)0xFE; TmpBuf[2] = '\0'; WriteFile (hMyLogFile, (LPCVOID)TmpBuf, 2, &dwBytesWritten, NULL); SetFilePointer (hMyLogFile, 0, NULL, FILE_END); } } else { hMyLogFile = INVALID_HANDLE_VALUE; } BOOL bOpenGeneral = FALSE; if ( INVALID_HANDLE_VALUE == hMyLogFile ) { // // use the general server log // LPTSTR dName=NULL; DWORD dirSize=0; DWORD rc = ScepGetNTDirectory( &dName, &dirSize, SCE_FLAG_WINDOWS_DIR ); if ( ERROR_SUCCESS == rc && dName ) { LPTSTR windirName = (LPTSTR)ScepAlloc(0, (dirSize+wcslen(SCESRV_LOG_PATH)+1)*sizeof(TCHAR)); if ( windirName ) { wcscpy(windirName, dName); wcscat(windirName, SCESRV_LOG_PATH); // // only keep current log transaction. if other threads are holding // on this log, it won't be deleted. It's ok (will be deleted later). // DeleteFile(windirName); hMyLogFile = CreateFile(windirName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if ( hMyLogFile != INVALID_HANDLE_VALUE ) { DWORD dwBytesWritten; SetFilePointer (hMyLogFile, 0, NULL, FILE_BEGIN); CHAR TmpBuf[3]; TmpBuf[0] = (CHAR)0xFF; TmpBuf[1] = (CHAR)0xFE; TmpBuf[2] = '\0'; WriteFile (hMyLogFile, (LPCVOID)TmpBuf, 2, &dwBytesWritten, NULL); SetFilePointer (hMyLogFile, 0, NULL, FILE_END); } ScepFree(windirName); bOpenGeneral = TRUE; } } if ( dName ) { ScepFree(dName); } } if ( hMyLogFile == INVALID_HANDLE_VALUE ) { // // Open file fails. return error // if (logname != NULL) rc = ERROR_INVALID_NAME; } // // log a separator to the file // ScepLogOutput3(0, 0, SCEDLL_SEPARATOR); if ( bOpenGeneral && logname ) { // // the log file provided is not valid, log it // ScepLogOutput3(0, 0, IDS_ERROR_OPEN_LOG, logname); } // // Write date/time information to the begining of the log file or to screen // TCHAR pvBuffer[100]; pvBuffer[0] = L'\0'; rc = ScepGetTimeStampString(pvBuffer); if ( pvBuffer[0] != L'\0' ) ScepLogOutput(0, pvBuffer); return(rc); } SCESTATUS ScepLogOutput2( IN INT ErrLevel, IN DWORD rc, IN PWSTR fmt, ... ) /* ++ Routine Description: This routine adds the information (variable arguments) to the end of the log file or prints to screen Arguments: ErrLevel - the error level of this error (to determine if the error needs to be outputted) rc - Win32 error code fmt - the format of the error information ... - variable argument list Return value: SCESTATUS error code -- */ { PWSTR buf=NULL; va_list args; if ( !ScepCheckLogging(ErrLevel, rc) ) { // // no log // return(SCESTATUS_SUCCESS); } // // check arguments // if ( !fmt ) return(SCESTATUS_SUCCESS); // // safely allocate the buffer on stack (or heap) // SafeAllocaAllocate( buf, SCE_BUF_LEN*sizeof(WCHAR) ); if ( buf == NULL ) { return(SCESTATUS_NOT_ENOUGH_RESOURCE); } va_start( args, fmt ); _vsnwprintf( buf, SCE_BUF_LEN - 1, fmt, args ); va_end( args ); SCESTATUS rCode = ScepLogOutput(rc, buf); SafeAllocaFree( buf ); return rCode; } SCESTATUS ScepLogOutput( IN DWORD rc, IN LPTSTR buf ) { if ( !buf ) { return(SCESTATUS_SUCCESS); } LPVOID lpMsgBuf=NULL; TCHAR strLevel[32]; INT idLevel=0; if ( rc != NO_ERROR ) { // // determine if this is warning, or error // if ( rc == ERROR_FILE_NOT_FOUND || rc == ERROR_PATH_NOT_FOUND || rc == ERROR_ACCESS_DENIED || rc == ERROR_CANT_ACCESS_FILE || rc == ERROR_SHARING_VIOLATION || rc == ERROR_INVALID_OWNER || rc == ERROR_INVALID_PRIMARY_GROUP || rc == ERROR_INVALID_HANDLE || rc == ERROR_INVALID_SECURITY_DESCR || rc == ERROR_INVALID_ACL || rc == ERROR_SOME_NOT_MAPPED ) { // // this is warning // idLevel = IDS_WARNING; } else { // // this is error // idLevel = IDS_ERROR; } strLevel[0] = L'\0'; if ( idLevel > 0 ) { LoadString( MyModuleHandle, idLevel, strLevel, 31 ); } // // get error description of rc // FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, 0, NULL ); } if ( hMyLogFile != INVALID_HANDLE_VALUE ) { // // The log file is initialized // if ( rc != NO_ERROR ) { if ( lpMsgBuf != NULL ) ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %d: %s %s", strLevel, rc, (PWSTR)lpMsgBuf, buf ); else ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %d: %s", strLevel, rc, buf ); } else { if ( lpMsgBuf != NULL ) ScepWriteVariableUnicodeLog( hMyLogFile, TRUE, L"%s %s", (PWSTR)lpMsgBuf, buf ); else ScepWriteSingleUnicodeLog( hMyLogFile, TRUE, buf ); } } if ( lpMsgBuf != NULL ) LocalFree(lpMsgBuf); return(SCESTATUS_SUCCESS); } BOOL ScepCheckLogging( IN INT ErrLevel, IN DWORD rc ) { DWORD dValue; if ( rc ) gWarningCode = rc; if ( !bLogOn ) { return(FALSE); } if ( gDebugLevel < 0 ) { // // load value from registry // if ( ScepRegQueryIntValue( HKEY_LOCAL_MACHINE, SCE_ROOT_PATH, L"DebugLevel", &dValue ) == SCESTATUS_SUCCESS ) gDebugLevel = (INT)dValue; else gDebugLevel = 1; } // // return if the error level is higher than required // if ( ErrLevel > gDebugLevel ) { return(FALSE); } else { return(TRUE); } } SCESTATUS ScepLogOutput3( IN INT ErrLevel, IN DWORD rc, IN UINT nId, ... ) /* ++ Routine Description: This routine load resource and adds error info (variable arguments) to the end of the log file or prints to screen Arguments: ErrLevel - the error level of this error (to determine if the error needs to be outputted) rc - Win32 error code nId - the resource string ID ... - variable argument list Return value: SCESTATUS error code -- */ { WCHAR szTempString[256]; PWSTR buf=NULL; va_list args; if ( !ScepCheckLogging(ErrLevel, rc) ) { // // no log // return(SCESTATUS_SUCCESS); } if ( nId > 0 ) { szTempString[0] = L'\0'; LoadString( MyModuleHandle, nId, szTempString, 256 ); // // safely allocate the buffer on stack (or heap) // SafeAllocaAllocate( buf, SCE_BUF_LEN*sizeof(WCHAR) ); if ( buf == NULL ) { return(SCESTATUS_NOT_ENOUGH_RESOURCE); } // // get the arguments // va_start( args, nId ); _vsnwprintf( buf, SCE_BUF_LEN - 1, szTempString, args ); va_end( args ); // // log it and free // SCESTATUS rCode = ScepLogOutput(rc, buf); SafeAllocaFree( buf ); return rCode; } return(SCESTATUS_SUCCESS); } SCESTATUS ScepLogWriteError( IN PSCE_ERROR_LOG_INFO pErrlog, IN INT ErrLevel ) /* ++ Routine Description: This routine outputs the error message in each node of the SCE_ERROR_LOG_INFO list to the log file Arguments: pErrlog - the error list Return value: None -- */ { PSCE_ERROR_LOG_INFO pErr; if ( !bLogOn ) { return(SCESTATUS_SUCCESS); } for ( pErr=pErrlog; pErr != NULL; pErr = pErr->next ) if ( pErr->buffer != NULL ) ScepLogOutput2( ErrLevel, pErr->rc, pErr->buffer ); return(SCESTATUS_SUCCESS); } SCESTATUS ScepLogClose() /* ++ Routine Description: Close the log file if there is one opened. Clear the log varialbes Arguments: None Return value: None --*/ { if ( !bLogOn ) { return(SCESTATUS_SUCCESS); } if ( hMyLogFile != INVALID_HANDLE_VALUE ) { CloseHandle( hMyLogFile ); } // // Reset the log handle // hMyLogFile = INVALID_HANDLE_VALUE; return(SCESTATUS_SUCCESS); }