Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2234 lines
62 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name :
inetlog.cxx
Abstract:
Defines the C interface for creating Internet Services Logging.
Author:
Murali R. Krishnan ( MuraliK ) 2-Feb-1995
Environment:
User Mode -- Win32
Project:
Internet Services common DLL
Functions Exported:
INETLOG_HANDLE TsCreateInetLogA()
INETLOG_HANDLE TsCreateInetLogW()
DWORD TsLogInformationA()
DWORD TsLogInformationW()
BOOL TsCloseInetLog()
BOOL TsReadInetLogConfigurationW()
BOOL TsWriteInetLogConfigurationW()
DWORD TsModifyLogConfigurationW()
BOOL TsGetLogInformation()
Revision History:
MuraliK 15-May-1995 Extended the LogInformation structure.
MuraliK 28-Jun-1995 Added ANSI API for LogInformation()
MuraliK 14-July-1995 Support for dynamically changing
logging behaviour added.
--*/
/************************************************************
* Include Headers
************************************************************/
#include "tcpdllp.hxx"
#include <tsproc.hxx>
#include "inetlog.h"
#include "ilogcls.hxx"
/************************************************************
* Registry Entries and Default Values
************************************************************/
# define PSZ_SERVICES_REG_ENTRY_W \
L"SYSTEM\\CurrentControlSet\\Services"
# define PSZ_PARAMETERS_REG_ENTRY_W L"Parameters"
# define LEN_PSZ_SERVICES_REG_ENTRY_W lstrlenW( PSZ_SERVICES_REG_ENTRY_W)
# define LEN_PSZ_PARAMETERS_REG_ENTRY_W lstrlenW(PSZ_PARAMETERS_REG_ENTRY_W)
# define MAX_LOG_PARAMETERS_FIELD_LEN (150)
//
// Logging related parameters
//
# define PSZ_LOG_TYPE_W L"LogType" // DWORD
# define PSZ_LOG_FILE_DIRECTORY_W L"LogFileDirectory" // EXPAND_SZ
# define PSZ_LOG_FILE_TRUNCATE_SIZE_W L"LogFileTruncateSize" // DWORD
# define PSZ_LOG_FILE_PERIOD_W L"LogFilePeriod" // DWORD
# define PSZ_LOG_FILE_FORMAT_W L"LogFileFormat" // DWORD
# define PSZ_LOG_SQL_DATASOURCE_W L"LogSqlDataSource" // SZ
# define PSZ_LOG_SQL_TABLE_W L"LogSqlTableName" // SZ
# define PSZ_LOG_SQL_USER_NAME_W L"LogSqlUserName" // SZ
# define PSZ_LOG_SQL_PASSWORD_W L"LogSqlPassword" // SZ
# define PSZ_LOG_FILE_BATCH_SIZE_W L"LogFileBatchSize" // DWORD
# define PSZ_LOG_FILE_FLUSH_INTERVAL_W L"LogFileFlushInterval" // DWORD
//
// Soon the password will be replaced by LSA_LOGON secret entry.
//
//
// Default values for Logging related registry parameters
//
# define DEFAULT_LOG_TYPE InetNoLog
# define DEFAULT_LOG_FILE_DIRECTORY_W L"%systemroot%\\system32"
# define DEFAULT_LOG_FILE_TRUNCATE_SIZE MAX_FILE_TRUNCATION_SIZE
# define DEFAULT_LOG_FILE_PERIOD InetLogNoPeriod
# define DEFAULT_LOG_FILE_FORMAT InternetStdLogFormat
# define DEFAULT_LOG_SQL_DATASOURCE_W L"InternetDb"
# define DEFAULT_LOG_SQL_TABLE_W L"InternetLog"
# define DEFAULT_LOG_SQL_USER_NAME_W L"InternetAdmin"
# define DEFAULT_LOG_SQL_PASSWORD_W L"sqllog"
# define DEFAULT_INET_LOG_FILE_BATCH_SIZE (64*1024) // 64 KB
# define DEFAULT_INET_LOG_FILE_FLUSH_INTERVAL (5*60) // 5 minutes
# define MIN_INET_LOG_FILE_BATCH_SIZE (1024) // 1 KB
# define MIN_INET_LOG_FILE_FLUSH_INTERVAL (1*60) // 1 minute
DWORD g_cbInetLogFileBatching = DEFAULT_INET_LOG_FILE_BATCH_SIZE;
DWORD g_cmsecIlogFileFlushInterval =
(DEFAULT_INET_LOG_FILE_FLUSH_INTERVAL * 1000);
# define PSZ_ERROR_INVALID_LOG_HANDLE_A "Error Invalid Log Handle"
# define PSZ_ERROR_INVALID_LOG_HANDLE_W L"Error Invalid Log Handle"
# define LEN_ERROR_INVALID_LOG_HANDLE_A sizeof(PSZ_ERROR_INVALID_LOG_HANDLE_A)
# define LEN_ERROR_INVALID_LOG_HANDLE_W sizeof(PSZ_ERROR_INVALID_LOG_HANDLE_W)
/************************************************************
* Functions
************************************************************/
static DWORD
ReadRegistryStringW(
IN HKEY hkeyReg,
IN LPCWSTR pszValueName,
IN LPWSTR pszBuffer,
IN DWORD cchBuffer,
IN LPWSTR pszDefaultValue);
static DWORD
ReadIntervalFromRegW(IN HKEY hkey,
IN LPCWSTR pszIntervalKeyName,
IN DWORD dwDefault,
IN DWORD dwMinValue = 0
);
static DWORD
OpenInetLogConfigRegKey(
IN LPCWSTR pszServiceName,
IN LPCWSTR pszSvcRegParamKey,
IN HKEY * phKeyReg);
DWORD
TsInitializeInetLogA( IN LPCSTR pszRegParamKey)
/*++
TsInitializeInetLog()
Description:
This function initializes the InetLog module with the common parameters
being read from the specified registry.
It also initializes all other global information for this logging module
Arguments:
pszRegParamKey pointer to Unicode string containing the
registry key name for common Parameters
for the logging module.
Returns:
Win32 Error code. NO_ERROR on success.
--*/
{
DWORD dwError;
WCHAR rgwchRegParamKey[MAX_PATH + 1];
DWORD cch;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Entering TsInitializeInetLogA( %s)\n",
pszRegParamKey));
}
//
// Convert ANSI strings to UNICODE strings to call TsInitializeInetLogW()
//
cch = MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pszRegParamKey,
-1,
rgwchRegParamKey,
sizeof(rgwchRegParamKey) / sizeof(WCHAR)
);
if ( cch != 0) {
dwError = TsInitializeInetLogW( rgwchRegParamKey);
} else {
dwError = GetLastError();
}
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Leaving TsInitializeInetLogA( %s) with",
pszRegParamKey));
}
return ( dwError);
} // TsInitializeInetLogA()
DWORD
TsInitializeInetLogW( IN LPCWSTR pszRegParamKey)
{
DWORD dwError;
HKEY hKey = NULL;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Entering TsInitializeInetLogW( %S)\n",
pszRegParamKey));
}
//
// Read the common parameters and initialize the global data for logging
// module.
//
// set default values for the parameters
g_cbInetLogFileBatching = DEFAULT_INET_LOG_FILE_BATCH_SIZE;
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
pszRegParamKey,
0,
KEY_ALL_ACCESS,
&hKey);
if ( dwError == NO_ERROR) {
//
// Read the size to be used for log file buffering.
//
g_cbInetLogFileBatching =
ReadRegistryDwordW(hKey,
PSZ_LOG_FILE_BATCH_SIZE_W,
DEFAULT_INET_LOG_FILE_BATCH_SIZE);
// special value of 0 means that always log record will be written
// immediately. no buffering will occur.
if ( g_cbInetLogFileBatching < MIN_INET_LOG_FILE_BATCH_SIZE) {
g_cbInetLogFileBatching = MIN_INET_LOG_FILE_BATCH_SIZE;
}
g_cmsecIlogFileFlushInterval =
ReadIntervalFromRegW(hKey,
PSZ_LOG_FILE_FLUSH_INTERVAL_W,
DEFAULT_INET_LOG_FILE_FLUSH_INTERVAL,
MIN_INET_LOG_FILE_FLUSH_INTERVAL);
RegCloseKey( hKey);
}
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Leaving TsInitializeInetLogW( %S) with",
pszRegParamKey));
}
if ( dwError == NO_ERROR) {
dwError = ILOG_FILE::Initialize();
}
return ( dwError);
} // TsInitializeInetLogW()
DWORD
TsCleanupInetLog(VOID)
{
DWORD dwError;
dwError = ILOG_FILE::Cleanup();
return (NO_ERROR);
} // TsCleanupInetLog()
INETLOG_HANDLE
TsCreateInetLogA(
IN LPCSTR pszServiceName,
IN EVENT_LOG * pEventLog,
IN LPCSTR pszSvcRegParamKey // Optional
)
/*++
See Documentation in TsCreateInetLogW()
--*/
{
INETLOG_HANDLE hInetLog = INVALID_INETLOG_HANDLE_VALUE;
UNICODE_STRING ustrServiceName;
UNICODE_STRING ustrSvcRegParamKey;
WCHAR rgwchServiceName[MAX_PATH + 1];
WCHAR rgwchSvcRegParamKey[MAX_PATH + 1];
DWORD cch;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Entering TsCreateInetLogA( %s, %s)\n",
pszServiceName, pszSvcRegParamKey));
}
//
// Convert ANSI strings to UNICODE strings to call TsCreateInetLogW()
//
cch = MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pszServiceName,
-1,
rgwchServiceName,
sizeof(rgwchServiceName) / sizeof(WCHAR)
);
if ( cch != 0) {
LPCWSTR pwszSvcRegKey = NULL;
if ( pszSvcRegParamKey != NULL) {
// Convert the SvcRegParamKey.
cch = MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
pszSvcRegParamKey,
-1,
rgwchSvcRegParamKey,
sizeof(rgwchSvcRegParamKey)/sizeof(WCHAR)
);
pwszSvcRegKey = rgwchSvcRegParamKey;
}
if ( cch != 0) {
hInetLog = TsCreateInetLogW( rgwchServiceName,
pEventLog,
pwszSvcRegKey);
}
}
// if ( cch == 0) {
// Error is available from GetLastError();
// }
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Leaving TsCreateInetLogA( %s, %s) with"
" LogHandle= %08x\n",
pszServiceName, pszSvcRegParamKey, hInetLog));
}
return ( hInetLog);
} // TsCreateInetLogA()
INETLOG_HANDLE
TsCreateInetLogW(
IN LPCWSTR pszServiceName,
IN EVENT_LOG * pEventLog,
IN LPCWSTR pszSvcRegParamKey // Optional
)
/*++
TsCreateInetLogW()
Description:
This function creates a InetLog handle for a specified service.
It loads parameters related to logging type, information and format
from registry using the key provided.
If the pszSvcRegParamKey is NULL, then this functions uses the
registry entry provided by
HKEY_LOCAL_MACHINE\System\CurrentControSet\pszServiceName\Parameters\...
The logging related parameters in registry configure the type of log,
structure of log files and records and fields to log.
Arguments:
pszServiceName pointer to Unicode string containing service name.
pEventLog Event log to log errors to
pszSvcRegParamKey pointer to Unicode string containing the
registry key name for Parameters of the service.
Returns:
On success it returns a valid INETLOG_HANDLE.
On failure it returns an INVALID_INETLOG_HANDLE_VALUE.
Use GetLastError() for detailed error.
--*/
{
INETLOG_CONFIGURATIONW ilConfig;
INETLOG_HANDLE hInetLog = INVALID_INETLOG_HANDLE_VALUE;
ASSERT( pszServiceName != NULL);
ASSERT( pEventLog != NULL);
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Entering TsCreateInetLogW( %ws, %ws).\n",
pszServiceName,
pszSvcRegParamKey));
}
//
// Read the logging configuration for given service
//
memset( &ilConfig, 0, sizeof( ilConfig));
if ( !TsReadInetLogConfigurationW( pszServiceName,
pszSvcRegParamKey,
&ilConfig)) {
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" TsReadInetLogConfigurationW( %ws, %ws) failed.\n",
pszServiceName, pszSvcRegParamKey));
}
DBG_ASSERT( hInetLog == INVALID_INETLOG_HANDLE_VALUE);
} else {
PINETLOG_CONTEXT pilContext = NULL;
PINET_BASIC_LOG piLog = TsCreateInetBasicLog(pszServiceName,
pEventLog,
&ilConfig);
// Error from TsCreateInetBasicLog() is ignored.
// It should have set an event log entry or equivalent already.
pilContext = new INETLOG_CONTEXT( pszServiceName, pEventLog, piLog);
if ( pilContext == NULL) {
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Not enough memory for InetLog Context\n"));
}
// Log an event about failure
DBG_ASSERT(pEventLog != NULL);
pEventLog->LogEvent(INET_SVC_LOG_CREATION_FAILED,
0,
(const CHAR **) NULL,
ERROR_NOT_ENOUGH_MEMORY);
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
if ( piLog != NULL) {
delete piLog;
piLog = NULL;
}
}
hInetLog = (INETLOG_HANDLE ) pilContext;
} // valid config found
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Returning InetLogHandle(%08x) from TsCreateInetLogW()\n",
hInetLog));
}
return ( hInetLog);
} // TsCreateInetLogW()
BOOL
TsCloseInetLog( IN OUT INETLOG_HANDLE hInetLog)
/*++
TsCloseInetLog()
Description:
This functions closes the InetLog handle. It closes any open files or
open handles maintained internally. It also cleans up other state
information present.
Arguments:
hInetLog handle for InetLog object, that needs to be closed.
Returns:
TRUE on success and FALSE on failure.
Detailed error message can be obtained using GetLastError().
--*/
{
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Entering TsCloseInetLog( %08x) \n",
hInetLog));
}
if ( hInetLog != INVALID_INETLOG_HANDLE_VALUE) {
PINETLOG_CONTEXT pilContext = (PINETLOG_CONTEXT ) hInetLog;
BOOL fInUse = pilContext->IsInUse();
if ( !fInUse) {
delete pilContext;
} else {
// The request log object is busy.
SetLastError( ERROR_BUSY);
}
} else {
SetLastError( ERROR_INVALID_PARAMETER);
}
return ( hInetLog != INVALID_INETLOG_HANDLE_VALUE);
} // TsCloseInetLog()
BOOL
TsGetLogInformation(
IN INETLOG_HANDLE hInetLog,
IN INETLOG_INFO_OPTION IlOptionName,
IN PBYTE pBuffer,
IN LPDWORD lpdwBuffer
)
/*++
TsGetLogInformation()
Description:
This functions checks and reports information requested about logging
handle in use. This function should be called with a valid
InetLogHandle.
Mainly this information can be used for optimizing the callers.
For Example: If Logging is not turned on, then TsLogInformation need
not be called.
Arguments:
hInetLog handle for InetLog object, about which inquiry is made.
IlOptionName Log Information Option indicating what info is required.
pBuffer pointer to buffer in which the data is copied into at return.
lpdwBuffer pointer to DWORD; contains size of buffer on call and
contains the count of bytes written on return.
Returns:
TRUE on success and FALSE on failure.
Detailed error message can be obtained using GetLastError().
--*/
{
BOOL fReturn = FALSE;
PINETLOG_CONTEXT pilContext = (PINETLOG_CONTEXT ) hInetLog;
PILREF_LOG pilRef;
PINET_BASIC_LOG piLog;
if ( hInetLog == INVALID_INETLOG_HANDLE_VALUE || lpdwBuffer == NULL) {
SetLastError( ERROR_INVALID_PARAMETER);
return (FALSE);
}
IF_DEBUG(INETLOG) {
DBGPRINTF(( DBG_CONTEXT,
"TsGetLogInformation( %08x, %u, %08x, %08x(%u))\n",
hInetLog, IlOptionName, pBuffer, lpdwBuffer, *lpdwBuffer));
}
pilRef= pilContext->AcquireCurrentPinetForRead();
piLog = pilRef->piLog;
//
// Process each option separately.
// For each option, check the size of buffer sent in.
// If the buffer is insufficient, sets ERROR_INSUFFICIENT_BUFFER as error
// Next check if the option is valid option and proceed
// to get and store the option in the buffer supplied.
//
switch ( IlOptionName) {
case IlIsLoggingOn:
// This is a boolean value supported by all log types
if ( *lpdwBuffer < sizeof(BOOL)) {
SetLastError( ERROR_INSUFFICIENT_BUFFER);
} else {
//
// return that logging is off, whenever there is no log object
// or the log type is InetNoLog.
//
*(BOOL *)pBuffer =
( (piLog == NULL || piLog->QueryLogType() == InetNoLog) ?
FALSE : TRUE);
fReturn = TRUE;
}
*lpdwBuffer = sizeof( BOOL);
break;
case IlLogType:
// The value is INETLOG_TYPE used by logging object.
if ( *lpdwBuffer < sizeof( INETLOG_TYPE)) {
SetLastError( ERROR_INSUFFICIENT_BUFFER);
} else {
*(INETLOG_TYPE *)pBuffer =
(( piLog == NULL) ? InetLogInvalidType : piLog->QueryLogType());
fReturn = TRUE;
}
*lpdwBuffer = sizeof(INETLOG_TYPE);
break;
case IlLogFilePeriod:
// This option is supported only for InetLogToFile log type.
if ( piLog == NULL || piLog->QueryLogType() != InetLogToFile) {
SetLastError( ERROR_INVALID_PARAMETER);
} else if ( *lpdwBuffer < sizeof(INETLOG_PERIOD)) {
SetLastError( ERROR_INSUFFICIENT_BUFFER);
} else {
// cast PINET_BASIC_LOG to PINET_FILE_LOG since
// it is InetLogToFile Log type
*(INETLOG_PERIOD *) pBuffer =
((PINET_FILE_LOG)piLog)->QueryLogPeriod();
fReturn = TRUE;
}
*lpdwBuffer = sizeof(INETLOG_PERIOD);
break;
case IlConfigurationW:
{
PINETLOG_CONFIGURATIONW pConfig =
(PINETLOG_CONFIGURATIONW ) pBuffer;
if ( *lpdwBuffer < sizeof( INETLOG_CONFIGURATIONW)) {
SetLastError( ERROR_INSUFFICIENT_BUFFER);
} else if ( piLog == NULL) {
// invalid log object
RtlZeroMemory( pConfig, sizeof( *pConfig));
pConfig->inetLogType = InetLogInvalidType;
fReturn = TRUE; // we succeed by returning invalid log type
} else {
fReturn = piLog->GetConfig((PINETLOG_CONFIGURATIONW ) pBuffer);
}
*lpdwBuffer = sizeof(INETLOG_CONFIGURATIONW);
break;
} // case IlConfigurationW
default:
SetLastError( ERROR_INVALID_PARAMETER);
break;
} // switch()
// Release the ref log object
pilContext->ReleasePinet( pilRef);
return ( fReturn);
} // TsGetLogInformation()
DWORD
TsLogInformationA(
IN OUT INETLOG_HANDLE hInetLog,
IN const INETLOG_INFORMATIONA * pInetLogInfo,
OUT LPSTR pszErrorMessage,
IN OUT LPDWORD lpcchErrorMessage
)
/*++
See comments below in TsLogInformationW()
NOTE:
This function is similar to TsLogInformationW() except that this uses
CHARs instead of WCHARs. If you update one of the functions,
update the other also.
--*/
{
DWORD dwError = NO_ERROR;
PINETLOG_CONTEXT pilContext = (PINETLOG_CONTEXT ) hInetLog;
PILREF_LOG pilRef;
PINET_BASIC_LOG piLog;
DBG_ASSERT( hInetLog != INVALID_INETLOG_HANDLE_VALUE &&
pInetLogInfo != NULL);
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Entering TsLogInformationA( %08x, %08x) \n",
hInetLog, pInetLogInfo));
}
pilRef= pilContext->AcquireCurrentPinetForRead();
piLog = pilRef->piLog;
if ( piLog == NULL ) {
DBG_ASSERT( pilContext->QueryEventLog() != NULL);
// Log an event indicating that log object is invalid.
pilContext->QueryEventLog()->LogEvent(
INET_SVC_LOG_INFORMATION_FAILED,
0,
(const char ** ) NULL,
0);
dwError = ERROR_INVALID_PARAMETER;
// store error message if there is space
if ( pszErrorMessage != NULL && lpcchErrorMessage != NULL) {
DWORD dwErrorLen = InetLogMin(*lpcchErrorMessage,
LEN_ERROR_INVALID_LOG_HANDLE_A);
lstrcpynA( pszErrorMessage, PSZ_ERROR_INVALID_LOG_HANDLE_A,
dwErrorLen);
*lpcchErrorMessage = dwErrorLen;
}
} else {
dwError = piLog->LogInformation( pInetLogInfo,
pszErrorMessage,
lpcchErrorMessage);
}
pilContext->ReleasePinet( pilRef);
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Leaving TsLogInformationA( %08x) with dwError = %d.\n",
hInetLog, dwError));
}
return ( dwError);
} // TsLogInformationA()
DWORD
TsLogInformationW(
IN OUT INETLOG_HANDLE hInetLog,
IN const INETLOG_INFORMATIONW * pInetLogInfo,
OUT LPWSTR pszErrorMessage,
IN OUT LPDWORD lpcchErrorMessage
)
/*++
Description:
This function logs information provided to the destination as
configured when the InetLog handle was created.
This is the core function which does the real work of writing log records.
Arguments:
hInetLog Handle for InetLog object. This contains the logging
configuration and state information.
pInetLogInfo pointer to InetLogInformation object, that contains the
data to be written as a single log record.
pszErrorMessage - pointer to error buffer that on
failure may contain the error message
lpcchErrorMessage - pointer to DWORD containing the count of chars
that can be stored in the buffer pszErrorMessage.
On return contains the number of chars returned if there
is a failure and error message is generated.
Returns:
TRUE on success and FALSE if failure.
Detailed error code on failure can be obtained by calling GetLastError().
NOTE:
This function is similar to TsLogInformationA() except that it uses
CHARs instead of WCHARs. If you update one of the functions,
update the other also.
--*/
{
DWORD dwError = NO_ERROR;
PINETLOG_CONTEXT pilContext = (PINETLOG_CONTEXT ) hInetLog;
PILREF_LOG pilRef;
PINET_BASIC_LOG piLog;
DBG_ASSERT( hInetLog != INVALID_INETLOG_HANDLE_VALUE &&
pInetLogInfo != NULL);
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Entering TsLogInformationW( %08x, %08x) \n",
hInetLog, pInetLogInfo));
}
pilRef= pilContext->AcquireCurrentPinetForRead();
piLog = pilRef->piLog;
if ( piLog == NULL) {
DBG_ASSERT( pilContext->QueryEventLog() != NULL);
// Log an event indicating that log object is invalid.
pilContext->QueryEventLog()->LogEvent(
INET_SVC_LOG_INFORMATION_FAILED,
0,
(const char ** ) NULL,
0);
dwError = ERROR_INVALID_PARAMETER;
// store error message if there is space
if ( pszErrorMessage != NULL && lpcchErrorMessage != NULL) {
DWORD dwErrorLen = InetLogMin(*lpcchErrorMessage,
LEN_ERROR_INVALID_LOG_HANDLE_W);
lstrcpynW( pszErrorMessage, PSZ_ERROR_INVALID_LOG_HANDLE_W,
dwErrorLen);
*lpcchErrorMessage = dwErrorLen;
}
} else {
dwError = piLog->LogInformation( pInetLogInfo,
pszErrorMessage,
lpcchErrorMessage);
}
pilContext->ReleasePinet( pilRef);
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Leaving TsLogInformationW( %08x) with dwError = %d.\n",
hInetLog, dwError));
}
return ( dwError);
} // TsLogInformationW()
# define PSZ_ERROR_INVALID_LOG_CALL_A "Error Invalid Call"
# define LEN_PSZ_ERROR_INVALID_LOG_CALL_A sizeof(PSZ_ERROR_INVALID_LOG_CALL_A)
DWORD
TsModifyLogConfigurationA(
IN OUT INETLOG_HANDLE hInetLog,
IN LPCSTR pszSvcRegParamKey,
IN const INETLOG_CONFIGURATIONA * pInetLogConfig,
OUT LPSTR pszErrorMessage,
IN OUT LPDWORD lpcchErrorMessage
)
/*++
This function is used for dynamically changing the log configuration, given
a new log configuration and inetlog handle.
The function updates the registry if new logging object is
successfully created.
This function applies new configuration to dynamically change the manner
logging is done or destination of logging.
Arguments:
hInetLog handle for InetLog object, that needs to be modified.
pszSvcRegParamKey pointer to Unicode string containing the
registry key name for Parameters of the service.
pInetLogConfig the new log configuration to be applied on this log handle.
pszErrorMessage - pointer to error buffer that on
failure may contain the error message
lpcchErrorMessage - pointer to DWORD containing the count of chars
that can be stored in the buffer pszErrorMessage.
On return contains the number of chars returned if there
is a failure and error message is generated.
Returns:
TRUE on success and FALSE if there is any error.
Atmost only one write is permitted to modify information associated with
a logging handle. It is caller's responsibility to ensure the proper use.
--*/
{
//
// For the present, no one uses this API. So it is not yet defined.
//
if ( pszErrorMessage != NULL && lpcchErrorMessage != NULL) {
DWORD dwErrorLen = InetLogMin(*lpcchErrorMessage,
LEN_PSZ_ERROR_INVALID_LOG_CALL_A);
lstrcpynA( pszErrorMessage, PSZ_ERROR_INVALID_LOG_CALL_A,
dwErrorLen);
*lpcchErrorMessage = dwErrorLen;
}
return ( ERROR_CALL_NOT_IMPLEMENTED);
} // TsModifyLogConfigurationA()
DWORD
TsModifyLogConfigurationW(
IN OUT INETLOG_HANDLE hInetLog,
IN LPCWSTR pszSvcRegParamKey,
IN const INETLOG_CONFIGURATIONW * pInetLogConfig,
OUT LPWSTR pszErrorMessage,
IN OUT LPDWORD lpcchErrorMessage
)
/*++
This function is used for dynamically changing the log configuration, given
a new log configuration and inetlog handle.
The function updates the registry if new logging object is
successfully created.
This function applies new configuration to dynamically change the manner
logging is done or destination of logging.
Arguments:
hInetLog handle for InetLog object, that needs to be modified.
pszSvcRegParamKey pointer to Unicode string containing the
registry key name for Parameters of the service.
pInetLogConfig the new log configuration to be applied on this log handle.
pszErrorMessage - pointer to error buffer that on
failure may contain the error message
lpcchErrorMessage - pointer to DWORD containing the count of chars
that can be stored in the buffer pszErrorMessage.
On return contains the number of chars returned if there
is a failure and error message is generated.
Returns:
TRUE on success and FALSE if there is any error.
Atmost only one write is permitted to modify information associated with
a logging handle. It is caller's responsibility to ensure the proper use.
--*/
{
BOOL fReturn = FALSE;
DWORD dwReturn = NO_ERROR;
PINETLOG_CONTEXT pilContext = (PINETLOG_CONTEXT ) hInetLog;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" TsModifyLogConfig(hInetLog=%08x, Reg=%S, config=%08x)\n",
hInetLog,
pszSvcRegParamKey,
pInetLogConfig));
DBG_CODE( PrintInetLogConfigurationW( pInetLogConfig));
}
if (hInetLog == INVALID_INETLOG_HANDLE_VALUE ||
pInetLogConfig == NULL) {
SetLastError( ERROR_INVALID_PARAMETER);
return (FALSE);
}
//
// If this is not a NTS, don't allow SQL logging
//
if ( (pInetLogConfig->inetLogType == InetLogToSql) &&
!TsIsNtServer() ) {
DBGPRINTF( ( DBG_CONTEXT,
"SQL logging not allowed in NTW version\n"));
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
//
// 1. Create a new log object using the configuration information
// supplied. Obtain eventlog and service name from old log object.
//
// We can optimize this path by checking and creating a new
// log object only when absolutely required. NYI
// Till then, always create a new object (simple).
//
PINET_BASIC_LOG piLogNew;
piLogNew = TsCreateInetBasicLog(pilContext->QueryServiceName(),
pilContext->QueryEventLog(),
pInetLogConfig);
if ( piLogNew != NULL) {
//
// 2. Set the new values in registry
//
fReturn = TsWriteInetLogConfigurationW( pilContext->QueryServiceName(),
pszSvcRegParamKey,
pilContext->QueryEventLog(),
pInetLogConfig);
if ( fReturn) {
//
// 3. Set the new log object in InetLogContext.
//
fReturn = pilContext->SetNewPinetLog( piLogNew);
} else {
// Delete this object, since we cannot update registry...
delete piLogNew;
}
}
if ( !fReturn) {
// we could not create a new log structure, because of some error.
dwReturn = GetLastError();
IF_DEBUG( INETLOG) {
DBGPRINTF(( DBG_CONTEXT,
" Error %u. Unable to create new log object\n",
dwReturn));
}
if ( pszErrorMessage != NULL && lpcchErrorMessage != NULL) {
//
// we should probably find out exact error message
// BUGBUG
//
lstrcpyW( pszErrorMessage, L"");
*lpcchErrorMessage = 0;
}
}
return ( dwReturn);
} // TsModifyLogConfigurationW()
BOOL
TsReadInetLogConfigurationA(
IN LPCSTR pszServiceName,
IN LPCSTR pszSvcRegParamKey, // Optional
OUT PINETLOG_CONFIGURATIONA pInetLogConfiguration
)
/*++
See comments below in TsReadInetLogConfigurationW()
History:
MuraliK 2-Feb-1995
--*/
{
//
// For the present, no one uses this API. So it is not yet defined.
//
SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
return ( FALSE);
} // TsReadInetLogConfigurationA()
BOOL
TsReadInetLogConfigurationW(
IN LPCWSTR pszServiceName,
IN LPCWSTR pszSvcRegParamKey, // Optional
OUT PINETLOG_CONFIGURATIONW pilConfig
)
/*++
Description:
This function reads the INETLOG configuration information
for given service name. The configuration information may be stored
in registry.
If the pszSvcRegParamKey is NULL, then this functions uses the
registry entry provided by
HKEY_LOCAL_MACHINE\System\CurrentControSet\pszServiceName\Parameters\...
Arguments:
pszServiceName pointer to Unicode string containing service name.
pszSvcRegParamKey pointer to Unicode string containing the
registry key name for Parameters of the service.
pilConfig pointer to INETLOG_CONFIGURATION structure which
on successful read contains the data read.
Returns:
TRUE on success and FALSE if failure.
Detailed error code can be obtained using GetLastError()
--*/
{
HKEY hkeyInetLog = NULL;
DWORD dwError = NO_ERROR;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Entering TsReadInetLogConfiguration( %ws, %ws, %08x)\n",
pszServiceName, pszSvcRegParamKey,
pilConfig));
}
ASSERT( pszServiceName != NULL && pilConfig != NULL);
dwError = OpenInetLogConfigRegKey( pszServiceName,
pszSvcRegParamKey,
&hkeyInetLog);
//
// Init Inet Log Config to default values.
//
memset( (PVOID ) pilConfig, 0, sizeof(INETLOG_CONFIGURATIONW));
pilConfig->inetLogType = InetNoLog;
if ( dwError == NO_ERROR) {
//
// Read data from registry as relevant for logging configuration.
//
// Read LogType
pilConfig->inetLogType =
(INETLOG_TYPE ) ReadRegistryDwordW( hkeyInetLog,
PSZ_LOG_TYPE_W,
DEFAULT_LOG_TYPE);
switch( pilConfig->inetLogType) {
case InetNoLog:
// No addl parameter to be read.
break;
case InetLogToFile:
{
INETLOG_PERIOD ilPeriod;
//
// Read the logging period.
//
ilPeriod =
(INETLOG_PERIOD )ReadRegistryDwordW(hkeyInetLog,
PSZ_LOG_FILE_PERIOD_W,
DEFAULT_LOG_FILE_PERIOD);
DBGPRINTF( ( DBG_CONTEXT, " Log File Period Read = %d\n",
ilPeriod));
pilConfig->u.logFile.ilFormat =
((ReadRegistryDwordW(hkeyInetLog, PSZ_LOG_FILE_FORMAT_W,
DEFAULT_LOG_FILE_FORMAT)==INET_LOG_FORMAT_INTERNET_STD)?
InternetStdLogFormat:NCSALogFormat);
DBGPRINTF( ( DBG_CONTEXT, " Log Format = %d\n",
pilConfig->u.logFile.ilFormat));
//
// Validate the parameter read
//
if ( ilPeriod > InetLogYearly) {
ilPeriod = DEFAULT_LOG_FILE_PERIOD;
}
pilConfig->u.logFile.ilPeriod = ilPeriod;
pilConfig->u.logFile.cbSizeForTruncation =
ReadRegistryDwordW( hkeyInetLog,
PSZ_LOG_FILE_TRUNCATE_SIZE_W,
DEFAULT_LOG_FILE_TRUNCATE_SIZE);
dwError = ReadRegistryStringW( hkeyInetLog,
PSZ_LOG_FILE_DIRECTORY_W,
pilConfig->
u.logFile.rgchLogFileDirectory,
MAX_PATH,
DEFAULT_LOG_FILE_DIRECTORY_W);
if ( dwError != NO_ERROR) {
break;
}
break;
} // case InetLogToFile
case InetLogToSql:
//
// We do not allow sql logging in the PWS version
//
if ( !TsIsNtServer( ) ) {
DBGPRINTF( ( DBG_CONTEXT,
"SQL Logging not allowed in NTW version\n"));
pilConfig->inetLogType = InetNoLog;
break;
}
// read the data source name
dwError = ReadRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_DATASOURCE_W,
pilConfig->u.logSql.rgchDataSource,
MAX_DATABASE_NAME_LEN,
DEFAULT_LOG_SQL_DATASOURCE_W);
if ( dwError != NO_ERROR) {
break;
}
// read the table into which log records have to be written
dwError = ReadRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_TABLE_W,
pilConfig->u.logSql.rgchTableName,
MAX_TABLE_NAME_LEN,
DEFAULT_LOG_SQL_TABLE_W);
if ( dwError != NO_ERROR) {
break;
}
// read username to be used for logging.
dwError = ReadRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_USER_NAME_W,
pilConfig->u.logSql.rgchUserName,
MAX_USER_NAME_LEN,
DEFAULT_LOG_SQL_USER_NAME_W);
if ( dwError != NO_ERROR) {
break;
}
// read password to be used for sql logging.
dwError = ReadRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_PASSWORD_W,
pilConfig->u.logSql.rgchPassword,
MAX_PASSWORD_LEN,
DEFAULT_LOG_SQL_PASSWORD_W);
if ( dwError != NO_ERROR) {
break;
}
break;
default:
ASSERT( FALSE);
DBGPRINTF( ( DBG_CONTEXT,
" Invalid Log Type( %d) found."
" Resetting to be NoLogging\n",
pilConfig->inetLogType));
pilConfig->inetLogType = InetNoLog;
break;
} // switch()
//
// Close Registry
//
LONG lError = RegCloseKey( hkeyInetLog);
DBG_REQUIRE( lError == NO_ERROR);
} // if ( dwError == NO_ERROR)
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
"Return from TsReadInetLogConfigurationW() with %d."
" Error = %d.\n",
dwError == NO_ERROR,
dwError));
DBG_CODE( PrintInetLogConfigurationW( pilConfig));
}
SetLastError( dwError);
return ( dwError == NO_ERROR);
} // TsReadInetLogConfigurationW()
BOOL
TsWriteInetLogConfigurationA(
IN LPCSTR pszServiceName,
IN LPCSTR pszSvcRegParamKey, // Optional
IN EVENT_LOG * pEventLog,
IN const INETLOG_CONFIGURATIONA * pilConfig
)
/*++
See comments below in TsWriteInetLogConfigurationW()
History:
MuraliK 2-Feb-1995
--*/
{
//
// For the present, no one uses this API. So it is not yet defined.
//
SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
return ( FALSE);
} // TsWriteInetLogConfigurationA()
BOOL
TsWriteInetLogConfigurationW(
IN LPCWSTR pszServiceName,
IN LPCWSTR pszSvcRegParamKey,
IN EVENT_LOG * pEventLog,
IN const INETLOG_CONFIGURATIONW * pilConfig
)
/*++
TsWriteInetLogConfiguration()
Description:
This function writes the INETLOG configuration information
for given service name. The configuration information may be stored
in registry.
If the pszSvcRegParamKey is NULL, then this functions uses the
registry entry provided by
HKEY_LOCAL_MACHINE\System\CurrentControSet\pszServiceName\Parameters\...
Arguments:
pszServiceName pointer to Unicode string containing service name.
pszSvcRegParamKey pointer to Unicode string containing the
registry key name for Parameters of the service.
pEventLog pointer to event log structure to write out
any events on error.
pilConfig pointer to INETLOG_CONFIGURATION structure that
contains the data to be written.
Returns:
TRUE on success and FALSE if failure.
Detailed error code can be obtained using GetLastError()
--*/
{
DWORD dwError;
BOOL fReturn = FALSE;
HKEY hkeyInetLog;
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Entering TsWriteInetLogConfiguration( %ws, %ws, %08x)\n",
pszServiceName,
pszSvcRegParamKey,
pilConfig));
DBG_CODE( PrintInetLogConfigurationW( pilConfig));
}
ASSERT( pilConfig != NULL && pszServiceName != NULL && pEventLog != NULL);
dwError = OpenInetLogConfigRegKey( pszServiceName, pszSvcRegParamKey,
&hkeyInetLog);
//
// Write the Inet Log Type
//
if ( dwError == NO_ERROR &&
((dwError = WriteRegistryDwordW( hkeyInetLog, PSZ_LOG_TYPE_W,
(DWORD ) pilConfig->inetLogType))
== NO_ERROR)) {
switch ( pilConfig->inetLogType) {
case InetNoLog:
break; // Nothing to be written
case InetLogToFile:
// Check Validity of the path supplied.
if ( (dwError = CheckIfPathIsDirectory(pilConfig->u.logFile.
rgchLogFileDirectory,
pEventLog))
!= NO_ERROR) {
break;
}
//
// Write Logging Period to file
//
dwError = WriteRegistryDwordW(hkeyInetLog,
PSZ_LOG_FILE_PERIOD_W,
(DWORD )pilConfig->
u.logFile.ilPeriod);
if ( dwError != NO_ERROR) {
break;
}
//
// Write Logging format
//
dwError = WriteRegistryDwordW(hkeyInetLog,
PSZ_LOG_FILE_FORMAT_W,
(DWORD)(pilConfig->u.logFile.ilFormat
==InternetStdLogFormat)?
INET_LOG_FORMAT_INTERNET_STD:
INET_LOG_FORMAT_NCSA);
if ( dwError != NO_ERROR) {
break;
}
//
// write the size of for log and the log file directory
//
if ( pilConfig->u.logFile.cbSizeForTruncation != 0) {
dwError = WriteRegistryDwordW( hkeyInetLog,
PSZ_LOG_FILE_TRUNCATE_SIZE_W,
pilConfig->
u.logFile.cbSizeForTruncation);
}
if ( dwError == NO_ERROR) {
//
// write the log file directory
//
DWORD cbLen = lstrlenW(pilConfig->
u.logFile.rgchLogFileDirectory);
DBG_ASSERT( cbLen > 0);
dwError = WriteRegistryStringW(hkeyInetLog,
PSZ_LOG_FILE_DIRECTORY_W,
pilConfig->u.logFile.
rgchLogFileDirectory,
cbLen * sizeof( WCHAR),
REG_EXPAND_SZ);
}
break;
case InetLogToSql: {
//
// write the data source, table name, username and password.
//
// While calculating the length always include terminating null.
//
DWORD cbLen;
// Without ODBC the LogToSql will not work, So check for same.
if ( (dwError = CheckAndLoadOdbc(pEventLog)) != NO_ERROR) {
break;
}
cbLen = lstrlenW( pilConfig->u.logSql.rgchDataSource) ;
dwError = WriteRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_DATASOURCE_W,
pilConfig->
u.logSql.rgchDataSource,
(1 + cbLen) * sizeof(WCHAR),
REG_SZ);
if ( dwError != NO_ERROR) {
break;
}
cbLen = lstrlenW( pilConfig->u.logSql.rgchTableName);
dwError = WriteRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_TABLE_W,
pilConfig->u.
logSql.rgchTableName,
(1+cbLen)*sizeof(WCHAR),
REG_SZ);
if ( dwError != NO_ERROR) {
break;
}
cbLen =lstrlenW( pilConfig->u.logSql.rgchUserName);
dwError = WriteRegistryStringW(hkeyInetLog,
PSZ_LOG_SQL_USER_NAME_W,
pilConfig->u.
logSql.rgchUserName,
(1 + cbLen)*sizeof(WCHAR),
REG_SZ);
if ( dwError != NO_ERROR) {
break;
}
cbLen = lstrlenW( pilConfig->u.logSql.rgchPassword);
dwError = WriteRegistryStringW( hkeyInetLog,
PSZ_LOG_SQL_PASSWORD_W,
pilConfig->u.
logSql.rgchPassword,
(1 +cbLen) * sizeof(WCHAR),
REG_SZ);
if ( dwError != NO_ERROR) {
break;
}
break;
} // case InetLogToSql:
default:
DBGPRINTF( ( DBG_CONTEXT, " Invalid InetLog Type %d.\n",
pilConfig->inetLogType));
ASSERT( FALSE);
dwError = ERROR_INVALID_PARAMETER;
break;
} // switch ()
DBG_REQUIRE(RegCloseKey( hkeyInetLog) == NO_ERROR);
} // registry key opened.
if ( dwError != NO_ERROR) {
SetLastError( dwError);
fReturn = FALSE;
} else {
fReturn = TRUE;
}
IF_DEBUG( INETLOG) {
DBGPRINTF( ( DBG_CONTEXT,
" Leaving TsWriteInetLogConfiguration() with %d."
" Error = %d\n",
fReturn,
dwError));
SetLastError( dwError);
}
return ( fReturn);
} // TsWriteInetLogConfiguration()
/**************************************************
* Debugging Functions
**************************************************/
# if DBG
VOID PrintInetLogInformationW( const INETLOG_INFORMATIONW * piLogInfo)
{
DBGPRINTF( ( DBG_CONTEXT,
" Printing InetLogInformation ( %08x)\n",
piLogInfo));
if ( piLogInfo != NULL) {
char rgchBytesSent[32];
char rgchBytesRecvd[32];
DWORD dwError;
DBGPRINTF( ( DBG_CONTEXT,
"ClientHost = %ws; ClientUser = %ws; Password = %08x;"
" ServerIpAddress=%ws\n",
piLogInfo->pszClientHostName,
piLogInfo->pszClientUserName,
piLogInfo->pszClientPassword,
piLogInfo->pszServerIpAddress));
dwError = IsLargeIntegerToDecimalChar(&piLogInfo->liBytesSent,
rgchBytesSent);
if ( dwError != NO_ERROR) {
wsprintfA( rgchBytesSent, "%lu:%lu",
piLogInfo->liBytesSent.HighPart,
piLogInfo->liBytesSent.LowPart);
}
dwError = IsLargeIntegerToDecimalChar(&piLogInfo->liBytesRecvd,
rgchBytesRecvd);
if ( dwError != NO_ERROR) {
wsprintfA( rgchBytesRecvd, "%lu:%lu",
piLogInfo->liBytesRecvd.HighPart,
piLogInfo->liBytesRecvd.LowPart);
}
DBGPRINTF( ( DBG_CONTEXT,
"TimeForProcessing: %u; BytesSent %s; BytesReceived %s\n",
piLogInfo->msTimeForProcessing,
rgchBytesSent,
rgchBytesRecvd));
DBGPRINTF( ( DBG_CONTEXT,
"ServiceStatus: %u; Win32Status: %u;"
" Service Operation: %ws; Target: %ws; Params: %ws\n",
piLogInfo->dwServiceSpecificStatus,
piLogInfo->dwWin32Status,
piLogInfo->pszOperation,
piLogInfo->pszTarget,
piLogInfo->pszParameters));
}
return;
} // PrintInetLogInformationW()
VOID PrintInetLogConfigurationW( const INETLOG_CONFIGURATIONW * pilConfig)
{
DBGPRINTF( ( DBG_CONTEXT,
"InetLogConfiguration( %08x)\n",
pilConfig));
if ( pilConfig != NULL) {
DBGPRINTF( ( DBG_CONTEXT,
" InetLogType = %d; LogRecordFormat = %ws\n",
pilConfig->inetLogType,
pilConfig->rgchLogRecordFormat));
switch ( pilConfig->inetLogType) {
case InetNoLog:
break;
case InetLogToFile:
DBGPRINTF( ( DBG_CONTEXT,
"Log To File in Dir %ws; TruncationSize = %u;"
" Period = %u Format = %u\n",
pilConfig->u.logFile.rgchLogFileDirectory,
pilConfig->u.logFile.cbSizeForTruncation,
pilConfig->u.logFile.ilPeriod,
pilConfig->u.logFile.ilFormat));
break;
case InetLogToSql:
DBGPRINTF( ( DBG_CONTEXT,
" Log To Sql Table( %ws) of DataSource( %ws)"
" User Name ( %ws) Password ( %ws)\n",
pilConfig->u.logSql.rgchTableName,
pilConfig->u.logSql.rgchDataSource,
pilConfig->u.logSql.rgchUserName,
pilConfig->u.logSql.rgchPassword));
break;
default:
DBGPRINTF( ( DBG_CONTEXT,
" Unknown Log Type %d \n",
pilConfig->inetLogType));
break;
} // switch
}
return;
} // PrintInetLogConfigurationW()
# endif // DBG
/**************************************************
* Local Functions
**************************************************/
static DWORD
OpenInetLogConfigRegKey(
IN LPCWSTR pszServiceName,
IN LPCWSTR pszSvcRegParamKey,
IN HKEY * phkeyInetLog)
/*++
This function opens the parameters key which consists of the
logging configuration for specified service.
If a service paramaeter registry key is provided that registry entry
is used. If none is given ( pszSvcRegParamKey == NULL), then
this function tries to open the registry key using service name
as part of pre-designated key.
Argumnets:
pszServiceName pointer to string containing service name.
pszSvcRegParamKey pointer to string containing the registry entry
path for service's parameters.
phkeyInetLog pointer to HKEY which on successful return contains
the required registry key.
Returns:
Win32 error code.
On success NO_ERROR is returned and *phkeyInetLog contains
the required registry entry.
--*/
{
DWORD dwError = NO_ERROR;
DBG_ASSERT( phkeyInetLog != NULL && pszServiceName!= NULL);
//
// Open registry key for accessing parameters.
//
if ( pszSvcRegParamKey == NULL) {
//
// Set up the registrty key for this service
//
DWORD cbReqd = (LEN_PSZ_SERVICES_REG_ENTRY_W +
lstrlenW( pszServiceName) +
LEN_PSZ_PARAMETERS_REG_ENTRY_W + 5) * sizeof( WCHAR);
LPWSTR pszRegKey = (LPWSTR ) LocalAlloc(LPTR, cbReqd);
if ( pszRegKey != NULL) {
#ifndef CHICAGO
wsprintfW( pszRegKey, L"%ws\\%ws\\%ws",
#else
wsprintfW( pszRegKey, L"%s\\%s\\%s",
#endif
PSZ_SERVICES_REG_ENTRY_W,
pszServiceName,
PSZ_PARAMETERS_REG_ENTRY_W);
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
pszRegKey,
0,
KEY_ALL_ACCESS,
phkeyInetLog);
LocalFree( pszRegKey);
} else {
*phkeyInetLog = NULL;
dwError = ERROR_NOT_ENOUGH_MEMORY;
}
} else {
dwError = RegOpenKeyExW( HKEY_LOCAL_MACHINE,
pszSvcRegParamKey,
0,
KEY_ALL_ACCESS,
phkeyInetLog);
}
return ( dwError);
} // OpenInetLogConfigRegKey()
//
// NOTE:
// The following function could very well be supplated by
// a common registry string read function and we can copy data
// to the buffer from there.
// Today such a function for WCHAR is not available in this code base
// Hence a new functions is invented.
//
//
static DWORD
ReadRegistryStringW(
IN HKEY hkeyReg,
IN LPCWSTR pszValueName,
IN LPWSTR pszBuffer,
IN DWORD cchBuffer,
IN LPWSTR pszDefaultValue)
/*++
Reads specified value from registry and stores the same in the buffer
supplied. If there is a need for expansion, the string is automatically
expanded.
Arguments:
hkeyReg Handle for Registry entry
pszValueName pointer to string containing
Name of the value to be read from registry
pszBuffer pointer to buffer which will contain the value read
on successful return from this function.
cbBuffer Count of bytes that can be stored in buffer
pszDefaultValue pointer to string containing the default value to be
used if the registry entry is missing.
Returns:
Win 32 dwErroror code. On success returns NO_DWERROROR
--*/
{
DWORD dwError = ERROR_FILE_NOT_FOUND; // default none found
WCHAR * pszBuffer1 = NULL;
#ifndef CHICAGO
BOOL fExpand = TRUE;
#else
BOOL fExpand = FALSE;
CHAR szValueA[MAX_PATH];
#endif
if ( hkeyReg != NULL) {
DWORD dwType;
DWORD cbBuffer = 0;
//
// Find bytes required.
//
dwError = RegQueryValueExW( hkeyReg, // HKEY
pszValueName, // value name
NULL, // lpvReserved = 0
&dwType, // lpdwType
NULL, // lpvData
&cbBuffer); // lpdwSize
if ( (dwError == NO_ERROR) || (dwError == ERROR_MORE_DATA)) {
//
// Valid. Data exists. Check type and retrieve data
//
if ( dwType != REG_SZ &&
dwType != REG_MULTI_SZ &&
dwType != REG_EXPAND_SZ) {
//
// Error in the type of data.
// Registry data is not a string. Use Default
//
dwError = ERROR_FILE_NOT_FOUND;
} else {
//
// Item Found. Allocate buffer and read data
//
#if 0
//
// I think we always want to expand environment variables
//
fExpand = ( dwType == REG_EXPAND_SZ);
#endif
#ifdef CHICAGO
cbBuffer*=2;
#endif
pszBuffer1 = ( WCHAR *) LocalAlloc( LPTR, cbBuffer + 2);
if ( pszBuffer1 == NULL) {
dwError = GetLastError();
} else {
//
// Read the value into buffer
//
#ifndef CHICAGO
dwError = RegQueryValueExW( hkeyReg,
pszValueName,
NULL,
NULL,
(LPBYTE ) pszBuffer1,
&cbBuffer);
#else // CHICAGO
dwError = RegQueryValueExW( hkeyReg,
pszValueName,
NULL,
NULL,
(LPBYTE ) szValueA,
&cbBuffer);
MultiByteToWideChar( CP_ACP,
MB_PRECOMPOSED,
(LPCSTR)szValueA,
-1,
pszBuffer1,
cbBuffer + 2
);
#endif
}
}
}
} // if ( hkeyReg != NULL)
if ( dwError == ERROR_FILE_NOT_FOUND &&
pszDefaultValue != NULL ) {
//
// Use the default value
//
dwError = NO_ERROR;
pszBuffer1 = (WCHAR * )
LocalAlloc( LPTR, lstrlenW( pszDefaultValue) * sizeof( WCHAR) + 2);
if ( pszBuffer1 == NULL) {
dwError = GetLastError();
} else {
lstrcpyW( pszBuffer1, pszDefaultValue);
}
}
if ( dwError == NO_ERROR) {
//
// A valid value exists.
// If needed expand the value received
//
if ( fExpand) {
WCHAR * pszBuffer2;
DWORD cch;
cch = ExpandEnvironmentStringsW( pszBuffer1, NULL, 0);
if ( cch == 0) {
dwError = GetLastError();
} else {
DWORD cch2;
pszBuffer2 = ( WCHAR *) LocalAlloc( LPTR,
cch * sizeof (WCHAR) + 2);
if ( pszBuffer2 == NULL ||
( (cch2 = ExpandEnvironmentStringsW( pszBuffer1,
pszBuffer2, cch))
> cch)) {
if ( pszBuffer2 != NULL) {
LocalFree( pszBuffer2);
pszBuffer2 = NULL;
}
dwError = ERROR_NOT_ENOUGH_MEMORY;
} else {
LocalFree( pszBuffer1); // Buffer1 is no more required
pszBuffer1 = pszBuffer2; // pszBuffer1 has Expanded string
}
}
} // if ( fExpand)
}
if ( dwError == NO_ERROR) {
//
// No ERROR. pszBuffer1 has the proper string.
// Copy this string.
//
ASSERT( pszBuffer1 != NULL);
if ( (DWORD ) lstrlenW( pszBuffer1) < cchBuffer) {
lstrcpyW( pszBuffer, pszBuffer1);
} else {
dwError = ERROR_INSUFFICIENT_BUFFER;
}
}
//
// Do Cleanup of memory occupied
//
if ( pszBuffer1 != NULL) {
LocalFree( pszBuffer1);
pszBuffer1 = NULL;
}
return ( dwError);
} // ReadRegistryStringW()
static DWORD
ReadIntervalFromRegW(IN HKEY hkey,
IN LPCWSTR pszIntervalKeyName,
IN DWORD dwDefault,
IN DWORD dwMinValue)
/*++
Reads the registry value under hkey\pszIntervalKeyName and returns the value
in milliseconds.
Arguments:
hkey Handle for registry key
pszIntervalKeyName - pointer to string containing the interval key name
dwDefault - DWORD containing default value for the interval
dwMinValue - minimum value for the interval
Returns:
the interval value in milliseconds.
--*/
{
DWORD dwVal;
dwVal = ReadRegistryDwordW(hkey,
pszIntervalKeyName,
dwDefault
);
//
// If the value is INFINITE (special) do not do any special work
//
DBG_ASSERT( INFINITE == 0xFFFFFFFF);
if ( dwVal != INFINITE) {
//
// registry setting is in seconds. convert to milliseconds.
//
dwVal *= 1000;
// use the default if no value is specified
if (dwVal == 0) {
dwVal = dwDefault * 1000;
}
//
// require a minimum of dwMinValue
//
dwVal = max( dwVal, dwMinValue * 1000);
}
return (dwVal);
} // ReadIntervalFromRegW()
/************************ End of File ***********************/