mirror of https://github.com/lianthony/NT4.0
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
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 ***********************/
|