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.
1784 lines
46 KiB
1784 lines
46 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
isvcinfo.cxx
|
|
|
|
Abstract:
|
|
|
|
This module implements the functions for ISVC_INFO object.
|
|
|
|
Author:
|
|
|
|
Murali R. Krishnan ( MuraliK ) 28-July-1995
|
|
|
|
Environment:
|
|
|
|
Win32 -- User Mode
|
|
|
|
Project:
|
|
|
|
Internet Services Common DLL
|
|
|
|
Functions Exported:
|
|
|
|
ISVC_INFO::InitializeServiceInfo()
|
|
ISVC_INFO::CleanupServiceInfo()
|
|
ISVC_INFO::InsertInServiceInfoList()
|
|
ISVC_INFO::RemoveFromServiceInfoList()
|
|
ISVC_INFO::EnumerateServiceInfo()
|
|
|
|
ISVC_INFO::ISVC_INFO()
|
|
ISVC_INFO::~ISVC_INFO()
|
|
ISVC_INFO::GetConfiguration()
|
|
ISVC_INFO::SetConfiguration()
|
|
ISVC_INFO::ReadParamsFromRegistry()
|
|
|
|
ISVC_INFO::InitializeIpc()
|
|
ISVC_INFO::CleanupIpc()
|
|
ISVC_INFO::InitializeDiscovery()
|
|
ISVC_INFO::CleanupDiscovery()
|
|
ISVC_INFO::LoadStr()
|
|
ISVC_INFO::LogInformation()
|
|
ISVC_INFO::TerminateLogging()
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
/************************************************************
|
|
* Include Headers
|
|
************************************************************/
|
|
|
|
#include "tcpdllp.hxx"
|
|
#include <inetinfo.h>
|
|
#include <tsproc.hxx>
|
|
|
|
# define _INETASRV_H_
|
|
# include "isvcinfo.hxx"
|
|
# include "tcpcons.h"
|
|
# include "inetreg.h"
|
|
# include "apiutil.h"
|
|
|
|
#include <mosname.h> // MSN_INTERFACE_NAME
|
|
|
|
/************************************************************
|
|
* Symbolic Constants
|
|
************************************************************/
|
|
|
|
|
|
//
|
|
// What we assume to be the last winsock error
|
|
//
|
|
#define WSA_MAX_ERROR (WSABASEERR + 3000)
|
|
|
|
//
|
|
// For socket errors, we return the numeric socket error
|
|
//
|
|
|
|
#define SOCK_ERROR_STR_W L"Socket error %d"
|
|
#define SOCK_ERROR_STR_A "Socket error %d"
|
|
|
|
|
|
|
|
/************************************************************
|
|
* Global variables
|
|
************************************************************/
|
|
//
|
|
// Define all class globals here
|
|
//
|
|
|
|
//
|
|
// Critical section used for locking the list of ISVC_INFO objects
|
|
// during insertion and deletion
|
|
//
|
|
CRITICAL_SECTION ISVC_INFO::sm_csLock;
|
|
|
|
LIST_ENTRY ISVC_INFO::sm_ServiceInfoListHead;
|
|
|
|
DWORD ISVC_INFO::sm_nServices = 0; // number of services running
|
|
BOOL ISVC_INFO::sm_fInitialized = FALSE;
|
|
|
|
|
|
|
|
/************************************************************
|
|
* Functions
|
|
************************************************************/
|
|
|
|
#ifdef CHICAGO
|
|
extern BOOL TsIsUserLevelPresent(VOID);
|
|
extern BOOL IsRPCEnabled(VOID);
|
|
#endif
|
|
|
|
//
|
|
// LOCAL Functions
|
|
//
|
|
|
|
|
|
static ULONGLONG InetServiceIdForService( IN DWORD serviceId);
|
|
|
|
extern VOID
|
|
CopyUnicodeStringToBuffer(
|
|
OUT WCHAR * pwchBuffer,
|
|
IN DWORD cchMaxSize,
|
|
IN LPCWSTR pwszSource);
|
|
|
|
static
|
|
DWORD
|
|
GetRPCLogConfiguration(IN INETLOG_HANDLE inetLog,
|
|
OUT LPINET_LOG_CONFIGURATION * ppLogConfig);
|
|
|
|
static
|
|
DWORD
|
|
SetInetLogConfiguration(IN LPCWSTR pszServiceName,
|
|
IN INETLOG_HANDLE hInetLog,
|
|
IN LPCWSTR pszRegKey,
|
|
IN EVENT_LOG * pEventLog,
|
|
IN const INET_LOG_CONFIGURATION * pRpcLogConfig);
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Static Functions belonging to ISVC_INFO class
|
|
//
|
|
|
|
BOOL
|
|
ISVC_INFO::InitializeServiceInfo( VOID)
|
|
/*++
|
|
Description:
|
|
|
|
This function initializes all necessary local data for ISVC_INFO class
|
|
|
|
Only the first initialization call does the initialization.
|
|
Others return without any effect.
|
|
|
|
Should be called from the entry function for DLL.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Returns:
|
|
TRUE on success and FALSE if any failure.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
|
|
if ( ! ISVC_INFO::sm_fInitialized) {
|
|
|
|
//
|
|
// The static data was Not Already initialized
|
|
//
|
|
|
|
|
|
ISVC_INFO::sm_nServices = 0;
|
|
InitializeCriticalSection( & ISVC_INFO::sm_csLock);
|
|
InitializeListHead( & ISVC_INFO::sm_ServiceInfoListHead);
|
|
ISVC_INFO::sm_fInitialized = TRUE;
|
|
|
|
dwError = ISRPC::Initialize();
|
|
|
|
if ( dwError != NO_ERROR) {
|
|
|
|
SetLastError( dwError);
|
|
}
|
|
}
|
|
|
|
return ( dwError == NO_ERROR);
|
|
} // ISVC_INFO::InitializeServiceInfo()
|
|
|
|
|
|
|
|
VOID
|
|
ISVC_INFO::CleanupServiceInfo( VOID)
|
|
/*++
|
|
Description:
|
|
|
|
Cleanup the data stored and services running.
|
|
This function should be called only after freeing all the
|
|
services running using this DLL.
|
|
This function is called typically when the DLL is unloaded.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Returns:
|
|
None
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS rpcerr;
|
|
|
|
DBG_ASSERT( ISVC_INFO::sm_fInitialized);
|
|
|
|
DBG_REQUIRE( ISRPC::Cleanup() == NO_ERROR);
|
|
|
|
//
|
|
// Should we walk down the list of all services and stop them?
|
|
// Are should we expect the caller to have done that? NYI
|
|
//
|
|
|
|
|
|
DBG_ASSERT( sm_nServices == 0); // all services are stopped
|
|
|
|
//
|
|
// The DLL is going away so make sure all of the threads get terminated
|
|
// here
|
|
//
|
|
|
|
DeleteCriticalSection( & sm_csLock);
|
|
|
|
ISVC_INFO::sm_fInitialized = FALSE;
|
|
|
|
} // ISVC_INFO::CleanupServiceInfo()
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::InsertInServiceInfoList( IN LPISVC_INFO pIsvcInfo)
|
|
/*++
|
|
Description:
|
|
Insert given service info object into the global
|
|
list of service info objects.
|
|
|
|
Arguments:
|
|
pIsvcInfo
|
|
pointer to ISVC_INFO object which is to be inserted.
|
|
|
|
|
|
Returns:
|
|
TRUE on success and FALSE if there is a failure in inserting
|
|
the object
|
|
--*/
|
|
{
|
|
|
|
DBG_ASSERT( pIsvcInfo != NULL && ISVC_INFO::sm_fInitialized);
|
|
|
|
EnterCriticalSection( &sm_csLock);
|
|
|
|
InsertHeadList( & sm_ServiceInfoListHead, &pIsvcInfo->QueryListEntry());
|
|
sm_nServices++;
|
|
|
|
LeaveCriticalSection( &sm_csLock);
|
|
|
|
return ( TRUE);
|
|
} // ISVC_INFO::InsertInServiceInfoList()
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::RemoveFromServiceInfoList(IN LPISVC_INFO pIsvcInfo)
|
|
/*++
|
|
Description:
|
|
|
|
Removes given Services Info object from the global list.
|
|
|
|
Arguments:
|
|
|
|
pIsvcInfo
|
|
pointer to ISVC_INFO object to be removed.
|
|
|
|
Returns:
|
|
TRUE on sucess and FALSE if there is a failure
|
|
|
|
--*/
|
|
{
|
|
|
|
DBG_ASSERT( pIsvcInfo != NULL && ISVC_INFO::sm_fInitialized);
|
|
|
|
EnterCriticalSection( & sm_csLock);
|
|
|
|
sm_nServices--;
|
|
RemoveEntryList( & pIsvcInfo->QueryListEntry());
|
|
|
|
LeaveCriticalSection( & sm_csLock);
|
|
|
|
return ( TRUE);
|
|
|
|
} // ISVC_INFO::RemoveFromServiceInfoList()
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::EnumerateServiceInfo(
|
|
IN TS_PFN_SVC_ENUM pfnEnum,
|
|
IN PVOID pContext,
|
|
IN DWORD dwServices )
|
|
/*++
|
|
Description:
|
|
|
|
Calls pfnEnum with the address of the tsvcinfo pointer that
|
|
matches a bit in dwServices. Since the item is in the list, the
|
|
server is running or paused.
|
|
|
|
Arguments:
|
|
|
|
pfnEnum - Pointer to callback function
|
|
pContext - Context to pass to pfnEnum
|
|
dwServices - Bitflag of services to call if the service is running
|
|
|
|
Returns:
|
|
TRUE on sucess and FALSE if there is a failure
|
|
|
|
--*/
|
|
{
|
|
LIST_ENTRY * pEntry;
|
|
BOOL fRet = TRUE;
|
|
BOOL fFoundOne = FALSE;
|
|
|
|
DBG_ASSERT( ISVC_INFO::sm_fInitialized);
|
|
|
|
EnterCriticalSection( &sm_csLock );
|
|
|
|
//
|
|
// Loop through the list of running internet servers and call the callback
|
|
// for each server that has one of the service id bits set
|
|
//
|
|
|
|
for ( pEntry = sm_ServiceInfoListHead.Flink;
|
|
pEntry != &sm_ServiceInfoListHead;
|
|
pEntry = pEntry->Flink )
|
|
{
|
|
ISVC_INFO * pIsvcInfo = CONTAINING_RECORD( pEntry,
|
|
ISVC_INFO,
|
|
m_listEntry );
|
|
|
|
if ( dwServices & pIsvcInfo->QueryServiceId() &&
|
|
(pIsvcInfo->QueryCurrentServiceState() == SERVICE_RUNNING ||
|
|
pIsvcInfo->QueryCurrentServiceState() == SERVICE_PAUSED ) )
|
|
{
|
|
fRet = pfnEnum( pIsvcInfo, pContext );
|
|
|
|
fFoundOne = TRUE;
|
|
}
|
|
|
|
if ( !fRet )
|
|
break;
|
|
}
|
|
|
|
LeaveCriticalSection( &sm_csLock );
|
|
|
|
//
|
|
// If we didn't find at least one server, then assume it's not started
|
|
//
|
|
|
|
if ( !fFoundOne )
|
|
{
|
|
SetLastError( ERROR_SERVICE_NOT_ACTIVE );
|
|
fRet = FALSE;
|
|
}
|
|
|
|
return fRet;
|
|
} // ISVC_INFO::EnumerateServiceInfo()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************
|
|
* ISVC_INFO member functions
|
|
**************************************************/
|
|
|
|
ISVC_INFO::ISVC_INFO(
|
|
IN DWORD dwServiceId,
|
|
IN LPCTSTR lpszServiceName,
|
|
IN LPCTSTR lpszModuleName,
|
|
IN LPCTSTR lpszRegParamKey
|
|
)
|
|
/*++
|
|
|
|
This function constructs a new ISVC_INFO object.
|
|
It also adds the service into the list of services specified.
|
|
|
|
Arguments:
|
|
|
|
dwServiceId
|
|
DWORD containing the bitflag id for service.
|
|
|
|
lpszServiceName
|
|
name of the service to be created.
|
|
|
|
lpszModuleName
|
|
name of the module for loading string resources.
|
|
|
|
lpszRegParamKey
|
|
fully qualified name of the registry key that contains the
|
|
common service data for this server
|
|
|
|
|
|
Returns:
|
|
On success it initializes all the members of the object,
|
|
inserts itself to the global list of service info objects and
|
|
returns with success.
|
|
|
|
Note:
|
|
The caller of this function should check the validity by
|
|
invoking the member function IsValid() after constructing
|
|
this object.
|
|
|
|
--*/
|
|
:
|
|
m_dwServiceId ( dwServiceId),
|
|
m_strServiceName ( lpszServiceName),
|
|
m_strModuleName ( lpszModuleName),
|
|
m_strParametersKey ( lpszRegParamKey),
|
|
m_fValid ( FALSE ),
|
|
m_cReadLocks ( 0 ),
|
|
m_EventLog ( lpszServiceName ),
|
|
m_strAdminName (), // <-- Will come from registry
|
|
m_strAdminEmail (), // <-- Will come from registry
|
|
m_strServerComment (), // <-- Will come from registry
|
|
m_pTcpsvcsGlobalData ( NULL ),
|
|
m_fIpcStarted ( 0 ),
|
|
m_fSvcLocationDone ( 0 ),
|
|
m_fEnableSvcLocation ( INETA_DEF_ENABLE_SVC_LOCATION ),
|
|
m_hInetLog ( INVALID_INETLOG_HANDLE_VALUE ),
|
|
m_fLoggingOn ( FALSE),
|
|
m_lLoggingState ( ILOG_OFF),
|
|
m_tslock (),
|
|
m_dwMaxConnections ( INETA_DEF_MAX_CONNECTIONS),
|
|
m_dwConnectionTimeout ( INETA_DEF_CONNECTION_TIMEOUT),
|
|
m_isrpc ( lpszServiceName)
|
|
{
|
|
|
|
DBG_ASSERT( lpszRegParamKey != NULL );
|
|
|
|
m_hModule = GetModuleHandle( lpszModuleName);
|
|
DBG_ASSERT( m_hModule != NULL);
|
|
|
|
//
|
|
// Limit PWS connections
|
|
//
|
|
|
|
if ( !TsIsNtServer() ) {
|
|
m_dwMaxConnections = INETA_DEF_MAX_CONNECTIONS_PWS;
|
|
}
|
|
|
|
m_fValid = ISVC_INFO::InsertInServiceInfoList( this);
|
|
m_fValid = m_fValid && m_EventLog.Success();
|
|
|
|
if ( m_fValid) {
|
|
|
|
m_hInetLog = TsCreateInetLog( lpszServiceName,
|
|
&m_EventLog,
|
|
lpszRegParamKey);
|
|
|
|
if ( m_hInetLog != INVALID_HANDLE_VALUE) {
|
|
|
|
DWORD cbBuffer = sizeof( m_fLoggingOn);
|
|
DBG_REQUIRE(TsGetLogInformation(m_hInetLog, IlIsLoggingOn,
|
|
(PBYTE ) &m_fLoggingOn, &cbBuffer)
|
|
);
|
|
m_fValid = TRUE;
|
|
m_lLoggingState = ILOG_ACTIVE;
|
|
|
|
} else {
|
|
m_fValid = FALSE;
|
|
}
|
|
}
|
|
|
|
return;
|
|
} // ISVC_INFO::ISVC_INFO()
|
|
|
|
|
|
|
|
|
|
|
|
ISVC_INFO::~ISVC_INFO(VOID)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Cleanup the Internet Services info object.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Returns:
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DBG_REQUIRE( TerminateLogging());
|
|
ISVC_INFO::RemoveFromServiceInfoList( this);
|
|
|
|
} // ISVC_INFO::~ISVC_INFO()
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::TerminateLogging(VOID)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
if ( m_hInetLog != INVALID_INETLOG_HANDLE_VALUE) {
|
|
|
|
fSuccess = TsCloseInetLog( m_hInetLog);
|
|
|
|
if ( fSuccess) {
|
|
m_hInetLog = INVALID_INETLOG_HANDLE_VALUE;
|
|
m_fLoggingOn = FALSE;
|
|
m_lLoggingState = ILOG_OFF;
|
|
}
|
|
}
|
|
|
|
return ( fSuccess);
|
|
|
|
} // ISVC_INFO::TerminateLogging()
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::ReadParamsFromRegistry(IN FIELD_CONTROL fc)
|
|
/*++
|
|
This function reads the parameters internal to ISVC_INFO object
|
|
from registry and initializes the internal data.
|
|
Several internal data include:
|
|
log configuration object,
|
|
AdminName, AdminEmail, ServerComment etc.
|
|
|
|
Arguments:
|
|
fc -- field control indicating what parameters need to be read.
|
|
|
|
Returns:
|
|
TRUE indicating success and FALSE if there is any failure.
|
|
--*/
|
|
{
|
|
DWORD err;
|
|
BOOL fRet = TRUE;
|
|
HKEY hkey = NULL;
|
|
|
|
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
QueryRegParamKey(),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkey );
|
|
|
|
if ( err )
|
|
{
|
|
IF_DEBUG( ERROR) {
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"ISVC_INFO::ReadParamsFromRegistry() "
|
|
" RegOpenKeyEx returned error %d\n",
|
|
err ));
|
|
}
|
|
|
|
SetLastError( err );
|
|
return FALSE;
|
|
}
|
|
|
|
LockThisForWrite();
|
|
|
|
|
|
if ( IsFieldSet( fc, FC_INET_COM_CONNECTION_TIMEOUT )) {
|
|
|
|
m_dwConnectionTimeout = ReadRegistryDword(hkey,
|
|
INETA_CONNECTION_TIMEOUT,
|
|
INETA_DEF_CONNECTION_TIMEOUT
|
|
);
|
|
}
|
|
|
|
if ( IsFieldSet( fc, FC_INET_COM_MAX_CONNECTIONS )) {
|
|
|
|
m_dwMaxConnections = ReadRegistryDword(hkey,
|
|
INETA_MAX_CONNECTIONS,
|
|
INETA_DEF_MAX_CONNECTIONS
|
|
);
|
|
//
|
|
// if not NTS, limit the connections. If reg value exceeds 40,
|
|
// set it to 10.
|
|
//
|
|
|
|
if ( !TsIsNtServer() ) {
|
|
|
|
if ( m_dwMaxConnections > INETA_MAX_MAX_CONNECTIONS_PWS ) {
|
|
m_dwMaxConnections = INETA_DEF_MAX_CONNECTIONS_PWS;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( fRet && IsFieldSet( fc, FC_INET_COM_ADMIN_NAME )) {
|
|
|
|
fRet = ReadRegistryStr(hkey,
|
|
m_strAdminName,
|
|
INETA_ADMIN_NAME,
|
|
INETA_DEF_ADMIN_NAME);
|
|
}
|
|
|
|
if ( fRet && IsFieldSet( fc, FC_INET_COM_ADMIN_EMAIL )) {
|
|
|
|
fRet = ReadRegistryStr(hkey,
|
|
m_strAdminEmail,
|
|
INETA_ADMIN_EMAIL,
|
|
INETA_DEF_ADMIN_EMAIL);
|
|
}
|
|
|
|
if ( fRet && IsFieldSet( fc, FC_INET_COM_SERVER_COMMENT )) {
|
|
|
|
fRet = ReadRegistryStr(hkey,
|
|
m_strServerComment,
|
|
INETA_SERVER_COMMENT,
|
|
INETA_DEF_SERVER_COMMENT );
|
|
}
|
|
|
|
// Logging configuration is not read here.........
|
|
// IT Is done at the object construction time and in
|
|
// SetConfiguration()
|
|
|
|
UnlockThis();
|
|
|
|
if ( hkey != NULL) {
|
|
RegCloseKey( hkey);
|
|
}
|
|
|
|
return ( fRet);
|
|
|
|
} // ISVC_INFO::ReadParamsFromRegistry()
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::SetConfiguration(IN PVOID pConfig)
|
|
/*++
|
|
This function writes the parameters internal to ISVC_INFO object
|
|
to registry.
|
|
Several internal data include:
|
|
log configuration object,
|
|
AdminName, AdminEmail, ServerComment etc.
|
|
|
|
Arguments:
|
|
pConfig - pointer to config information which needs to be written
|
|
to registry
|
|
|
|
Returns:
|
|
TRUE indicating success and FALSE if there is any failure.
|
|
--*/
|
|
{
|
|
DWORD err;
|
|
BOOL fReturn = TRUE;
|
|
HKEY hkey = NULL;
|
|
FIELD_CONTROL fcConfig;
|
|
LPINET_COMMON_CONFIG_INFO pCommonConfig;
|
|
LPINET_COM_CONFIG_INFO pComConfig;
|
|
|
|
pCommonConfig = (LPINET_COMMON_CONFIG_INFO) pConfig;
|
|
|
|
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
QueryRegParamKey(),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkey );
|
|
|
|
if ( err )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"SetConfiguration() RegOpenKeyEx returned error %d\n",
|
|
err ));
|
|
SetLastError( err );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
fcConfig = pCommonConfig->FieldControl;
|
|
pComConfig = &pCommonConfig->CommonConfigInfo;
|
|
|
|
|
|
if ( err == NO_ERROR &&
|
|
IsFieldSet( fcConfig, FC_INET_COM_CONNECTION_TIMEOUT ))
|
|
{
|
|
err = WriteRegistryDword( hkey,
|
|
INETA_CONNECTION_TIMEOUT,
|
|
pComConfig->dwConnectionTimeout );
|
|
}
|
|
|
|
if ( err == NO_ERROR && IsFieldSet( fcConfig, FC_INET_COM_MAX_CONNECTIONS ))
|
|
{
|
|
err = WriteRegistryDword( hkey,
|
|
INETA_MAX_CONNECTIONS,
|
|
pComConfig->dwMaxConnections );
|
|
}
|
|
|
|
if ( err == NO_ERROR && IsFieldSet( fcConfig, FC_INET_COM_ADMIN_NAME ))
|
|
{
|
|
err = RegSetValueExW( hkey,
|
|
INETA_ADMIN_NAME_W,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *) pComConfig->lpszAdminName,
|
|
(wcslen( pComConfig->lpszAdminName ) + 1) *
|
|
sizeof( WCHAR ));
|
|
}
|
|
|
|
if ( err == NO_ERROR && IsFieldSet( fcConfig, FC_INET_COM_ADMIN_EMAIL ))
|
|
{
|
|
err = RegSetValueExW( hkey,
|
|
INETA_ADMIN_EMAIL_W,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *) pComConfig->lpszAdminEmail,
|
|
(wcslen( pComConfig->lpszAdminEmail ) + 1) *
|
|
sizeof( WCHAR ));
|
|
}
|
|
|
|
if ( err == NO_ERROR && IsFieldSet( fcConfig, FC_INET_COM_SERVER_COMMENT ))
|
|
{
|
|
err = RegSetValueExW( hkey,
|
|
INETA_SERVER_COMMENT_W,
|
|
0,
|
|
REG_SZ,
|
|
(BYTE *) pComConfig->lpszServerComment,
|
|
(wcslen( pComConfig->lpszServerComment ) + 1) *
|
|
sizeof( WCHAR ));
|
|
}
|
|
|
|
|
|
if ( err == NO_ERROR &&
|
|
IsFieldSet( fcConfig, FC_INET_COM_LOG_CONFIG)) {
|
|
|
|
WCHAR rgchServiceName[MAX_SERVICE_NAME_LEN + 1];
|
|
DWORD cbWritten = wsprintfW(rgchServiceName, L"%S",QueryServiceName());
|
|
rgchServiceName[cbWritten] = L'\0';
|
|
|
|
if ( lstrlen(QueryRegParamKey()) >= MAX_PATH) {
|
|
|
|
err = ERROR_INSUFFICIENT_BUFFER;
|
|
} else {
|
|
|
|
WCHAR rgchRegKey[MAX_PATH];
|
|
wsprintfW( rgchRegKey, L"%S", QueryRegParamKey());
|
|
|
|
err = SetInetLogConfiguration(rgchServiceName,
|
|
QueryInetLog(),
|
|
rgchRegKey,
|
|
QueryEventLog(),
|
|
pComConfig->lpLogConfig);
|
|
}
|
|
|
|
if ( err != NO_ERROR) {
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"SetConfiguration() SetInetLogConfig() failed. "
|
|
" Err=%u\n",
|
|
err));
|
|
} else {
|
|
|
|
// obtain and cache logging on status
|
|
|
|
DWORD cbBuffer = sizeof( m_fLoggingOn);
|
|
DBG_REQUIRE(TsGetLogInformation(m_hInetLog, IlIsLoggingOn,
|
|
(PBYTE ) &m_fLoggingOn, &cbBuffer)
|
|
);
|
|
// Assume active until further error
|
|
InterlockedExchange( &m_lLoggingState, ILOG_ACTIVE);
|
|
}
|
|
}
|
|
|
|
if ( err != NO_ERROR) {
|
|
|
|
|
|
SetLastError( err);
|
|
fReturn = FALSE;
|
|
}
|
|
|
|
if ( hkey != NULL) {
|
|
RegCloseKey( hkey);
|
|
}
|
|
|
|
return ( fReturn);
|
|
|
|
} // ISVC_INFO::SetConfiguration()
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::GetConfiguration( IN OUT PVOID pConfig)
|
|
/*++
|
|
This function copies the current configuration for a service into the
|
|
given RPC object pConfig.
|
|
In case of any failures, it deallocates any memory block that was
|
|
allocated during the process of copy.
|
|
|
|
Arguments:
|
|
pConfig - pointer to RPC configuration object for a service.
|
|
|
|
Returns:
|
|
|
|
TRUE for success and FALSE for any errors.
|
|
--*/
|
|
{
|
|
BOOL fReturn;
|
|
LPINET_COMMON_CONFIG_INFO pCommonConfig;
|
|
LPINET_COM_CONFIG_INFO pComConfig;
|
|
|
|
pCommonConfig = (LPINET_COMMON_CONFIG_INFO) pConfig;
|
|
|
|
|
|
LockThisForRead();
|
|
|
|
pCommonConfig->FieldControl = FC_INET_COM_ALL;
|
|
pComConfig = &pCommonConfig->CommonConfigInfo;
|
|
|
|
pComConfig->dwConnectionTimeout = QueryConnectionTimeout();
|
|
pComConfig->dwMaxConnections = QueryMaxConnections();
|
|
|
|
pComConfig->LangId = GetSystemDefaultLangID();
|
|
pComConfig->LocalId = GetSystemDefaultLCID();
|
|
|
|
//
|
|
// This is the PSS product ID
|
|
//
|
|
|
|
memset( pComConfig->ProductId,
|
|
0,
|
|
sizeof( pComConfig->ProductId ));
|
|
|
|
//
|
|
// Copy the strings
|
|
//
|
|
|
|
fReturn = (ConvertStringToRpc(&pComConfig->lpszAdminName,
|
|
QueryAdminName() ) &&
|
|
ConvertStringToRpc( &pComConfig->lpszAdminEmail,
|
|
QueryAdminEmail() ) &&
|
|
ConvertStringToRpc( &pComConfig->lpszServerComment,
|
|
QueryServerComment())
|
|
);
|
|
|
|
if ( fReturn) {
|
|
DWORD dwError;
|
|
|
|
pComConfig->lpLogConfig = NULL;
|
|
dwError = GetRPCLogConfiguration(QueryInetLog(),
|
|
&pComConfig->lpLogConfig);
|
|
|
|
if ( dwError != NO_ERROR) {
|
|
|
|
SetLastError( dwError);
|
|
fReturn = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( !fReturn ) {
|
|
|
|
if ( pComConfig->lpLogConfig != NULL) {
|
|
|
|
MIDL_user_free( pComConfig->lpLogConfig);
|
|
pComConfig->lpLogConfig = NULL;
|
|
}
|
|
|
|
//
|
|
// FreeRpcString checks for NULL pointer
|
|
//
|
|
|
|
FreeRpcString( pComConfig->lpszAdminName );
|
|
FreeRpcString( pComConfig->lpszAdminEmail );
|
|
FreeRpcString( pComConfig->lpszServerComment );
|
|
}
|
|
|
|
UnlockThis();
|
|
|
|
return (fReturn);
|
|
|
|
} // TSVC_INFO::GetConfiguration()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
ISVC_INFO::LoadStr( OUT STR & str, IN DWORD dwResId) const
|
|
/*++
|
|
This function loads the string, whose resource id is ( dwResId), into
|
|
the string str passed.
|
|
|
|
Arguments:
|
|
str reference to string object into which the string specified
|
|
by resource id is loaded
|
|
dwResId DWORD containing the resource id for string to be loaded.
|
|
|
|
Returns:
|
|
TRUE on success and FALSE if there is any failure.
|
|
--*/
|
|
{
|
|
BOOL fReturn = FALSE;
|
|
|
|
if ( (dwResId >= WSABASEERR) && (dwResId < WSA_MAX_ERROR) ) {
|
|
|
|
if (( fReturn = !str.Resize((sizeof(SOCK_ERROR_STR_A) + 11) *
|
|
sizeof( WCHAR )))) {
|
|
|
|
if ( str.IsUnicode() ) {
|
|
|
|
wsprintfW( str.QueryStrW(), SOCK_ERROR_STR_W, dwResId );
|
|
} else {
|
|
|
|
wsprintfA( str.QueryStrA(), SOCK_ERROR_STR_A, dwResId );
|
|
}
|
|
|
|
} // if ( Resize()
|
|
|
|
} else {
|
|
|
|
//
|
|
// Try to load the string from current module or system table
|
|
// depending upon if the Id < STR_RES_ID_BASE.
|
|
// System table contains strings for id's < STR_RES_ID_BASE.
|
|
//
|
|
|
|
if ( dwResId < STR_RES_ID_BASE) {
|
|
|
|
#ifndef CHICAGO
|
|
fReturn = str.LoadString( dwResId, (LPCTSTR ) NULL);
|
|
#else
|
|
fReturn = FALSE;
|
|
#endif
|
|
} else {
|
|
|
|
fReturn = str.LoadString( dwResId, QueryHandleForModule());
|
|
}
|
|
}
|
|
|
|
return ( fReturn);
|
|
|
|
} // ISVC_INFO::LoadStr()
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
ISVC_INFO::InitializeIpc( IN RPC_IF_HANDLE rpcIfHandle)
|
|
/*++
|
|
Description:
|
|
Initializes the RPC server (ADMIN RPC) for given rpc interface.
|
|
This function establishses RPC binding over Named Pipe (static)
|
|
and TCP/IP (dynamic).
|
|
It uses the service name from ISVC_INFO for both pipe name and
|
|
annotation purposes.
|
|
|
|
Arguments:
|
|
|
|
rpcIfHandle RPC Interface handle for the specified service.
|
|
|
|
Returns:
|
|
Win32 error code.
|
|
NO_ERROR on success
|
|
|
|
Limitation:
|
|
This function is not multi-thread safe.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError;
|
|
INET_BINDINGS inetBindings;
|
|
|
|
#ifdef CHICAGO
|
|
if(!IsRPCEnabled()) {
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"IPC Win95 : RPC servicing disabled \n"
|
|
));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
IF_DEBUG( DLL_RPC) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"Initializing RPC ( Rpc Interface = %08x)\n",
|
|
rpcIfHandle ));
|
|
}
|
|
|
|
//
|
|
// Start the RPC Server.
|
|
//
|
|
|
|
|
|
dwError = m_isrpc.AddProtocol( ISRPC_OVER_TCPIP
|
|
|
|
#ifndef CHICAGO
|
|
| ISRPC_OVER_NP | ISRPC_OVER_LPC
|
|
#endif
|
|
);
|
|
|
|
DBG_ASSERT( dwError != RPC_S_DUPLICATE_ENDPOINT);
|
|
|
|
if ( dwError == RPC_S_OK) {
|
|
|
|
dwError = m_isrpc.RegisterInterface( rpcIfHandle);
|
|
}
|
|
|
|
if( dwError != RPC_S_OK ) {
|
|
|
|
//
|
|
// Ignore the Duplicate End point error.
|
|
//
|
|
if( dwError == RPC_S_DUPLICATE_ENDPOINT ) {
|
|
|
|
dwError = RPC_S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Start the RPC listen thread if being built for Services.
|
|
//
|
|
|
|
if( dwError == RPC_S_OK ){
|
|
|
|
//
|
|
// Everything is fine. Fire off the global RPC thread.
|
|
//
|
|
|
|
|
|
DBG_ASSERT( QueryTcpsvcsGlobalData() != NULL);
|
|
dwError = m_isrpc.StartServer( QueryTcpsvcsGlobalData());
|
|
}
|
|
|
|
if( dwError != RPC_S_OK ) {
|
|
|
|
IF_DEBUG( DLL_RPC) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, "Cannot start RPC Server, error %u\n",
|
|
dwError ));
|
|
}
|
|
|
|
return ( dwError);
|
|
}
|
|
|
|
//
|
|
// Success!
|
|
//
|
|
|
|
m_fIpcStarted = 1;
|
|
|
|
IF_DEBUG( DLL_RPC) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, "Finished Initializing RPC \n"));
|
|
}
|
|
|
|
return ( dwError);
|
|
} // ISVC_INFO::InitializeIpc()
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
ISVC_INFO::CleanupIpc( IN RPC_IF_HANDLE rpcIfHandle)
|
|
/*++
|
|
Description:
|
|
Cleansup the RPC server (ADMIN RPC) side listen state information.
|
|
|
|
Arguments:
|
|
rpcIfHandle RPC Interface handle for the specified service.
|
|
|
|
Returns:
|
|
Win32 error code. Returns NO_ERROR on success.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
|
|
#ifdef CHICAGO
|
|
if(!IsRPCEnabled()) {
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"IPC Win95 : RPC servicing disabled \n"
|
|
));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
IF_DEBUG( DLL_RPC) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, "%08x::CleanupIpc( %08x) called \n",
|
|
rpcIfHandle ));
|
|
}
|
|
|
|
if( m_fIpcStarted ) {
|
|
|
|
m_fIpcStarted = FALSE;
|
|
|
|
//
|
|
// Stop the RPC Server.
|
|
//
|
|
|
|
dwError = m_isrpc.StopServer( QueryTcpsvcsGlobalData());
|
|
|
|
if( dwError != RPC_S_OK ) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"%08x::Stop RPC Server returned %lu\n", dwError ));
|
|
|
|
} else {
|
|
dwError = m_isrpc.UnRegisterInterface();
|
|
|
|
if( dwError != RPC_S_OK ) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"%08x::UnRegister RPC Interface returns %lu\n",
|
|
dwError ));
|
|
}
|
|
}
|
|
}
|
|
|
|
return ( dwError);
|
|
|
|
} // ISVC_INFO::CleanupIpc()
|
|
|
|
DWORD
|
|
ISVC_INFO::InitializeDiscovery( IN LPINET_BINDINGS pExtraBindings)
|
|
/*++
|
|
|
|
Register this server and service with service discoverer.
|
|
It will discover us using these information for administering us.
|
|
|
|
BUGBUG For now if extra bindings are give it does not use RpcBindings.
|
|
I.e. for now we either use default bindings (pExtraBindings is NULL) or
|
|
non-default bindings as given by pExtraBindings (which is not NULL).
|
|
|
|
Arguments:
|
|
|
|
pExtraBindings : pointer to extra (i.e. non-default) binding info
|
|
|
|
Return Value:
|
|
Win32 Error Code;
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
|
|
//
|
|
// Only enable on server as we don't have remove admin on
|
|
// the PWS. -jra !!! of course, we could change our minds again.
|
|
//
|
|
|
|
if ( !TsIsNtServer() ) {
|
|
m_fEnableSvcLocation = FALSE;
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
#ifndef CHICAGO
|
|
|
|
INET_BINDINGS TotalBindings = { 0, NULL};
|
|
HKEY hkey = NULL;
|
|
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
QueryRegParamKey(),
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkey );
|
|
|
|
if ( dwError )
|
|
{
|
|
IF_DEBUG( ERROR) {
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"ISVC_INFO::ReadParamsFromRegistry() "
|
|
" RegOpenKeyEx returned error %d\n",
|
|
dwError ));
|
|
}
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
LockThisForWrite(); // There doesn't appear to be a need for this
|
|
|
|
m_fEnableSvcLocation = !!ReadRegistryDword( hkey,
|
|
INETA_ENABLE_SVC_LOCATION,
|
|
INETA_DEF_ENABLE_SVC_LOCATION);
|
|
UnlockThis();
|
|
|
|
if ( hkey != NULL) {
|
|
|
|
RegCloseKey( hkey);
|
|
}
|
|
|
|
if ( m_fEnableSvcLocation == FALSE) {
|
|
|
|
//
|
|
// Service Location is not enabled (by admin presumably).
|
|
// So Let us not register ourselves now.
|
|
//
|
|
return ( NO_ERROR);
|
|
}
|
|
|
|
if ( pExtraBindings == NULL) {
|
|
|
|
// Form the global binding information
|
|
dwError = m_isrpc.EnumBindingStrings( &TotalBindings);
|
|
}
|
|
|
|
if ( dwError == NO_ERROR) {
|
|
|
|
dwError = INetRegisterService(
|
|
InetServiceIdForService(QueryServiceId()),
|
|
INetServiceRunning,
|
|
m_strServerComment.QueryStr(),
|
|
(( pExtraBindings != NULL)
|
|
? pExtraBindings : &TotalBindings)
|
|
);
|
|
|
|
IF_DEBUG( DLL_RPC) {
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"INetRegisterService( %u), Running, returns %u\n",
|
|
QueryServiceId(),
|
|
dwError));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Log the error then ignore it as it only affects service discovery
|
|
//
|
|
|
|
if ( dwError != NO_ERROR ) {
|
|
|
|
m_EventLog.LogEvent( INET_SVC_SERVICE_REG_FAILED,
|
|
0,
|
|
(WCHAR **) NULL,
|
|
dwError );
|
|
|
|
dwError = NO_ERROR; // Ignore the error .....
|
|
} else {
|
|
|
|
m_fSvcLocationDone = 1;
|
|
}
|
|
|
|
m_isrpc.FreeBindingStrings( &TotalBindings);
|
|
|
|
#endif
|
|
|
|
return( dwError);
|
|
|
|
} // ISVC_INFO::InitializeDiscovery()
|
|
|
|
|
|
|
|
DWORD
|
|
ISVC_INFO::TerminateDiscovery( VOID)
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
|
|
#ifndef CHICAGO
|
|
|
|
//
|
|
// Deregister the service from the Discovery Service. This will
|
|
// prevent admins from picking up our machine for administration.
|
|
//
|
|
|
|
if ( m_fEnableSvcLocation && m_fSvcLocationDone == 1) {
|
|
|
|
dwError =
|
|
INetDeregisterService(InetServiceIdForService(QueryServiceId()));
|
|
DBG_ASSERT( dwError == NO_ERROR);
|
|
m_fSvcLocationDone = 0; // since we deregistered, reset the flag
|
|
}
|
|
|
|
#endif
|
|
return( dwError);
|
|
|
|
} // ISVC_INFO::TerminateDiscovery()
|
|
|
|
|
|
|
|
DWORD
|
|
ISVC_INFO::LogInformation( IN const INETLOG_INFORMATIONA * pInetLogInfo,
|
|
OUT LPSTR pszErrorMessage,
|
|
IN OUT LPDWORD lpcchErrorMessage)
|
|
{
|
|
DWORD dwError;
|
|
|
|
if ( m_fLoggingOn) {
|
|
|
|
dwError = TsLogInformationA( m_hInetLog, pInetLogInfo,
|
|
pszErrorMessage, lpcchErrorMessage);
|
|
|
|
if ( dwError != NO_ERROR && (m_lLoggingState == ILOG_ACTIVE)) {
|
|
|
|
//
|
|
// We are entering the mode when logging is to be suspended.
|
|
// Send a single event log message so that admin can take care of
|
|
// the failure.
|
|
//
|
|
|
|
if ( InterlockedExchange( &m_lLoggingState, ILOG_SUSPENDED) ==
|
|
ILOG_ACTIVE) {
|
|
|
|
// I am the first thread, let me send an error message.
|
|
// Send event log message about suspension here.
|
|
|
|
const CHAR * apsz[1];
|
|
|
|
apsz[0] = pszErrorMessage;
|
|
|
|
LogEvent( INET_SVC_LOGGING_SUSPENDED,
|
|
(pszErrorMessage != NULL) ? 1:0,
|
|
apsz,
|
|
dwError );
|
|
}
|
|
}
|
|
|
|
if ( dwError == NO_ERROR && m_lLoggingState == ILOG_SUSPENDED) {
|
|
|
|
//
|
|
// Logging succeeded after a suspension period.
|
|
// Send a single event log message that we are resuming logging
|
|
// and continue service
|
|
//
|
|
|
|
if ( InterlockedExchange( &m_lLoggingState, ILOG_ACTIVE) ==
|
|
ILOG_SUSPENDED) {
|
|
|
|
// I am the first thread to detect that this is suspended.
|
|
// Send event log message about resumption here.
|
|
|
|
const CHAR * apsz[1];
|
|
|
|
apsz[0] = "";
|
|
|
|
LogEvent( INET_SVC_LOGGING_RESUMED,
|
|
0,
|
|
apsz,
|
|
dwError );
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
dwError = NO_ERROR; // no logging needs to be done.
|
|
}
|
|
|
|
return ( dwError);
|
|
} // ISVC_INFO::LogInformation()
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
ISVC_INFO::LogInformation( IN const INETLOG_INFORMATIONW * pInetLogInfo,
|
|
OUT LPWSTR pszErrorMessage,
|
|
IN OUT LPDWORD lpcchErrorMessage)
|
|
{
|
|
DWORD dwError;
|
|
|
|
if ( m_fLoggingOn) {
|
|
|
|
dwError = TsLogInformationW( m_hInetLog, pInetLogInfo,
|
|
pszErrorMessage, lpcchErrorMessage);
|
|
|
|
if ( dwError != NO_ERROR && (m_lLoggingState == ILOG_ACTIVE)) {
|
|
|
|
//
|
|
// We are entering the mode when logging is to be suspended.
|
|
// Send a single event log message so that admin can take care of
|
|
// the failure.
|
|
//
|
|
|
|
if ( InterlockedExchange( &m_lLoggingState, ILOG_SUSPENDED) ==
|
|
ILOG_ACTIVE) {
|
|
|
|
// I am the first thread, let me send an error message.
|
|
// Send event log message about suspension here.
|
|
|
|
STR strError;
|
|
WCHAR * apsz[1];
|
|
|
|
apsz[0] = pszErrorMessage;
|
|
|
|
LogEvent( INET_SVC_LOGGING_SUSPENDED,
|
|
(pszErrorMessage != NULL) ? 1 : 0,
|
|
apsz,
|
|
dwError );
|
|
}
|
|
}
|
|
|
|
if ( dwError == NO_ERROR && m_lLoggingState == ILOG_SUSPENDED) {
|
|
|
|
//
|
|
// Logging succeeded after a suspension period.
|
|
// Send a single event log message that we are resuming logging
|
|
// and continue service
|
|
//
|
|
|
|
if ( InterlockedExchange( &m_lLoggingState, ILOG_ACTIVE) ==
|
|
ILOG_SUSPENDED) {
|
|
|
|
// I am the first thread to detect that this is suspended.
|
|
// Send event log message about resumption here.
|
|
|
|
WCHAR * apsz[1];
|
|
|
|
apsz[0] = L"";
|
|
|
|
LogEvent( INET_SVC_LOGGING_RESUMED,
|
|
0,
|
|
apsz,
|
|
dwError );
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
dwError = NO_ERROR; // no logging needs to be done.
|
|
}
|
|
|
|
return ( dwError);
|
|
} // ISVC_INFO::LogInformation()
|
|
|
|
|
|
|
|
|
|
# if DBG
|
|
|
|
VOID
|
|
ISVC_INFO::Print(VOID) const
|
|
{
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
" Printing ISVC_INFO object (%08x)\n"
|
|
" Valid = %u. IpcStarted = %u\n"
|
|
" EnableSvcLoc = %u; SvcLocationDone = %u\n"
|
|
" Readers # = %u. PTcpsvcsGlobalData = %08x\n"
|
|
" Service Id = %u. Service Name = %s\n"
|
|
" Module handle = %08x. ModuleName = %s\n"
|
|
" Reg Parameters Key = %s\n"
|
|
" MaxConn = %d. ConnTimeout = %u secs.\n"
|
|
,
|
|
this,
|
|
m_fValid, m_fIpcStarted,
|
|
m_fEnableSvcLocation, m_fSvcLocationDone,
|
|
m_cReadLocks, m_pTcpsvcsGlobalData,
|
|
m_dwServiceId, m_strServiceName.QueryStr(),
|
|
m_hModule, m_strModuleName.QueryStr(),
|
|
m_strParametersKey.QueryStr(),
|
|
m_dwMaxConnections, m_dwConnectionTimeout
|
|
));
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
" AdminName = %s\n"
|
|
" AdminEmail = %s\n"
|
|
" ServerComment = %s\n"
|
|
" Eventlog = %08x\n"
|
|
" RequestLog = %08x LoggingOn = %u; LogState = %d\n",
|
|
m_strAdminName.QueryStr(),
|
|
m_strAdminEmail.QueryStr(),
|
|
m_strServerComment.QueryStr(),
|
|
&m_EventLog,
|
|
m_hInetLog, m_fLoggingOn, m_lLoggingState
|
|
));
|
|
|
|
m_isrpc.Print();
|
|
|
|
return;
|
|
} // ISVC_INFO::Print()
|
|
|
|
# endif // DBG
|
|
|
|
|
|
/**************************************************
|
|
* PRIVATE Functions
|
|
**************************************************/
|
|
|
|
static ULONGLONG
|
|
InetServiceIdForService( IN DWORD serviceId)
|
|
/*++
|
|
Converts the local service id into the one required for Inet Discovery
|
|
service.
|
|
|
|
It so happens the Internet Services Admin and Service Locator use
|
|
same ids but of different data type. So just return the value in proper
|
|
type.
|
|
|
|
--*/
|
|
{
|
|
ULONGLONG ulServiceId;
|
|
|
|
return ( (ULONGLONG ) serviceId);
|
|
|
|
} // InetServiceIdForService()
|
|
|
|
|
|
|
|
static
|
|
DWORD
|
|
GetRPCLogConfiguration(IN INETLOG_HANDLE hInetLog,
|
|
OUT LPINET_LOG_CONFIGURATION * ppLogConfig)
|
|
/*++
|
|
This function allocates space (using MIDL_ functions) and stores
|
|
log configuration for the given log handle in it.
|
|
|
|
Arguments:
|
|
hInetLog handle for InetLog object.
|
|
ppLogConfig pointer to INET_LOG_CONFIGURATION object which on return
|
|
contains valid log config informtion, on success.
|
|
|
|
Returns:
|
|
Win32 error code.
|
|
--*/
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
LPINET_LOG_CONFIGURATION pRpcConfig;
|
|
|
|
DBG_ASSERT( ppLogConfig != NULL);
|
|
|
|
pRpcConfig = ((LPINET_LOG_CONFIGURATION )
|
|
MIDL_user_allocate( sizeof(INET_LOG_CONFIGURATION)));
|
|
|
|
if ( pRpcConfig != NULL) {
|
|
|
|
INETLOG_CONFIGURATIONW ilogConfig;
|
|
DWORD cbConfig = sizeof(ilogConfig);
|
|
BOOL fReturn =
|
|
TsGetLogInformation(hInetLog,
|
|
IlConfigurationW,
|
|
(PBYTE ) &ilogConfig,
|
|
&cbConfig);
|
|
|
|
if ( !fReturn) {
|
|
dwError = GetLastError();
|
|
MIDL_user_free(pRpcConfig);
|
|
pRpcConfig = NULL;
|
|
|
|
} else {
|
|
|
|
// we got valid config. copy it into pRpcConfig.
|
|
// since the enumerated values in inetlog.w are same in inetasrv.h
|
|
// we do no mapping, we directly copy values.
|
|
|
|
RtlZeroMemory( pRpcConfig, sizeof( INET_LOG_CONFIGURATION));
|
|
pRpcConfig->inetLogType = ilogConfig.inetLogType;
|
|
|
|
switch ( ilogConfig.inetLogType) {
|
|
|
|
case InetNoLog:
|
|
// do nothing
|
|
break;
|
|
|
|
case InetLogToFile:
|
|
{
|
|
*((DWORD UNALIGNED*)&(pRpcConfig->rgchDataSource[MAX_PATH-sizeof(DWORD)])) = ilogConfig.u.logFile.ilFormat;
|
|
pRpcConfig->ilPeriod = ilogConfig.u.logFile.ilPeriod;
|
|
pRpcConfig->cbSizeForTruncation =
|
|
ilogConfig.u.logFile.cbSizeForTruncation;
|
|
CopyUnicodeStringToBuffer(
|
|
pRpcConfig->rgchLogFileDirectory,
|
|
MAX_PATH,
|
|
ilogConfig.u.logFile.rgchLogFileDirectory);
|
|
}
|
|
break;
|
|
|
|
case InetLogToSql:
|
|
|
|
CopyUnicodeStringToBuffer(
|
|
pRpcConfig->rgchDataSource,
|
|
MAX_PATH,
|
|
ilogConfig.u.logSql.rgchDataSource);
|
|
|
|
CopyUnicodeStringToBuffer(
|
|
pRpcConfig->rgchTableName,
|
|
MAX_TABLE_NAME_LEN,
|
|
ilogConfig.u.logSql.rgchTableName);
|
|
|
|
CopyUnicodeStringToBuffer(
|
|
pRpcConfig->rgchUserName,
|
|
UNLEN,
|
|
ilogConfig.u.logSql.rgchUserName);
|
|
|
|
CopyUnicodeStringToBuffer(
|
|
pRpcConfig->rgchPassword,
|
|
PWLEN,
|
|
ilogConfig.u.logSql.rgchPassword);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
} // switch()
|
|
}
|
|
} else {
|
|
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
*ppLogConfig = pRpcConfig;
|
|
|
|
return (dwError);
|
|
} // GetRPCLogConfiguration()
|
|
|
|
|
|
|
|
static INETLOG_TYPE
|
|
FindInetLogType( IN DWORD dwValue)
|
|
{
|
|
INETLOG_TYPE ilType;
|
|
|
|
switch (dwValue) {
|
|
|
|
case INET_LOG_DISABLED: ilType = InetNoLog; break;
|
|
case INET_LOG_TO_FILE: ilType = InetLogToFile; break;
|
|
case INET_LOG_TO_SQL: ilType = InetLogToSql; break;
|
|
default: ilType = InetLogInvalidType; break;
|
|
} // switch()
|
|
|
|
return (ilType);
|
|
|
|
} // FindInetLogType()
|
|
|
|
|
|
static INETLOG_PERIOD
|
|
FindInetLogPeriod( IN DWORD dwValue)
|
|
{
|
|
INETLOG_PERIOD ilPeriod;
|
|
|
|
switch (dwValue) {
|
|
case INET_LOG_PERIOD_NONE: ilPeriod = InetLogNoPeriod; break;
|
|
case INET_LOG_PERIOD_DAILY: ilPeriod = InetLogDaily; break;
|
|
case INET_LOG_PERIOD_WEEKLY: ilPeriod = InetLogWeekly; break;
|
|
case INET_LOG_PERIOD_MONTHLY:ilPeriod = InetLogMonthly; break;
|
|
case INET_LOG_PERIOD_YEARLY: ilPeriod = InetLogYearly; break;
|
|
default: ilPeriod = InetLogInvalidPeriod; break;
|
|
} // switch()
|
|
|
|
return (ilPeriod);
|
|
} // FindInetLogPeriod()
|
|
|
|
|
|
static
|
|
DWORD
|
|
SetInetLogConfiguration(IN LPCWSTR pszServiceName,
|
|
IN INETLOG_HANDLE hInetLog,
|
|
IN LPCWSTR pszRegKey,
|
|
IN EVENT_LOG * pEventLog,
|
|
IN const INET_LOG_CONFIGURATION * pRpcLogConfig)
|
|
/*++
|
|
This function modifies the logconfiguration associated with a given InetLog
|
|
handle. It also updates the registry containing log configuration for service
|
|
with which the inetlog handle is associated.
|
|
|
|
Arguments:
|
|
pszServiceName pointer to string containing name of the service.
|
|
hInetLog Handle to INETLOG object whose configuration needs to be
|
|
changed.
|
|
pszRegKey pointer to string containing registry key for parameters
|
|
pRpcLogConfig new RPC log configuration
|
|
|
|
|
|
Returns:
|
|
Win32 Error code. NO_ERROR returned on success.
|
|
|
|
--*/
|
|
{
|
|
DWORD dwError = NO_ERROR;
|
|
INETLOG_CONFIGURATIONW ilConfig;
|
|
|
|
// initialize
|
|
RtlZeroMemory( &ilConfig, sizeof(INETLOG_CONFIGURATIONW));
|
|
|
|
// Copy the RPC inet log configuration into local INETLOG_CONFIGURATIONW
|
|
|
|
// since the enumerated values in inetlog.w are same in inetasrv.h
|
|
// we do no mapping, we directly copy values.
|
|
ilConfig.inetLogType = FindInetLogType(pRpcLogConfig->inetLogType);
|
|
|
|
if ( ilConfig.inetLogType == InetLogInvalidType) {
|
|
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
switch (ilConfig.inetLogType) {
|
|
|
|
case INET_LOG_DISABLED:
|
|
break; // do nothing
|
|
|
|
case INET_LOG_TO_FILE:
|
|
{
|
|
DWORD *pilFormat = (DWORD UNALIGNED*)&(pRpcLogConfig->rgchDataSource[MAX_PATH-sizeof(DWORD)]);
|
|
|
|
CopyUnicodeStringToBuffer(ilConfig.u.logFile.rgchLogFileDirectory,
|
|
MAX_PATH,
|
|
pRpcLogConfig->rgchLogFileDirectory);
|
|
ilConfig.u.logFile.ilPeriod =
|
|
FindInetLogPeriod(pRpcLogConfig->ilPeriod);
|
|
|
|
ilConfig.u.logFile.ilFormat = (*pilFormat == INET_LOG_FORMAT_INTERNET_STD ) ? InternetStdLogFormat : NCSALogFormat ;
|
|
|
|
if ( ilConfig.u.logFile.ilPeriod == InetLogInvalidPeriod) {
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
ilConfig.u.logFile.cbSizeForTruncation =
|
|
pRpcLogConfig->cbSizeForTruncation;
|
|
}
|
|
break;
|
|
|
|
case INET_LOG_TO_SQL:
|
|
|
|
CopyUnicodeStringToBuffer(ilConfig.u.logSql.rgchDataSource,
|
|
MAX_PATH,
|
|
pRpcLogConfig->rgchDataSource);
|
|
|
|
CopyUnicodeStringToBuffer(ilConfig.u.logSql.rgchTableName,
|
|
MAX_TABLE_NAME_LEN,
|
|
pRpcLogConfig->rgchTableName);
|
|
|
|
CopyUnicodeStringToBuffer(ilConfig.u.logSql.rgchUserName,
|
|
UNLEN,
|
|
pRpcLogConfig->rgchUserName);
|
|
|
|
CopyUnicodeStringToBuffer(ilConfig.u.logSql.rgchPassword,
|
|
CNLEN,
|
|
pRpcLogConfig->rgchPassword);
|
|
break;
|
|
|
|
default:
|
|
return (ERROR_INVALID_PARAMETER);
|
|
} // switch()
|
|
|
|
|
|
//
|
|
// Now the ilConfig contains the local data related to configuration.
|
|
// call modify log config to modify dynamically the log handle.
|
|
//
|
|
|
|
WCHAR pszErrorMessage[200] = L"";
|
|
DWORD cchErrorMessage = sizeof(pszErrorMessage) /sizeof(WCHAR);
|
|
dwError = TsModifyLogConfigurationW( hInetLog, pszRegKey, &ilConfig,
|
|
pszErrorMessage, &cchErrorMessage );
|
|
|
|
IF_DEBUG( INETLOG) {
|
|
if (dwError != NO_ERROR ) {
|
|
|
|
dwError = GetLastError();
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
" Failure in modifying log configuration"
|
|
" ( hInetLog = %08x),"
|
|
" Service = %ws. Error =%u (%ws)\n",
|
|
hInetLog, pszServiceName, dwError,
|
|
pszErrorMessage));
|
|
}
|
|
}
|
|
|
|
return (dwError);
|
|
} // SetInetLogConfiguration()
|
|
|
|
|
|
|
|
/************************ End of File ***********************/
|