|
|
/*++
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: Sean Woodward (t-seanwo) 26-October-1997 ADSI Update
--*/
#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 = 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, (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 ); }
|