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.
671 lines
21 KiB
671 lines
21 KiB
#include "precomp.h"
|
|
DEBUG_FILEZONE(ZONE_T120_GCCNC);
|
|
/*
|
|
* mcsdllif.cpp
|
|
*
|
|
* Copyright (c) 1993 by DataBeam Corporation, Lexington, KY
|
|
*
|
|
* Abstract:
|
|
* This is the implementation file for the MCAT MCS DLL interface class.
|
|
* This class is designed to work with Microsoft's implementation of the
|
|
* MCS DLL. All access by GCC to and from this DLL should pass through
|
|
* this class.
|
|
*
|
|
* MCS interface objects represent the Service Access Point (SAP)
|
|
* between GCC and MCS. Exactly how the interface works is an
|
|
* implementation matter for those classes that inherit from this one.
|
|
* This class defines the public member functions that GCC expects to be
|
|
* able to call upon to utilize MCS.
|
|
*
|
|
* The public member functions defined here can be broken into two
|
|
* categories: those that are part of T.122; and those that are not.
|
|
* The T.122 functions include connect provider request, connect
|
|
* provider response, disconnect provider request, create domain, delete
|
|
* domain, send data request, etc. All other member functions are
|
|
* considered a local matter from a standards point-of-view. These
|
|
* functions include support for initialization and setup, as well as
|
|
* functions allowing GCC to poll MCS for activity.
|
|
*
|
|
* This class contains a number of virtual functions which GCC needs to
|
|
* operate. Making these functions virtual in the base class allows the
|
|
* MCS interface to be portable to most any platform. All the platform
|
|
* specific code required to access MCS is contained in classes that will
|
|
* inherit from this one.
|
|
*
|
|
* Note that this class also handles the connect provider confirms by
|
|
* keeping a list of all the objects with outstanding connect provider
|
|
* request. These are held in the ConfirmObjectList.
|
|
*
|
|
* Portable
|
|
* No
|
|
*
|
|
* Author:
|
|
* Christos Tsollis
|
|
*/
|
|
|
|
#include "mcsdllif.h"
|
|
#include "mcsuser.h"
|
|
#include "gcontrol.h"
|
|
|
|
|
|
extern CRITICAL_SECTION g_csGCCProvider;
|
|
|
|
/*
|
|
* g_pMCSController
|
|
* This is a pointer to the one-and-only controller created within the
|
|
* MCS system. This object is created during MCSInitialize by the process
|
|
* that is taking on the responsibilities of the node controller.
|
|
*/
|
|
extern PController g_pMCSController;
|
|
|
|
void CALLBACK MCSCallBackProcedure (UINT, LPARAM, PVoid);
|
|
|
|
|
|
// MACROS used with the packet rebuilder
|
|
#define SEND_DATA_PACKET 0
|
|
#define UNIFORM_SEND_DATA_PACKET 1
|
|
|
|
|
|
extern MCSDLLInterface *g_pMCSIntf;
|
|
|
|
/*
|
|
* MCSDLLInterface ( )
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This is the constructor for the MCS Interface class. It is responsible
|
|
* for initializing the MCAT MCS DLL. Any errors that occur during
|
|
* initialization are returned in the error_value provided.
|
|
*/
|
|
MCSDLLInterface::MCSDLLInterface(PMCSError error_value)
|
|
:
|
|
m_ConfirmConnHdlConfList2(),
|
|
m_MCSUserList()
|
|
{
|
|
/*
|
|
** Create/initialize the MCS Controller object.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
g_pMCSController = new Controller (error_value);
|
|
|
|
if (g_pMCSController == NULL) {
|
|
/*
|
|
* The allocation of the controller failed. Report and return
|
|
* the appropriate error.
|
|
*/
|
|
WARNING_OUT (("MCSDLLInterface::MCSDLLInterface: controller creation failed"));
|
|
*error_value = MCS_ALLOCATION_FAILURE;
|
|
}
|
|
#ifdef _DEBUG
|
|
else if (*error_value != MCS_NO_ERROR) {
|
|
WARNING_OUT (("MCSDLLInterface::MCSDLLInterface: MCS controller is faulty."));
|
|
}
|
|
#endif // _DEBUG
|
|
}
|
|
|
|
|
|
/*
|
|
* ~MCSDLLInterface ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This is the destructor for the MCS Interface class. It is responsible
|
|
* for cleaning up both itself and the MCAT MCS DLL.
|
|
*/
|
|
MCSDLLInterface::~MCSDLLInterface ()
|
|
{
|
|
/*
|
|
* Destroy the controller, which will clean up all resources
|
|
* in use at this time. Then reset the flag indicating that
|
|
* MCS is initialized (since it no longer is).
|
|
*/
|
|
TRACE_OUT (("MCSDLLInterface::~MCSDLLInterface: deleting controller"));
|
|
if (NULL != g_pMCSController) {
|
|
g_pMCSController->Release();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* MCSError ConnectProviderRequest ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This T.122 primitive is used to connect two domains. This request
|
|
* should always be followed by a connect provider confirm. The
|
|
* confirm will be sent to be object specified by the confirm object
|
|
* the is passed into this routine.
|
|
*/
|
|
MCSError MCSDLLInterface::ConnectProviderRequest (
|
|
GCCConfID *calling_domain,
|
|
GCCConfID *called_domain,
|
|
TransportAddress calling_address,
|
|
TransportAddress called_address,
|
|
BOOL fSecure,
|
|
DBBoolean upward_connection,
|
|
PUChar user_data,
|
|
ULong user_data_length,
|
|
PConnectionHandle connection_handle,
|
|
PDomainParameters domain_parameters,
|
|
CConf *confirm_object)
|
|
{
|
|
MCSError mcs_error;
|
|
ConnectRequestInfo connect_request_info;
|
|
|
|
/*
|
|
* Pack all necessary information into a structure, since it will not
|
|
* all fit into the 4 byte parameter that is sent with the message.
|
|
*/
|
|
connect_request_info.calling_domain = calling_domain;
|
|
connect_request_info.called_domain = called_domain;
|
|
connect_request_info.calling_address = calling_address;
|
|
connect_request_info.called_address = called_address;
|
|
connect_request_info.fSecure = fSecure;
|
|
connect_request_info.upward_connection = upward_connection;
|
|
connect_request_info.domain_parameters = domain_parameters;
|
|
connect_request_info.user_data = user_data;
|
|
connect_request_info.user_data_length = user_data_length;
|
|
connect_request_info.connection_handle = connection_handle;
|
|
|
|
/*
|
|
* Send a connect provider request message to the controller through its
|
|
* owner callback function.
|
|
*/
|
|
ASSERT (g_pMCSController);
|
|
mcs_error = g_pMCSController->HandleAppletConnectProviderRequest(&connect_request_info);
|
|
|
|
if (mcs_error == MCS_NO_ERROR)
|
|
{
|
|
/*
|
|
** The confirm object list maintains a list of object
|
|
** pointers that have outstanding request. When the confirms
|
|
** come back in, they will be routed to the appropriate object
|
|
** based on the connection handle.
|
|
*/
|
|
mcs_error = AddObjectToConfirmList (confirm_object,
|
|
*connection_handle);
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("MCSDLLInterface::ConnectProviderRequest: error = %d", mcs_error));
|
|
}
|
|
|
|
return (mcs_error);
|
|
}
|
|
|
|
MCSError MCSDLLInterface::ConnectProviderResponse (
|
|
ConnectionHandle connection_handle,
|
|
GCCConfID *domain_selector,
|
|
PDomainParameters domain_parameters,
|
|
Result result,
|
|
PUChar user_data,
|
|
ULong user_data_length)
|
|
{
|
|
ConnectResponseInfo connect_response_info;
|
|
|
|
/*
|
|
* Pack all necessary information into a structure, since it will not
|
|
* all fit into the 4 byte parameter that is sent with the message.
|
|
*/
|
|
connect_response_info.connection_handle = connection_handle;
|
|
connect_response_info.domain_selector = domain_selector;
|
|
connect_response_info.domain_parameters = domain_parameters;
|
|
connect_response_info.result = result;
|
|
connect_response_info.user_data = user_data;
|
|
connect_response_info.user_data_length = user_data_length;
|
|
|
|
ASSERT (g_pMCSController);
|
|
/*
|
|
* Send a connect provider response message to the controller through its
|
|
* owner callback function.
|
|
*/
|
|
return g_pMCSController->HandleAppletConnectProviderResponse(&connect_response_info);
|
|
}
|
|
|
|
/*
|
|
* MCSError DisconnectProviderRequest ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is used to disconnect a node from a particular connection.
|
|
* This can be either an upward or downward connection
|
|
*/
|
|
MCSError MCSDLLInterface::DisconnectProviderRequest (
|
|
ConnectionHandle connection_handle)
|
|
{
|
|
ASSERT (g_pMCSController);
|
|
m_ConfirmConnHdlConfList2.Remove(connection_handle);
|
|
return g_pMCSController->HandleAppletDisconnectProviderRequest(connection_handle);
|
|
}
|
|
|
|
/*
|
|
* MCSError AttachUserRequest ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is used to create a user attachment to MCS. It will result
|
|
* in an attach user confirm.
|
|
*/
|
|
MCSError MCSDLLInterface::AttachUserRequest
|
|
(
|
|
GCCConfID *domain_selector,
|
|
PIMCSSap *ppMCSSap,
|
|
MCSUser *user_object
|
|
)
|
|
{
|
|
MCSError mcs_error;
|
|
|
|
mcs_error = MCS_AttachRequest (ppMCSSap,
|
|
(DomainSelector) domain_selector,
|
|
sizeof(GCCConfID),
|
|
MCSCallBackProcedure,
|
|
(PVoid) user_object,
|
|
ATTACHMENT_DISCONNECT_IN_DATA_LOSS |
|
|
ATTACHMENT_MCS_FREES_DATA_IND_BUFFER);
|
|
|
|
if (mcs_error == MCS_NO_ERROR)
|
|
m_MCSUserList.Append(user_object);
|
|
|
|
return (mcs_error);
|
|
}
|
|
|
|
/*
|
|
* MCSError DetachUserRequest ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This function is used when a user of MCS whishes to detach itself from
|
|
* a domain.
|
|
*/
|
|
MCSError MCSDLLInterface::DetachUserRequest (PIMCSSap pMCSSap,
|
|
PMCSUser pMCSUser)
|
|
{
|
|
MCSError mcs_error;
|
|
#ifdef DEBUG
|
|
UINT_PTR storing = (UINT_PTR) this;
|
|
#endif // DEBUG
|
|
|
|
mcs_error = pMCSSap->ReleaseInterface();
|
|
ASSERT ((UINT_PTR) this == storing);
|
|
m_MCSUserList.Remove(pMCSUser);
|
|
|
|
return (mcs_error);
|
|
}
|
|
|
|
/*
|
|
* void ProcessCallback ()
|
|
*
|
|
* Public
|
|
*
|
|
* Functional Description:
|
|
* This routine is called whenever a callback message is received by
|
|
* the "C" callback routine. It is responsible for both processing
|
|
* callback messages and forwarding callback messages on to the
|
|
* appropriate object.
|
|
*/
|
|
void MCSDLLInterface::ProcessCallback (unsigned int message,
|
|
LPARAM parameter,
|
|
PVoid object_ptr)
|
|
{
|
|
ConnectionHandle connection_handle;
|
|
CConf *pConf;
|
|
|
|
/*
|
|
** Before processing any callbacks from MCS we must enter a critical
|
|
** section to gaurantee that we do not attempt to process a message
|
|
** in GCC while its own thread is running.
|
|
*/
|
|
EnterCriticalSection (&g_csGCCProvider);
|
|
|
|
if (MCS_SEND_DATA_INDICATION == message ||
|
|
MCS_UNIFORM_SEND_DATA_INDICATION == message) {
|
|
|
|
/*
|
|
** First check the segmentation flag to make sure we have the
|
|
** entire packet. If not we must give the partial packet to
|
|
** the packet rebuilder and wait for the remainder of the data.
|
|
*/
|
|
ASSERT(((PSendData)parameter)->segmentation == (SEGMENTATION_BEGIN | SEGMENTATION_END));
|
|
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr)) {
|
|
// Process the entire packet
|
|
if (message == MCS_SEND_DATA_INDICATION)
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessSendDataIndication((PSendData) parameter);
|
|
}
|
|
else
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessUniformSendDataIndication((PSendData) parameter);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// Non-Send-Data callbacks.
|
|
//
|
|
WORD wHiWordParam = HIWORD(parameter);
|
|
WORD wLoWordParam = LOWORD(parameter);
|
|
|
|
switch (message)
|
|
{
|
|
/*
|
|
** These messages are handled by the object passed in through
|
|
** the user data field.
|
|
*/
|
|
case MCS_DETACH_USER_INDICATION:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr))
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessDetachUserIndication(
|
|
(Reason) wHiWordParam,
|
|
(UserID) wLoWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_ATTACH_USER_CONFIRM:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr))
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessAttachUserConfirm(
|
|
(Result) wHiWordParam,
|
|
(UserID) wLoWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_CHANNEL_JOIN_CONFIRM:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr))
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessChannelJoinConfirm(
|
|
(Result) wHiWordParam,
|
|
(ChannelID) wLoWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_CHANNEL_LEAVE_INDICATION:
|
|
#if 0 // LONCHANC: MCSUser does not handle this message.
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr))
|
|
{
|
|
((PMCSUser)object_ptr)->OwnerCallback(CHANNEL_LEAVE_INDICATION,
|
|
NULL,
|
|
parameter);
|
|
}
|
|
#endif // 0
|
|
break;
|
|
|
|
case MCS_TOKEN_GRAB_CONFIRM:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenGrabConfirm(
|
|
(TokenID) wLoWordParam,
|
|
(Result) wHiWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_TOKEN_GIVE_INDICATION:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenGiveIndication(
|
|
(TokenID) wLoWordParam,
|
|
(UserID) wHiWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_TOKEN_GIVE_CONFIRM:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenGiveConfirm(
|
|
(TokenID) wLoWordParam,
|
|
(Result) wHiWordParam);
|
|
}
|
|
break;
|
|
|
|
case MCS_TOKEN_PLEASE_INDICATION:
|
|
#ifdef JASPER
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenPleaseIndication(
|
|
(TokenID) wLoWordParam,
|
|
(UserID) wHiWordParam);
|
|
}
|
|
#endif // JASPER
|
|
break;
|
|
|
|
case MCS_TOKEN_RELEASE_CONFIRM:
|
|
#ifdef JASPER
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenReleaseConfirm(
|
|
(TokenID) wLoWordParam,
|
|
(Result) wHiWordParam);
|
|
}
|
|
#endif // JASPER
|
|
break;
|
|
|
|
case MCS_TOKEN_TEST_CONFIRM:
|
|
if (IsUserAttachmentVaid ((PMCSUser)object_ptr) )
|
|
{
|
|
((PMCSUser)object_ptr)->ProcessTokenTestConfirm(
|
|
(TokenID) wLoWordParam,
|
|
(TokenStatus) wHiWordParam);
|
|
}
|
|
break;
|
|
|
|
/*
|
|
** These messages are handled by the object that created the
|
|
** MCS DLL interface.
|
|
*/
|
|
#ifdef TSTATUS_INDICATION
|
|
case MCS_TRANSPORT_STATUS_INDICATION:
|
|
if (g_pControlSap != NULL)
|
|
{
|
|
g_pControlSap->TransportStatusIndication((PTransportStatus) parameter);
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case MCS_CONNECT_PROVIDER_INDICATION:
|
|
g_pGCCController->ProcessConnectProviderIndication((PConnectProviderIndication) parameter);
|
|
// Cleanup the controller message.
|
|
delete (PConnectProviderIndication) parameter;
|
|
break;
|
|
|
|
|
|
case MCS_DISCONNECT_PROVIDER_INDICATION:
|
|
connection_handle = (ConnectionHandle) parameter;
|
|
|
|
g_pGCCController->ProcessDisconnectProviderIndication(connection_handle);
|
|
|
|
/*
|
|
** If no entry exists in the confirm object list, there
|
|
** is a problem. All confirms must have an associated
|
|
** response.
|
|
*/
|
|
if (m_ConfirmConnHdlConfList2.Remove(connection_handle))
|
|
{
|
|
DisconnectProviderRequest(connection_handle);
|
|
}
|
|
break;
|
|
|
|
/*
|
|
** All connect provider confirms must be matched up with the
|
|
** connect provider request to determine where to route the
|
|
** message.
|
|
*/
|
|
case MCS_CONNECT_PROVIDER_CONFIRM:
|
|
connection_handle = ((PConnectProviderConfirm)parameter)->connection_handle;
|
|
|
|
/*
|
|
** If no entry exists in the confirm object list, there
|
|
** is a problem. All confirms must have an associated
|
|
** response.
|
|
*/
|
|
if (NULL != (pConf = m_ConfirmConnHdlConfList2.Remove(connection_handle)))
|
|
{
|
|
// Send the confirm to the appropriate object
|
|
if ((LPVOID) pConf != (LPVOID) LPVOID_NULL)
|
|
{
|
|
// confirm_object is a CConf.
|
|
pConf->ProcessConnectProviderConfirm((PConnectProviderConfirm) parameter);
|
|
}
|
|
else
|
|
{
|
|
// confirm_object is the GCC Controller.
|
|
g_pGCCController->ProcessConnectProviderConfirm((PConnectProviderConfirm)parameter);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING_OUT(("MCSDLLInterface: ProcessCallback: Bad Connect"
|
|
" Provider Confirm received"));
|
|
}
|
|
|
|
// Cleanup the controller message.
|
|
CoTaskMemFree( ((PConnectProviderConfirm) parameter)->pb_cred );
|
|
delete (PConnectProviderConfirm) parameter;
|
|
break;
|
|
|
|
default:
|
|
WARNING_OUT(("MCSDLLInterface: ProcessCallback: Unsupported message"
|
|
" received from MCS = %d",message));
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Leave the critical section after the callback is processed.
|
|
LeaveCriticalSection (&g_csGCCProvider);
|
|
}
|
|
|
|
/*
|
|
* void CALLBACK MCSCallBackProcedure ( unsigned int message,
|
|
* LPARAM parameter,
|
|
* PVoid user_defined)
|
|
*
|
|
* Functional Description:
|
|
* This routine receives callback messages directly from the MCAT MCS
|
|
* DLL.
|
|
*
|
|
* Formal Parameters:
|
|
* message (i)
|
|
* This is the mcs message to be processed
|
|
* parameter (i)
|
|
* Varies according to the message. See the MCAT programmers manual
|
|
* object_ptr (i)
|
|
* This is the user defined field that was passed to MCS on
|
|
* initialization.
|
|
*
|
|
* Return Value:
|
|
* See ProcessCallback
|
|
*
|
|
* Side Effects:
|
|
* None.
|
|
*
|
|
* Caveats:
|
|
* None.
|
|
*/
|
|
void CALLBACK MCSCallBackProcedure (unsigned int message,
|
|
LPARAM parameter,
|
|
PVoid user_defined)
|
|
{
|
|
if (g_pMCSIntf != NULL)
|
|
g_pMCSIntf->ProcessCallback (message, parameter, user_defined);
|
|
}
|
|
|
|
|
|
/*
|
|
* TranslateMCSResultToGCCResult ()
|
|
*
|
|
* Public Function Description
|
|
* This routine translate a standard MCS result to a GCC result.
|
|
*/
|
|
GCCResult
|
|
TranslateMCSResultToGCCResult ( Result mcs_result )
|
|
{
|
|
GCCResult gcc_result;
|
|
|
|
switch (mcs_result)
|
|
{
|
|
case RESULT_SUCCESSFUL:
|
|
gcc_result = GCC_RESULT_SUCCESSFUL;
|
|
break;
|
|
|
|
case RESULT_PARAMETERS_UNACCEPTABLE:
|
|
gcc_result = GCC_RESULT_DOMAIN_PARAMETERS_UNACCEPTABLE;
|
|
break;
|
|
|
|
case RESULT_USER_REJECTED:
|
|
gcc_result = GCC_RESULT_USER_REJECTED;
|
|
break;
|
|
|
|
/*
|
|
** Note that we are making the assumption here that the only token
|
|
** that GCC deals with is a conductor token.
|
|
*/
|
|
case RESULT_TOKEN_NOT_AVAILABLE:
|
|
gcc_result = GCC_RESULT_IN_CONDUCTED_MODE;
|
|
break;
|
|
|
|
case RESULT_TOKEN_NOT_POSSESSED:
|
|
gcc_result = GCC_RESULT_NOT_THE_CONDUCTOR;
|
|
break;
|
|
|
|
/****************************************************************/
|
|
|
|
case RESULT_UNSPECIFIED_FAILURE:
|
|
default:
|
|
gcc_result = GCC_RESULT_UNSPECIFIED_FAILURE;
|
|
break;
|
|
}
|
|
|
|
return (gcc_result);
|
|
}
|
|
|
|
/*
|
|
* MCSError AddObjectToConfirmList ()
|
|
*
|
|
* Functional Description:
|
|
* This function is used to add information about an object to the list
|
|
* which holds all information required to send connect provider confirms.
|
|
*
|
|
* Formal Parameters:
|
|
* confirm_object (i)
|
|
* This is a pointer to the object the made the connect provider
|
|
* request.
|
|
* connection_handle (i)
|
|
* This is the connection handle returned from the connect provider
|
|
* request.
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Side Effects:
|
|
* None.
|
|
*
|
|
* Caveats:
|
|
* None.
|
|
*/
|
|
MCSError MCSDLLInterface::AddObjectToConfirmList (
|
|
CConf *pConf,
|
|
ConnectionHandle connection_handle)
|
|
{
|
|
MCSError return_value;
|
|
|
|
/*
|
|
** First check to make sure that the list doesn't already contain the
|
|
** connection.
|
|
*/
|
|
if (m_ConfirmConnHdlConfList2.Find(connection_handle) == FALSE)
|
|
{
|
|
// Add it to the list
|
|
m_ConfirmConnHdlConfList2.Append(connection_handle, pConf ? pConf : (CConf *) LPVOID_NULL);
|
|
return_value = MCS_NO_ERROR;
|
|
}
|
|
else
|
|
return_value = MCS_INVALID_PARAMETER;
|
|
|
|
return (return_value);
|
|
}
|
|
|
|
|
|
|