609 lines
12 KiB
C++
609 lines
12 KiB
C++
/*++
|
||
|
||
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 <winnls.h>
|
||
#include <alloca.h>
|
||
|
||
#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);
|
||
}
|
||
|