windows-nt/Source/XPSP1/NT/termsrv/remdsk/rds/t120/mst120/mcsdllif.cpp
2020-09-26 16:20:57 +08:00

671 lines
20 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
}