671 lines
20 KiB
C++
671 lines
20 KiB
C++
#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);
|
||
}
|
||
|
||
|
||
|