windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/svcloc/svcinfo.cxx

1500 lines
30 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
svcinfo.cxx
Abstract:
contains class implementation of service location classes.
Author:
Madan Appiah (madana) 15-May-1995
Environment:
User Mode - Win32
Revision History:
--*/
#include <svcloc.hxx>
DWORD
EMBED_SERVICE_INFO::ComputeServiceInfoSize(
LPINET_SERVICE_INFO ServiceInfo
)
/*++
Routine Description:
This private member function computes the size of the embedded service
info buffer.
Arguments:
ServiceInfo : pointer to a service info structure.
Return Value:
size of the embedded service info buffer.
--*/
{
DWORD Size;
DWORD NumBindings;
LPINET_BIND_INFO BindingsInfo;
DWORD i;
DWORD ServiceCommentLen;
if( ServiceInfo->ServiceComment != NULL) {
ServiceCommentLen =
ROUND_UP_COUNT(
(strlen(ServiceInfo->ServiceComment) + 1) * sizeof(CHAR),
ALIGN_DWORD);
}
else {
ServiceCommentLen = ROUND_UP_COUNT( 1, ALIGN_DWORD );
}
Size =
sizeof(ULONGLONG) + // service mask
sizeof(INET_SERVICE_STATE) + // service state
ServiceCommentLen + // service comment
sizeof(DWORD); // NumBindings
NumBindings = ServiceInfo->Bindings.NumBindings;
BindingsInfo = ServiceInfo->Bindings.BindingsInfo;
if( NumBindings != 0 ) {
TcpsvcsDbgAssert( BindingsInfo != NULL )
for( i = 0; i < NumBindings; i++ ) {
Size += sizeof(DWORD);
if( BindingsInfo[i].Length != 0 ) {
Size += ROUND_UP_COUNT(BindingsInfo[i].Length, ALIGN_DWORD);
TcpsvcsDbgAssert( BindingsInfo[i].BindData != NULL );
}
}
}
return( Size );
}
VOID
EMBED_SERVICE_INFO::CopyServiceInfo(
LPINET_SERVICE_INFO ServiceInfo
)
/*++
Routine Description:
This private member function copies service info to the embedded service info buffer.
Arguments:
ServiceInfo : pointer to a service info structure.
Return Value:
NONE.
--*/
{
DWORD NumBindings;
LPINET_BIND_INFO BindingsInfo;
DWORD i;
LPBYTE EndofBuffer;
LPBYTE BufferPtr;
NumBindings = ServiceInfo->Bindings.NumBindings;
BindingsInfo = ServiceInfo->Bindings.BindingsInfo;
BufferPtr = _ServiceInfoBuffer;
EndofBuffer = _ServiceInfoBuffer + _ServiceInfoLength;
//
// copy header.
//
*(ULONGLONG UNALIGNED *)BufferPtr = ServiceInfo->ServiceMask;
_ServiceMask = (ULONGLONG UNALIGNED *)BufferPtr;
BufferPtr += sizeof(ULONGLONG);
*(INET_SERVICE_STATE *)BufferPtr = ServiceInfo->ServiceState;
_ServiceState = (INET_SERVICE_STATE *)BufferPtr;
BufferPtr += sizeof(INET_SERVICE_STATE);
//
// copy service comment.
//
DWORD CommentLen;
if( ServiceInfo->ServiceComment != NULL) {
CommentLen =
ROUND_UP_COUNT(
(strlen(ServiceInfo->ServiceComment) + 1) * sizeof(CHAR),
ALIGN_DWORD);
}
else {
CommentLen = ROUND_UP_COUNT( 1, ALIGN_DWORD );
}
TcpsvcsDbgAssert( (BufferPtr + CommentLen) < EndofBuffer );
if( ServiceInfo->ServiceComment != NULL) {
strcpy( (LPSTR)BufferPtr, ServiceInfo->ServiceComment );
}
else {
*(LPSTR)BufferPtr = '\0';
}
BufferPtr += CommentLen;
*(DWORD *)BufferPtr = ServiceInfo->Bindings.NumBindings;
BufferPtr += sizeof(DWORD);
//
// copy bindings.
//
if( NumBindings != 0 ) {
for( i = 0; i < NumBindings; i++ ) {
TcpsvcsDbgAssert( BufferPtr < EndofBuffer );
*(DWORD *)BufferPtr = BindingsInfo[i].Length;
BufferPtr += sizeof(DWORD);
if( BindingsInfo[i].Length != 0 ) {
memcpy( BufferPtr, BindingsInfo[i].BindData, BindingsInfo[i].Length );
BufferPtr += ROUND_UP_COUNT( BindingsInfo[i].Length, ALIGN_DWORD );
}
}
}
TcpsvcsDbgAssert( BufferPtr == EndofBuffer );
return;
}
EMBED_SERVICE_INFO::EMBED_SERVICE_INFO(
LPINET_SERVICE_INFO ServiceInfo
)
/*++
Routine Description:
This function constructs an embedded service info object.
Note : embedded service info buffer layout :
dword 1 : ServiceMask
2 : ServiceState
3 : NumBindings
4 : Binding1 Length
5 : Binding1
6 : ..
7 : ..
8 : ..
9 : Binding2 Length
10 : Binding2
11 : ..
12 : ..
Arguments:
ServiceInfo : pointer to a service info structure.
Return Value:
NONE.
--*/
{
DWORD Size;
//
// initialize the object elements.
//
INITIALIZE_CRITICAL_SECTION( &_ServiceObjCritSect );
_ServiceInfoLength = 0;
_ServiceInfoBuffer = NULL;
_AllottedBufferSize = 0;
_ServiceState = NULL;
_ServiceComment = NULL;
_ServiceMask = NULL;
TcpsvcsDbgAssert( ServiceInfo != NULL );
if( ServiceInfo == NULL ) {
_Status = ERROR_INVALID_PARAMETER;
return;
}
//
// compute the embedded buffer length.
//
Size = ComputeServiceInfoSize( ServiceInfo );
TcpsvcsDbgAssert( Size != 0 );
//
// allocate memory.
//
_ServiceInfoBuffer = (LPBYTE) SvclocHeap->Alloc( Size );
if( _ServiceInfoBuffer == NULL ) {
_Status = ERROR_NOT_ENOUGH_MEMORY;
return;
}
_ServiceInfoLength = Size;
_AllottedBufferSize = Size;
//
// copy service info.
//
CopyServiceInfo( ServiceInfo );
_Status = ERROR_SUCCESS;
return;
}
EMBED_SERVICE_INFO::EMBED_SERVICE_INFO(
LPBYTE InfoBuffer,
DWORD InfoBufferLength
)
/*++
Routine Description:
This function constructs an embedded service info object from a given
embedded buffer.
Arguments:
InfoBuffer : pointer to a embedded buffer.
InfoBufferLength : length of the embedded buffer.
Return Value:
NONE.
--*/
{
TcpsvcsDbgAssert( InfoBuffer != NULL );
TcpsvcsDbgAssert( InfoBufferLength != 0 );
INITIALIZE_CRITICAL_SECTION( &_ServiceObjCritSect );
_ServiceInfoLength = InfoBufferLength;
_ServiceInfoBuffer = InfoBuffer;
_AllottedBufferSize = 0;
_ServiceMask = (ULONGLONG UNALIGNED *)InfoBuffer;
_ServiceState = (INET_SERVICE_STATE *)(InfoBuffer + sizeof(ULONGLONG));
_ServiceComment = (LPSTR)
(InfoBuffer +
sizeof(ULONGLONG) +
sizeof(INET_SERVICE_STATE) );
_Status = ERROR_SUCCESS;
}
EMBED_SERVICE_INFO::~EMBED_SERVICE_INFO(
VOID
)
/*++
Routine Description:
This function destructs a embedded service info object.
Arguments:
NONE.
Return Value:
NONE.
--*/
{
if( _AllottedBufferSize != 0 ) {
TcpsvcsDbgAssert( _ServiceInfoBuffer != NULL );
SvclocHeap->Free( _ServiceInfoBuffer );
}
#if DBG
_ServiceInfoLength = 0;
_ServiceInfoBuffer = NULL;
_AllottedBufferSize = 0;
_ServiceState = NULL;
_ServiceComment = NULL;
_ServiceMask = NULL;
#endif // DBG
DeleteCriticalSection( &_ServiceObjCritSect );
_Status = ERROR_SUCCESS;
return;
}
DWORD
EMBED_SERVICE_INFO::SetServiceInfo(
LPINET_SERVICE_INFO ServiceInfo
)
/*++
Routine Description:
This member function sets the new service info to the embedded service
info buffer.
Arguments:
ServiceInfo : pointer to a service info structure.
Return Value:
Windows error code.
--*/
{
DWORD Size;
TcpsvcsDbgAssert( ServiceInfo != NULL );
LockServiceObj();
if( ServiceInfo == NULL ) {
UnlockServiceObj();
return( ERROR_INVALID_PARAMETER );
}
//
// compute the size of the new service info buffer.
//
Size = ComputeServiceInfoSize( ServiceInfo ) ;
TcpsvcsDbgAssert( Size != 0 );
if( Size > _AllottedBufferSize ) {
LPBYTE NewServiceInfoBuffer;
//
// free the old buffer and reallocate a new one.
//
NewServiceInfoBuffer = (LPBYTE) SvclocHeap->Alloc( Size );
if( NewServiceInfoBuffer == NULL ) {
UnlockServiceObj();
return( ERROR_NOT_ENOUGH_MEMORY );
}
SvclocHeap->Free( _ServiceInfoBuffer );
_ServiceInfoBuffer = NewServiceInfoBuffer;
_AllottedBufferSize = Size;
}
_ServiceInfoLength = Size;
//
// now copy buffer.
//
CopyServiceInfo( ServiceInfo );
UnlockServiceObj();
return( ERROR_SUCCESS );
}
DWORD
EMBED_SERVICE_INFO::GetServiceInfo(
LPINET_SERVICE_INFO *ServiceInfo
)
/*++
Routine Description:
This member function allocates memory for service info structure and
copies service info from embedded service info buffer.
Arguments:
ServiceInfo : pointer to a location where the server info structure
pointer is returned. The caller should free the structure after
use.
Return Value:
Windows error code.
--*/
{
DWORD Error;
LPBYTE BufferPtr = _ServiceInfoBuffer;
LPBYTE EndBufferPtr = _ServiceInfoBuffer + _ServiceInfoLength;
DWORD NumBindings;
DWORD i;
LPINET_SERVICE_INFO LocalServiceInfo = NULL;
LockServiceObj();
//
// allocate memory for the service info structure.
//
LocalServiceInfo = (LPINET_SERVICE_INFO)
SvclocHeap->Alloc( sizeof( INET_SERVICE_INFO ) );
if( LocalServiceInfo == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// copy main structure first.
//
LocalServiceInfo->ServiceMask = *(ULONGLONG UNALIGNED *)BufferPtr;
BufferPtr += sizeof(ULONGLONG);
LocalServiceInfo->ServiceState = *(INET_SERVICE_STATE *)BufferPtr;
BufferPtr += sizeof(INET_SERVICE_STATE);
//
// allocate memory for the service comment.
//
DWORD CommentLen;
CommentLen =
ROUND_UP_COUNT(
(strlen((LPSTR)BufferPtr) + 1) * sizeof(CHAR),
ALIGN_DWORD );
LocalServiceInfo->ServiceComment = (LPSTR)
SvclocHeap->Alloc( CommentLen );
if( LocalServiceInfo->ServiceComment == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// copy service comment.
//
strcpy(
LocalServiceInfo->ServiceComment,
(LPSTR)BufferPtr );
BufferPtr += CommentLen;
NumBindings = *(DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
LocalServiceInfo->Bindings.NumBindings = 0;
LocalServiceInfo->Bindings.BindingsInfo = NULL;
if( NumBindings != 0 ) {
LPINET_BIND_INFO Bindings;
//
// allocate memory for bindingsinfo array.
//
Bindings = (LPINET_BIND_INFO)
SvclocHeap->Alloc( sizeof( INET_BIND_INFO ) * NumBindings );
if( Bindings == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
LocalServiceInfo->Bindings.BindingsInfo = Bindings;
for( i = 0; i < NumBindings; i++ ) {
LPBYTE BindData;
TcpsvcsDbgAssert( BufferPtr < EndBufferPtr );
Bindings[i].Length = *(DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
//
// allocate memory for the bind data.
//
BindData = (LPBYTE)SvclocHeap->Alloc( Bindings[i].Length );
if( BindData == NULL ) {
//
// free the bindings structure memory only if NumBindings
// is zero, otherwise it will be freed later on along
// with some other memory blocks.
//
if( LocalServiceInfo->Bindings.NumBindings == 0 ) {
if( LocalServiceInfo->Bindings.BindingsInfo != NULL ) {
SvclocHeap->Free( LocalServiceInfo->Bindings.BindingsInfo );
LocalServiceInfo->Bindings.BindingsInfo = NULL;
}
}
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// copy bind data.
//
memcpy( BindData, BufferPtr, Bindings[i].Length );
BufferPtr += ROUND_UP_COUNT( Bindings[i].Length, ALIGN_DWORD );
//
// successfully copied one more bind data.
//
Bindings[i].BindData = BindData;
LocalServiceInfo->Bindings.NumBindings++;
}
}
//
// all done.
//
*ServiceInfo = LocalServiceInfo;
LocalServiceInfo = NULL;
Error = ERROR_SUCCESS;
Cleanup:
if( LocalServiceInfo != NULL ) {
FreeServiceInfo( LocalServiceInfo );
}
UnlockServiceObj();
return( Error );
}
/*---------------------------------------------------------------------*/
BOOL
EMBED_SERVER_INFO::IsServiceEntryExist(
ULONGLONG ServiceMask,
LPEMBED_SERVICE_ENTRY *ServiceEntry
)
/*++
Routine Description:
This private member function looks up a service entry in the service
list.
Arguments:
ServiceMask : mask of the service to look at.
ServiceEntry : pointer to location where the service entry pointer is
returned if found.
Return Value:
TRUE : if the service entry is found in the service list.
FALSE : otherwise.
--*/
{
PLIST_ENTRY SList;
LPEMBED_SERVICE_ENTRY SEntry;
ULONGLONG SMask;
//
// Scan service list.
//
for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
SEntry = (LPEMBED_SERVICE_ENTRY)SList;
//
// Get Service Mask.
//
SMask = (SEntry->ServiceObject)->GetServiceMask();
if( SMask == ServiceMask ) {
//
// found the service entry.
//
*ServiceEntry = SEntry;
return( TRUE );
}
}
return( FALSE );
}
EMBED_SERVER_INFO::EMBED_SERVER_INFO(
WORD MajorVersion,
WORD MinorVersion,
LPSTR ServerName
)
/*++
Routine Description:
This member function constructs a server info object.
Arguments:
MajorVersion : major version number of the server software.
MinorVersion : minor version number of the server software.
ServerName : computer name of the server.
Return Value:
None.
--*/
{
DWORD Size;
LPBYTE BufferPtr;
DWORD ServerNameLen;
//
// init object fields.
//
INITIALIZE_CRITICAL_SECTION( &_ServerObjCritSect );
_ServerInfoLength = 0;
_ServerInfoBuffer = NULL;
_AllottedBufferSize = 0;
_VersionNum = NULL;
_ServerLoad = NULL;
_ServicesMask = NULL;
_ServerName = NULL;
_NumServices = NULL;
InitializeListHead( &_ServicesList );
//
// compute Server Info Size.
//
ServerNameLen = ROUND_UP_COUNT(
(strlen(ServerName) + 1) * sizeof(CHAR),
ALIGN_DWORD);
Size = sizeof(INET_VERSION_NUM) + // for version number
ServerNameLen + // for server name
sizeof(DWORD) + // for load factor
sizeof(ULONGLONG) + // for services mask.
sizeof(DWORD); // for number of services.
_ServerInfoBuffer = (LPBYTE)SvclocHeap->Alloc( Size );
if( _ServerInfoBuffer == NULL ) {
_Status = ERROR_NOT_ENOUGH_MEMORY;
return;
}
_ServerInfoLength = Size;
_AllottedBufferSize = Size;
BufferPtr = _ServerInfoBuffer;
((INET_VERSION_NUM *)BufferPtr)->Version.Major = MajorVersion;
((INET_VERSION_NUM *)BufferPtr)->Version.Minor = MinorVersion;
_VersionNum = (INET_VERSION_NUM *)BufferPtr;
BufferPtr += sizeof(INET_VERSION_NUM);
strcpy( (LPSTR)BufferPtr, ServerName );
_ServerName = (LPSTR)BufferPtr;
BufferPtr += ServerNameLen;
*(DWORD *)BufferPtr = 0; // load factor
_ServerLoad = (DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
*(ULONGLONG UNALIGNED *)BufferPtr = 0; // services mask;
_ServicesMask = (ULONGLONG UNALIGNED *)BufferPtr;
BufferPtr += sizeof(ULONGLONG);
*(DWORD *)BufferPtr = 0; // num services.
_NumServices = (DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
TcpsvcsDbgAssert( BufferPtr == (_ServerInfoBuffer + _ServerInfoLength) );
_Status = ERROR_SUCCESS;
return;
}
EMBED_SERVER_INFO::EMBED_SERVER_INFO(
LPBYTE ResponseBuffer,
DWORD ResponseBufferLength
)
/*++
Routine Description:
This member function constructs a server info object from embedded
server info buffer (received from the server).
Arguments:
ResponseBuffer : pointer to the embedded server info buffer.
ResponseBufferLength : length of the above buffer.
Return Value:
--*/
{
LPBYTE BufferPtr;
DWORD ServerNameLen;
DWORD nServices;
DWORD i;
INITIALIZE_CRITICAL_SECTION( &_ServerObjCritSect );
//
// set object fields.
//
BufferPtr = _ServerInfoBuffer = ResponseBuffer;
_VersionNum = (INET_VERSION_NUM *)BufferPtr;
BufferPtr += sizeof(INET_VERSION_NUM); // skip version number.
_ServerName = (LPSTR)BufferPtr;
ServerNameLen =
ROUND_UP_COUNT(
(strlen((LPSTR)BufferPtr) + 1) * sizeof(CHAR),
ALIGN_DWORD);
BufferPtr += ServerNameLen;
_ServerLoad = (DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
_ServicesMask = (ULONGLONG UNALIGNED *)BufferPtr;
BufferPtr += sizeof(ULONGLONG);
_NumServices = (DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
_ServerInfoLength = DIFF(BufferPtr - _ServerInfoBuffer);
_AllottedBufferSize = 0;
nServices = *_NumServices;
InitializeListHead( &_ServicesList );
//
// now make service objects.
//
for( i = 0; i < nServices; i++) {
DWORD ServiceBufferLength;
LPSERVICE_OBJECT ServiceObject;
DWORD ObjStatus;
LPEMBED_SERVICE_ENTRY ServiceEntry;
ServiceBufferLength = *(DWORD * )BufferPtr;
BufferPtr += sizeof(DWORD);
//
// make another service object.
//
ServiceObject =
new EMBED_SERVICE_INFO( BufferPtr, ServiceBufferLength );
if( ServiceObject == NULL ) {
_Status = ERROR_NOT_ENOUGH_MEMORY;
return;
}
ObjStatus = ServiceObject->GetStatus();
if( ObjStatus != ERROR_SUCCESS ) {
_Status = ObjStatus;
delete ServiceObject;
return;
}
//
// allocate space for a new service entry.
//
ServiceEntry = (LPEMBED_SERVICE_ENTRY)
SvclocHeap->Alloc( sizeof(EMBED_SERVICE_ENTRY) );
if( ServiceEntry == NULL ) {
_Status = ERROR_NOT_ENOUGH_MEMORY;
delete ServiceObject;
return;
}
ServiceEntry->ServiceObject = ServiceObject;
//
// add this new entry to the list.
//
InsertTailList( &_ServicesList, &ServiceEntry->NextEntry );
//
// point to the next service record.
//
BufferPtr += ServiceBufferLength;
}
_Status = ERROR_SUCCESS;
return;
}
EMBED_SERVER_INFO::~EMBED_SERVER_INFO(
VOID
)
/*++
Routine Description:
This member function destructs a server info object.
Arguments:
NONE.
Return Value:
NONE.
--*/
{
//
// delete all service objects first.
//
while( !IsListEmpty( &_ServicesList ) ) {
LPEMBED_SERVICE_ENTRY ServiceEntry;
//
// remove an entry from the tail of the list.
//
ServiceEntry =
(LPEMBED_SERVICE_ENTRY)RemoveTailList( &_ServicesList );
//
// delete service object.
//
delete ServiceEntry->ServiceObject;
//
// free the entry memory.
//
SvclocHeap->Free( ServiceEntry );
}
//
// free up server info buffer.
//
if( _AllottedBufferSize != 0 ) {
TcpsvcsDbgAssert( _ServerInfoBuffer != NULL );
SvclocHeap->Free( _ServerInfoBuffer );
}
#if DBG
_ServerInfoLength = 0;
_ServerInfoBuffer = NULL;
_AllottedBufferSize = 0;
_VersionNum = NULL;
_ServerLoad = NULL;
_ServicesMask = NULL;
_ServerName = NULL;
_NumServices = NULL;
#endif // DBG
DeleteCriticalSection( &_ServerObjCritSect );
_Status = ERROR_SUCCESS;
return;
}
DWORD
EMBED_SERVER_INFO::AddService (
LPINET_SERVICE_INFO ServiceInfo
)
/*++
Routine Description:
This member function adds or replaces a service info object to the
server info object.
Arguments:
ServiceInfo : pointer to the service info structure.
Return Value:
Windows Error Code.
--*/
{
DWORD Error;
LPSERVICE_OBJECT ServiceObj;
LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
ULONGLONG SMask;
LockServerObj();
SMask = ServiceInfo->ServiceMask;
if( IsServiceEntryExist( SMask, &ServiceEntry ) ) {
//
// this service already exists, so just update the content.
//
TcpsvcsDbgAssert( ServiceEntry != NULL );
TcpsvcsDbgAssert( (*_ServicesMask & SMask) == SMask );
//
// set service info.
//
Error = (ServiceEntry->ServiceObject)->SetServiceInfo( ServiceInfo );
UnlockServerObj();
return( Error );
}
//
// new entry.
//
TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0 );
//
// make a service object.
//
ServiceObj = new EMBED_SERVICE_INFO( ServiceInfo );
if( ServiceObj == NULL ) {
UnlockServerObj();
return( ERROR_NOT_ENOUGH_MEMORY );
}
Error = ServiceObj->GetStatus();
if( Error != ERROR_SUCCESS ) {
delete ServiceObj;
UnlockServerObj();
return( Error );
}
//
// allocate memory for the new service entry.
//
ServiceEntry = (LPEMBED_SERVICE_ENTRY)
SvclocHeap->Alloc( sizeof(EMBED_SERVICE_ENTRY) );
if( ServiceEntry == NULL ) {
delete ServiceObj;
UnlockServerObj();
return( ERROR_NOT_ENOUGH_MEMORY );
}
ServiceEntry->ServiceObject = ServiceObj;
//
// Adjust parameters.
//
*_ServicesMask |= SMask;
(*_NumServices)++;
//
// add this entry to the service list.
//
InsertTailList(&_ServicesList, &ServiceEntry->NextEntry);
UnlockServerObj();
return( ERROR_SUCCESS );
}
DWORD
EMBED_SERVER_INFO::RemoveService(
ULONGLONG SMask
)
/*++
Routine Description:
This member function removes a service info object from the server
info object.
Arguments:
SMask : Service mask of the service to be removed from the
server object.
Return Value:
Windows Error Code.
--*/
{
LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
LockServerObj();
//
// check the service is in the service list.
//
if( IsServiceEntryExist( SMask, &ServiceEntry ) == FALSE ) {
TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0);
UnlockServerObj();
return( ERROR_SERVICE_NOT_FOUND );
}
TcpsvcsDbgAssert( ServiceEntry != NULL );
TcpsvcsDbgAssert( *_ServicesMask & SMask );
//
// adjust parameters.
//
*_ServicesMask &= ~SMask;
(*_NumServices)--;
//
// remove entry from list.
//
RemoveEntryList( &ServiceEntry->NextEntry );
//
// delete service object.
//
delete ServiceEntry->ServiceObject;
//
// free entry memory.
//
SvclocHeap->Free( ServiceEntry );
UnlockServerObj();
return( ERROR_SUCCESS );
}
DWORD
EMBED_SERVER_INFO::SetServiceState(
ULONGLONG SMask,
INET_SERVICE_STATE ServiceState
)
/*++
Routine Description:
This member function sets the state of a service.
Arguments:
SMask : Service Mask of the service whose state to be set.
ServiceState : New state of the service.
Return Value:
None.
--*/
{
LPEMBED_SERVICE_ENTRY ServiceEntry = NULL;
LockServerObj();
//
// check the service is in the service list.
//
if( IsServiceEntryExist( SMask, &ServiceEntry ) == FALSE ) {
TcpsvcsDbgAssert( (*_ServicesMask & SMask) == 0);
UnlockServerObj();
return( ERROR_SERVICE_NOT_FOUND );
}
TcpsvcsDbgAssert( ServiceEntry != NULL );
TcpsvcsDbgAssert( *_ServicesMask & SMask );
//
// set service state.
//
(ServiceEntry->ServiceObject)->SetServiceState( ServiceState );
UnlockServerObj();
return( ERROR_SUCCESS );
}
DWORD
EMBED_SERVER_INFO::ComputeResponseLength(
VOID
)
/*++
Routine Description:
This member function computes the length of the response message
(containing server info and all services info in the embedded
formatted) sent to a client.
Arguments:
None.
Return Value:
Length of the response.
--*/
{
DWORD Size = 0;
PLIST_ENTRY SList;
LPEMBED_SERVICE_ENTRY SEntry;
LockServerObj();
//
// Compute response length of the services.
//
for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
SEntry = (LPEMBED_SERVICE_ENTRY)SList;
//
// Get Service info buffer size.
//
Size += (SEntry->ServiceObject)->GetServiceInfoLength();
Size += sizeof(DWORD); // for service length info itself.
}
//
// server info size.
//
Size += _ServerInfoLength;
UnlockServerObj();
return( Size );
}
DWORD
EMBED_SERVER_INFO::MakeResponseMessage(
LPBYTE MessageBuffer,
DWORD BufferLength
)
/*++
Routine Description:
This member function builds a response message sent to a client.
Arguments:
MessageBuffer : pointer to a buffer where the response message is
built.
BufferLength : length of the message.
Return Value:
Windows Error Code.
--*/
{
LPBYTE BufferPtr = MessageBuffer;
LPBYTE EndBufferPtr = MessageBuffer + BufferLength;
LPEMBED_SERVICE_ENTRY SEntry;
ULONGLONG SMask;
DWORD Error;
DWORD RequiredBufferLength;
PLIST_ENTRY SList;
LockServerObj();
RequiredBufferLength = ComputeResponseLength();
if( RequiredBufferLength > BufferLength ) {
UnlockServerObj();
return( ERROR_INSUFFICIENT_BUFFER );
}
//
// copy server info first.
//
memcpy( BufferPtr, _ServerInfoBuffer, _ServerInfoLength );
BufferPtr += _ServerInfoLength;
//
// copy all service info buffers.
//
for( SList = _ServicesList.Flink; SList != &_ServicesList; SList = SList->Flink ) {
DWORD *_ServiceInfoLength;
TcpsvcsDbgAssert( BufferPtr < EndBufferPtr );
_ServiceInfoLength = (DWORD *)BufferPtr;
BufferPtr += sizeof(DWORD);
SEntry = (LPEMBED_SERVICE_ENTRY)SList;
//
// Get Service Mask.
//
Error = (SEntry->ServiceObject)->GetServiceInfoBuffer(
BufferPtr,
DIFF(EndBufferPtr - BufferPtr),
_ServiceInfoLength );
if( Error != ERROR_SUCCESS ) {
UnlockServerObj();
return( Error );
}
BufferPtr += *_ServiceInfoLength;
}
UnlockServerObj();
return( ERROR_SUCCESS );
}
DWORD
EMBED_SERVER_INFO::GetServerInfo(
LPINET_SERVER_INFO *ServerInfo
)
/*++
Routine Description:
This member function retrieves the server info structure.
Arguments:
ServerInfo : pointer to a location where the pointer to the server
info structure is returned. The member function allots memory for
the structure, the caller should free the mmeory after use.
Return Value:
Windows Error Code.
--*/
{
DWORD Error;
LPINET_SERVER_INFO LocalServerInfo = NULL;
LPINET_SERVICE_INFO *ServicesInfoArray = NULL;
PLIST_ENTRY SList;
DWORD i;
LockServerObj();
//
// allocate memory for the server info structure.
//
LocalServerInfo = (LPINET_SERVER_INFO)SvclocHeap->Alloc(sizeof(INET_SERVER_INFO) );
if( LocalServerInfo == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
//
// initialize all fields.
//
memset( LocalServerInfo, 0x0, sizeof(INET_SERVER_INFO) );
//
// fill in the fields.
//
//
// server info field is fill by some one else !!
// leave it empty for now.
//
LocalServerInfo->ServerAddress.Length = 0;
LocalServerInfo->ServerAddress.BindData = NULL;
LocalServerInfo->VersionNum = *_VersionNum;
//
// alloc memory for the server name.
//
LocalServerInfo->ServerName = (LPSTR)
SvclocHeap->Alloc( (strlen(_ServerName) + 1) * sizeof(CHAR) );
if( LocalServerInfo->ServerName == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
strcpy( LocalServerInfo->ServerName, _ServerName );
LocalServerInfo->LoadFactor = *_ServerLoad;
LocalServerInfo->ServicesMask = *_ServicesMask;
LocalServerInfo->Services.NumServices = 0;
LocalServerInfo->Services.Services = NULL;
//
// allocate memory for the service struct. array pointers.
//
ServicesInfoArray = (LPINET_SERVICE_INFO *)
SvclocHeap->Alloc( (*_NumServices) * sizeof(LPINET_SERVICE_INFO ) );
if(ServicesInfoArray == NULL ) {
Error = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
memset( ServicesInfoArray, 0x0, (*_NumServices) * sizeof(LPINET_SERVICE_INFO) );
//
// now get services info.
//
for ( SList = _ServicesList.Flink, i = 0;
(SList != &_ServicesList) && (i < *_NumServices);
SList = SList->Flink, i++ ) {
LPSERVICE_OBJECT SObj;
SObj = ((LPEMBED_SERVICE_ENTRY)SList)->ServiceObject;
Error = SObj->GetServiceInfo( &ServicesInfoArray[i] );
if( Error != ERROR_SUCCESS ) {
goto Cleanup;
}
}
TcpsvcsDbgAssert( i <= (*_NumServices) );
LocalServerInfo->Services.NumServices = i;
LocalServerInfo->Services.Services = ServicesInfoArray;
ServicesInfoArray = NULL;
*ServerInfo = LocalServerInfo;
LocalServerInfo = NULL;
Error = ERROR_SUCCESS;
Cleanup:
if( Error != ERROR_SUCCESS ) {
//
// Cleanup allotted data.
//
if( ServicesInfoArray != NULL ) {
for ( i = 0; i < (*_NumServices) && ServicesInfoArray[i] != NULL; i++) {
FreeServiceInfo( ServicesInfoArray[i] );
}
SvclocHeap->Free( ServicesInfoArray );
}
if( LocalServerInfo != NULL ) {
if( LocalServerInfo->ServerName != NULL ) {
SvclocHeap->Free( LocalServerInfo->ServerName );
}
SvclocHeap->Free( LocalServerInfo );
}
}
UnlockServerObj();
return( Error );
}