/****************************************************************************** * * INTEL Corporation Proprietary Information * Copyright (c) 1994, 1995, 1996 Intel Corporation. * * This listing is supplied under the terms of a license agreement * with INTEL Corporation and may not be used, copied, nor disclosed * except in accordance with the terms of that agreement. * *****************************************************************************/ /****************************************************************************** * * AUTHOR: cjutzi (Curt Jutzi) Intel Corporation * * $Workfile: api_dwn.c $ * $Revision: 1.45 $ * $Modtime: 05 Mar 1997 09:53:36 $ * $Log: S:/STURGEON/SRC/H245/SRC/VCS/api_dwn.c_v $ * * Rev 1.45 05 Mar 1997 09:56:04 MANDREWS * Fixed compiler warning in release mode. * * Rev 1.44 04 Mar 1997 17:33:26 MANDREWS * H245CopyCap() and H245CopyCapDescriptor() now return HRESULTs. * * Rev 1.43 26 Feb 1997 11:12:06 MANDREWS * Fixed problem in assigning dynamic term cap IDs; the dynamic IDs were * overlapping with static IDs. * * Rev 1.42 Feb 24 1997 18:30:18 tomitowx * multiple modedescriptor support * * Rev 1.41 07 Feb 1997 15:33:58 EHOWARDX * Changed H245DelCapDescriptor to match changes to set_cap_descriptor. * * Rev 1.40 27 Jan 1997 12:40:16 MANDREWS * * Fixed warnings. * * Rev 1.39 09 Jan 1997 19:17:04 EHOWARDX * * Initialize lError to H245_ERROR_OK to prevent "may be uninitialized" * warning. * * Rev 1.38 19 Dec 1996 17:18:50 EHOWARDX * Changed to use h245asn1.h definitions instead of _setof3 and _setof8. * * Rev 1.37 12 Dec 1996 15:57:22 EHOWARDX * Master Slave Determination kludge. * * Rev 1.36 11 Dec 1996 13:55:44 SBELL1 * Changed H245Init parameters. * * Rev 1.35 17 Oct 1996 18:17:36 EHOWARDX * Changed general string to always be Unicode. * * Rev 1.34 14 Oct 1996 14:01:26 EHOWARDX * Unicode changes. * * Rev 1.33 11 Oct 1996 15:19:56 EHOWARDX * Fixed H245CopyCap() bug. * * Rev 1.32 28 Aug 1996 11:37:10 EHOWARDX * const changes. * * Rev 1.31 19 Aug 1996 16:28:36 EHOWARDX * H245CommunicationModeResponse/H245CommunicationModeCommand bug fixes. * * Rev 1.30 15 Aug 1996 15:19:46 EHOWARDX * First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews. * Use at your own risk! * * Rev 1.29 08 Aug 1996 16:02:58 EHOWARDX * * Eliminated api_vers.h. * Changed H245Init Debug trace to eliminate API_VERSION. * * Rev 1.28 19 Jul 1996 12:48:22 EHOWARDX * * Multipoint clean-up. * * Rev 1.27 01 Jul 1996 22:13:42 EHOWARDX * * Added Conference and CommunicationMode structures and functions. * * Rev 1.26 18 Jun 1996 14:53:16 EHOWARDX * Eliminated Channel parameter to MaintenanceLoopRelease. * Made Multiplex Capability mandatory -- H245SendTermCaps now returns * H245_ERROR_NO_MUX_CAPS if no Multiplex Capability has been defined. * * Rev 1.25 14 Jun 1996 18:57:38 EHOWARDX * Geneva update. * * Rev 1.24 10 Jun 1996 16:59:02 EHOWARDX * Moved init/shutdown of submodules to CreateInstance/InstanceUnlock. * * Rev 1.23 06 Jun 1996 18:50:10 EHOWARDX * Equivalent of H.324 bugs #808 and 875 fixed. * * Rev 1.22 05 Jun 1996 17:16:48 EHOWARDX * MaintenanceLoop bug fix. * * Rev 1.21 04 Jun 1996 13:56:42 EHOWARDX * Fixed Release build warnings. * * Rev 1.20 30 May 1996 23:38:52 EHOWARDX * Cleanup. * * Rev 1.19 29 May 1996 16:08:04 unknown * Fixed bug in copying nonstandard identifiers. * * Rev 1.18 29 May 1996 15:19:48 EHOWARDX * Change to use HRESULT. * * Rev 1.17 28 May 1996 14:25:12 EHOWARDX * Tel Aviv update. * * Rev 1.16 21 May 1996 15:46:54 EHOWARDX * Fixed bugs in NonStandard messages using object identifier. * * Rev 1.15 20 May 1996 22:17:54 EHOWARDX * Completed NonStandard Message and H.225.0 Maximum Skew indication * implementation. Added ASN.1 validation to H245SetLocalCap and * H245SetCapDescriptor. Check-in from Microsoft drop on 17-May-96. * * Rev 1.14 20 May 1996 14:35:12 EHOWARDX * Got rid of asynchronous H245EndConnection/H245ShutDown stuff... * * Rev 1.13 17 May 1996 14:53:38 EHOWARDX * Added calls to StartSystemClose() and EndSystemClose(). * * Rev 1.12 16 May 1996 19:40:30 EHOWARDX * Fixed multiplex capability bug. * * Rev 1.11 16 May 1996 16:36:10 EHOWARDX * Fixed typo in H245SetCapDescriptor. * * Rev 1.10 16 May 1996 16:14:06 EHOWARDX * Fixed backwards-compatibility problem in H245SetLocalCap * (CapId of zero should result in dynamically-allocated cap id being used) * * Rev 1.9 16 May 1996 16:03:44 EHOWARDX * Fixed typo in H245SetCapDescriptor. * * Rev 1.8 16 May 1996 15:58:32 EHOWARDX * Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/ * H245DelCapDescriptor behaviour. * * Rev 1.7 15 May 1996 21:49:46 unknown * Added call to InstanceLock() to increment lock count before call * to InstanceDelete() in H245EndConnectionPhase2(). * * Rev 1.6 15 May 1996 19:54:02 unknown * Fixed H245SetCapDescriptor. * * Rev 1.5 14 May 1996 16:56:22 EHOWARDX * Last minute change from H245_IND_CAPDESC_T to H245_TOTCAPDESC_T. * H245EnumCaps() callback now uses H245_TOTCAPDESC_T instead * of separate H245_CAPDESCID_T and H245_CAPDESC_T for consistency. * * Rev 1.4 14 May 1996 15:55:44 EHOWARDX * Added mux cap handling to H245DelLocalCap. * * Rev 1.3 14 May 1996 14:06:06 EHOWARDX * Fixed abort from H245EnumCaps - if Cap Callback returns non-zero, * Cap Desc Callback is never called. * * Rev 1.2 13 May 1996 23:16:42 EHOWARDX * Fixed remote terminal capability handling. * * Rev 1.1 11 May 1996 20:32:52 EHOWARDX * Checking in for the night... * * Rev 1.0 09 May 1996 21:06:06 EHOWARDX * Initial revision. * * Rev 1.25.1.10 09 May 1996 19:31:02 EHOWARDX * Redesigned thread locking logic. * Added new API functions. * * Rev 1.25.1.9 01 May 1996 19:31:16 EHOWARDX * Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux(). * Changed H2250_xxx definitions for H.225.0 address types to H245_xxx. * * Rev 1.25.1.8 27 Apr 1996 21:09:20 EHOWARDX * Changed Channel Numbers to words, added H.225.0 support. * * Rev 1.25.1.7 25 Apr 1996 20:06:26 EHOWARDX * Moved setting of EndSessionPdu in EndSessionPhase1 to before call to api_fs * * Rev 1.25.1.6 25 Apr 1996 17:57:00 EHOWARDX * Added dwTxPort argument to H245OpenChannel(). * * Rev 1.25.1.5 25 Apr 1996 16:51:00 EHOWARDX * Function changes as per H.245 API Changes spec. * * Rev 1.25.1.4 24 Apr 1996 20:54:32 EHOWARDX * Added new OpenLogicalChannelAck/OpenLogicalChannelReject support. * * Rev 1.25.1.3 19 Apr 1996 12:54:40 EHOWARDX * Updated to 1.30 * * Rev 1.25.1.2 15 Apr 1996 15:10:48 EHOWARDX * Updated to match Curt's current version. * * Rev 1.25.1.1 03 Apr 1996 17:12:50 EHOWARDX * Integrated latest H.323 changes. * * Rev 1.25.1.0 03 Apr 1996 15:53:42 cjutzi * Branched for H.323. * * Rev 1.20 27 Mar 1996 15:25:34 cjutzi * - fixed a bug from this morning checkin dynamically allocating * pdu's.. free_mux_tbl was getting called after pdu was free'd.. * this was a problem since the mux table pointer was in the pdu * * Rev 1.19 27 Mar 1996 08:37:08 cjutzi * * - removed PDU from stack.. made them dynamically allocated * * Rev 1.18 20 Mar 1996 14:47:32 cjutzi * - added ERROR H245_ERROR_NO_CAPDESC to SendTermCaps. * * Rev 1.17 18 Mar 1996 15:23:16 cjutzi * * * * Rev 1.16 13 Mar 1996 09:15:44 cjutzi * * - changed LLPCRITICAL_SECTION to CRITICAL_SECTION * * * Rev 1.15 12 Mar 1996 15:51:48 cjutzi * * - implemented locking * - fixed callback bug w/ clenaup on term caps.. * - implemented End Session * - fixed shutdown * * Rev 1.14 08 Mar 1996 14:02:48 cjutzi * * - removed H245SetSimultaneous stuff.. * - added H245SetCapDescriptor Stuff.. * - completeed MuxTable Entry Stuff. * - required H223 -or- some portion of MuxCapbilities to be * there before you issue SendCaps.. * - NOTE: need to inforce the Simultaneous capabilities in * the same mannor.. * * Rev 1.13 05 Mar 1996 17:35:38 cjutzi * * - implemented SendMultiplexTable.. * - removed bcopy/bzero and changed free call * - added master slave indication * * Rev 1.12 01 Mar 1996 13:48:24 cjutzi * * - added hani's new fsm id's * - added some support for release on close request. * * Rev 1.11 29 Feb 1996 17:27:10 cjutzi * * - bi-directional channel working.. * * Rev 1.10 29 Feb 1996 08:35:52 cjutzi * * - added p_ossWorld to initialization * * Rev 1.9 27 Feb 1996 13:30:18 cjutzi * * - fixed master slave problem with conf_ind and tracker type * - removed RSP_LCSE in close channel resp * * Rev 1.8 26 Feb 1996 17:23:18 cjutzi * * - MiscCommand API added * - Fixed Assert for H245Init.. was not NULL'n out the pointers for the * context blocks.. * * Rev 1.7 26 Feb 1996 11:05:16 cjutzi * * - added simultaneous caps.. and fixed bugs.. * lot's of changes.. * * Rev 1.6 16 Feb 1996 13:01:08 cjutzi * * - got open / close / request close working in both directions. * * Rev 1.5 15 Feb 1996 14:42:54 cjutzi * * - fixed trace level bind w/ Instance.. no other change but had to * add when h245deb.c when in.. * * * Rev 1.4 15 Feb 1996 10:50:54 cjutzi * * - termcaps working * - changed API interface for MUX_T * - changed callback or IND_OPEN * - changed constants IND_OPEN/IND_OPEN_NEEDRSP etc.. * - cleaned up the open.. (not complete yet.. ) * * Rev 1.3 09 Feb 1996 16:58:36 cjutzi * * - cleanup.. and some fixes.. * - added and or changed headers to reflect the log of changes * *****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ /**** *****/ /**** NOTES TO THE READER *****/ /**** *****/ /**** This program has been put together using a a screen which is *****/ /**** wider than 80 characters.. It is best if a similar screen size is *****/ /**** used.. Of course emacs is my preference but 80 col screens will *****/ /**** cause you much frustration.. *****/ /**** *****/ /**** Tabs are set to 8 *****/ /**** *****/ /**** NOTE: *****/ /**** Headers are documented, however they may or may not *****/ /**** coorispond to reality. See the H245Spec.doc from Intel for the *****/ /**** current :-> H245 specification *****/ /**** *****/ /**** DISCLAMER: *****/ /**** *****/ /**** Since this code wasn't developed in Word 7.0, I am fully *****/ /**** responsable for all spelling mistakes in the comments. Please *****/ /**** disregard the spelling mistakes.. or fix them, if you are *****/ /**** currently modifying the code. *****/ /**** *****/ /**** - Thankyou *****/ /**** *****/ /**** Curt Jutzi *****/ /**** Oregon, USA *****/ /**** *****/ /****************************************************************************/ /****************************************************************************/ /****************************************************************************/ #ifndef STRICT #define STRICT #endif #include "precomp.h" /***********************/ /* H245 INCLUDES */ /***********************/ #define H245DLL_EXPORT #include "h245api.h" #include "h245com.h" #include "h245sys.x" #include "api_util.x" #include "pdu.x" #include "fsmexpor.h" #include "api_debu.x" #include "sr_api.h" #include "h245deb.x" /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245Init * * DESCRIPTION * * H245_INST_T H245Init ( * H245_CONF_T Configuration, * DWORD dwH245PhysId, * DWORD dwLinkLayerPhysId, * DWORD dwPreserved, * H245_CONF_IND_CALLBACK_T Callback * ) * Description: * * Called to create an H.245 instance and its related sublayers * (e.g., SRP). This function must be called before any other * API calls may be called The current H.245 implementation can * only have, at most, one client. Therefore H245Init can only be * called once per physical ID. * Input * * Configuration Indicates the type of configuration the client * wishes to establish, e.g. H.324, H.323, H.310, * or DSVD. * dwH245PhysId Parameter identifying the H245 entry * pdwLinkLayerPhysId * Output parameter identifying the linkLayer * entry. * dwPreserved Parameter that may be used by H.245 client to * provide context, passed back to client in all * confirms and indications. * Callback Callback routine supplied by the client which * will be used by the H.245 subsystem to convey * confirm and indication messages back to the * client. * Call Type: * * Synchronous * * Return Values: * * Return value of 0 indicates Failure * Return value of non 0 is a valid H245_INST_T * * Errors: * N/A * * See Also: * H245EndSession * H245Shutdown * * *****************************************************************************/ H245DLL H245_INST_T H245Init ( H245_CONFIG_T Configuration, unsigned long dwH245PhysId, unsigned long *pdwLinkLayerPhysId, DWORD_PTR dwPreserved, H245_CONF_IND_CALLBACK_T CallBack, unsigned char byTerminalType ) { register struct InstanceStruct *pInstance; HRESULT lError; H245TRACE(dwH245PhysId,4,"H245Init(%d, 0x%x, 0x%x, 0x%x, %d) <-", Configuration, dwH245PhysId, dwPreserved, CallBack, byTerminalType); switch (Configuration) { case H245_CONF_H324: case H245_CONF_H323: break; default: H245TRACE(dwH245PhysId,1,"H245Init -> Invalid Configuration %d", Configuration); return H245_INVALID_ID; } // switch if (CallBack == NULL) { H245TRACE(dwH245PhysId,1,"H245Init -> Null CallBack"); return H245_INVALID_ID; } /* see if this physical identifier has been initialized already */ // Send down H245PhysId that was input. pInstance = InstanceCreate(dwH245PhysId, Configuration); if (pInstance == NULL) { return H245_INVALID_ID; } // Get the linkLayer PhysId. *pdwLinkLayerPhysId = pInstance->SendReceive.hLinkLayerInstance; // Initialize instance API structure pInstance->API.dwPreserved = dwPreserved; pInstance->API.ConfIndCallBack = CallBack; // Initialize instance FSM structure pInstance->StateMachine.sv_TT = byTerminalType; pInstance->StateMachine.sv_STATUS = INDETERMINATE; H245TRACE(pInstance->dwInst,4,"H245Init -> %d", pInstance->dwInst); lError = pInstance->dwInst; InstanceUnlock(pInstance); return lError; } // H245Init() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245EndSession * * DESCRIPTION * * Yes.. this should be explained.. Since Send Receive needs * to flush some buffers and send out an End Session.. what we've * hopefully done is a 2 phase shut down... * * call StartSessionClose which initiates the flush.. * when flush is complete EndSessionPhase1 is called.. * The end session pdu is then placed in the send queue.. * When the End Session Pdu is sent.. the EndSession Phase * 2 is called, and the result is sent up to the client.. * * Hope that helps.. * * * HRESULT H245EndSession ( H245_INST_T dwInst, * H245_ENDSESSION_T Mode, * H245_NONSTANDARD_T *pNonStd (*optional*) * ) * * Description: * Called to shutdown the peer to peer session between this H.245 * session and the remote peers H.245 layer. * * It will terminate by issuing an EndSession command to the * remote side and call end session for all the H.245 subsystems. * All resources are returned; therefore no further action is * permitted, except H245ShutDown until another H245Init API call * is made. * * input * dwInst Instance handle returned by H245Init * Mode Mode which the client wishes to terminat * the session * pNonStd If the mode is non standard this is the non * standard parameter passes to the remote client. * This parameter is optional, and should be set * to NULL if not used * * Call Type: * Asynchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK * H245_ERROR_PARAM * H245_ERROR_INVALID_INST * H245_ERROR_NOT_CONNECTED * See Also: * H245Shutdown * H245Init * *****************************************************************************/ H245DLL HRESULT H245EndSession ( H245_INST_T dwInst, H245_ENDSESSION_T Mode, const H245_NONSTANDARD_PARAMETER_T * pNonStd ) { register struct InstanceStruct *pInstance; register MltmdSystmCntrlMssg *pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245EndSession <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in either connecting or connected */ switch (pInstance->API.SystemState) { case APIST_Connecting: case APIST_Connected: break; default: H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } // Allocate the PDU buffer pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); // Build the PDU lError = pdu_cmd_end_session (pPdu, Mode, pNonStd); if (lError == H245_ERROR_OK) { // Send the PDU lError = FsmOutgoing(pInstance, pPdu, 0); } // Free the PDU buffer MemFree(pPdu); if (lError != H245_ERROR_OK) { H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(lError)); } else { H245TRACE (dwInst,4,"H245EndSession -> OK"); pInstance->API.SystemState = APIST_Disconnected; } InstanceUnlock(pInstance); return lError; } // H245EndSession() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245ShutDown * * DESCRIPTION * * HRESULT H245Shutdown ( H245_INST_T dwInst); * * Description: * * Called to terminate the specified instance of H.245. If there * is currently an active session (see H245Init) then the H.245 * subsystem will issue an EndSession to the other side and wait * for H.245 sublayer termination notifications before it queues * Callback confirm. * * This call will force the client to issue another H245Init * before it can use any of the H.245 API functions. * * Input * dwInst Instance handle returned by H245Init * * Call Type: * asynchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * * See Also: * H245Init * *****************************************************************************/ H245DLL HRESULT H245ShutDown (H245_INST_T dwInst) { register struct InstanceStruct *pInstance; register HRESULT lError; H245TRACE (dwInst,4,"H245ShutDown <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245ShutDown -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } switch (pInstance->API.SystemState) { case APIST_Connecting: case APIST_Connected: lError = H245EndSession(dwInst,H245_ENDSESSION_DISCONNECT,NULL); break; default: lError = H245_ERROR_OK; } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245ShutDown -> %s", map_api_error(lError)); else H245TRACE (dwInst,4,"H245ShutDown -> OK"); InstanceDelete (pInstance); return H245_ERROR_OK; } // H245ShutDown() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245InitMasterSlave * * DESCRIPTION * * HRESULT H245InitMasterSlave ( H245_INST_T dwInst, * DWORD dwTransId ) * * Description: * Called to initiate the H.245 master slave negotiation. * Upon completion of the negotiation the local client will * receive an H245_CONF_INIT_MSTSLV message indicating the * result of the negotiation. * Input * dwInst Instance handle returned by * H245GetInstanceId * dwTransId User supplied object used to identify this * request in the asynchronous response to * this call. * * Call Type: * Asynchronous * * Return Values: * See Errors * * Callbacks: * H245_CONF_INIT_MSTSLV * * Errors: * H245_ERROR_OK Master Slave Determination started * H245_ERROR_INPROCESS Master Slave Determination currently * in process * H245_ERROR_NOMEM * H245_ERROR_INPROCESS In process * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * * See Also: * H245Init * * callbacks * H245_IND_MSTSLV * * *****************************************************************************/ H245DLL HRESULT H245InitMasterSlave ( H245_INST_T dwInst, DWORD_PTR dwTransId ) { struct InstanceStruct *pInstance; Tracker_T *pTracker; HRESULT lError; MltmdSystmCntrlMssg *pPdu = NULL; /* check for valid instance handle */ H245TRACE (dwInst,4,"H245InitMasterSlave <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* if the transaction is in process.. tell client */ if (pInstance->API.MasterSlave == APIMS_InProcess) { H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INPROCESS)); InstanceUnlock(pInstance); return H245_ERROR_INPROCESS; } /* if the transaction is already complete */ if (pInstance->API.MasterSlave != APIMS_Undef) { if (pInstance->API.ConfIndCallBack) { H245_CONF_IND_T confirm_ind_event; confirm_ind_event.Kind = H245_CONF; confirm_ind_event.u.Confirm.Confirm = H245_CONF_INIT_MSTSLV; confirm_ind_event.u.Confirm.dwPreserved = pInstance->API.dwPreserved; confirm_ind_event.u.Confirm.dwTransId = dwTransId; confirm_ind_event.u.Confirm.Error = H245_ERROR_OK; confirm_ind_event.u.Confirm.u.ConfMstSlv = (pInstance->API.MasterSlave == APIMS_Master) ? H245_MASTER : H245_SLAVE; (*pInstance->API.ConfIndCallBack)(&confirm_ind_event, NULL); } H245TRACE (dwInst,4,"H245InitMasterSlave -> OK"); InstanceUnlock(pInstance); return H245_ERROR_OK; } /* get somthing to keep track of what the heck you're doing.. */ if (!(pTracker = alloc_link_tracker (pInstance, API_MSTSLV_T, dwTransId, API_ST_WAIT_RMTACK, API_CH_ALLOC_UNDEF, API_CH_TYPE_UNDEF, 0, H245_INVALID_CHANNEL, H245_INVALID_CHANNEL, 0))) { H245TRACE(dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } /* set master slave in process */ pInstance->API.SystemState = APIST_Connecting; pInstance->API.MasterSlave = APIMS_InProcess; memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = masterSlaveDetermination_chosen; lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); MemFree(pPdu); if (lError != H245_ERROR_OK) { unlink_dealloc_tracker (pInstance, pTracker); H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(lError)); } else H245TRACE (dwInst,4,"H245InitMasterSlave -> OK"); InstanceUnlock(pInstance); return lError; } // H245InitMasterSlave() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245SetLocalCap * * DESCRIPTION * * HRESULT H245SetLocalCap ( * H245_INST_T dwInst, * H245_TOTCAP_T *pTotCap, * H245_CAPID_T *pCapId * ) * * Description: * This function allows the client to define a specific * capability to the H.245 subsystem. When this function is * called a new capability entry is made in the local capability * table. The returned value in *pCapId can be used by the client * to refer to that registered capability. NULL in the *pCapId * is valid. * * This call is used for both client (Audio / Video / Data / Mux) * capabilities. It is not used for setting capability descriptors. * * Note: * 7 This function does not communicate this update to the * remote peer until the client calls H245SendTermCaps. * 7 pTotCap->CapId is of no significance in this call. * * pTotCap->CapId is of no significance in this call and should * be set to 0 * * if DataType of H245_DATA_MUX is used (i.e. in setting the * mux table capabilities) No capid is returned, and it can not * be used in H245SetCapDescritptor api call. * * Input * dwInst Instance handle returned by GetInstanceId * pTotCap Capability set defining the capability * * Note: pTotCap->CapId is of no significance in this call. * * output * pCapId Capability id which client can use to reference * this capability in the H.245 subsystem. This can * be NULL, in this case nothing is returned. * * Call Type: * Synchronous * * Return Values: * If pCap is not null, the local cap table id is returned * to the client in this parameter. * * Errors: * H245_ERROR_OK * H245_ERROR_PARAM There was an invalid parameter passed * H245_ERROR_MAXTBL Entry not made because local cap table * is full * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * * See Also: * H245DelLocalCap * H245EnumCaps * H245SetCapDescriptor * * * ASSUMPTION: * pTotCap->CapId will be set to H245_INVALID_CAPID * pTotCap->Dir will be set * *****************************************************************************/ H245DLL HRESULT H245SetLocalCap ( H245_INST_T dwInst, H245_TOTCAP_T * pTotCap, H245_CAPID_T * pCapId ) { register struct InstanceStruct *pInstance; struct TerminalCapabilitySet *pTermCapSet; HRESULT lError; H245TRACE (dwInst,4,"H245SetLocalCap <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* check for valid parameters */ if (pTotCap == NULL || pCapId == NULL || ((*pCapId > H245_MAX_CAPID) && (*pCapId != H245_INVALID_CAPID)) || pTotCap->Dir < H245_CAPDIR_LCLRX || pTotCap->Dir > H245_CAPDIR_LCLRXTX || pTotCap->ClientType < H245_CLIENT_NONSTD || pTotCap->ClientType > H245_CLIENT_MUX_H2250) { H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet; // Don't trust the user filled-in data type! pTotCap->DataType = DataTypeMap[pTotCap->ClientType]; /* if it's a MUX type handle here */ if (pTotCap->DataType == H245_DATA_MUX) { // Add multiplex capability if (pTermCapSet->bit_mask & multiplexCapability_present) { del_mux_cap(pTermCapSet); } *pCapId = pTotCap->CapId = 0; lError = set_mux_cap(pInstance, pTermCapSet, pTotCap); #if defined(_DEBUG) if (lError == H245_ERROR_OK) { // Validate mux capability if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap)) { // Bad mux capability - delete it del_mux_cap(pTermCapSet); lError = H245_ERROR_ASN1; } } #endif // (DEBUG) } else if (*pCapId == 0 || *pCapId == H245_INVALID_CAPID) { // Assign the next never-used cap id if (pInstance->API.LocalCapIdNum == H245_INVALID_CAPID) { // All possible capability identifiers have been assigned H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_MAXTBL)); InstanceUnlock(pInstance); return H245_ERROR_MAXTBL; } *pCapId = pInstance->API.LocalCapIdNum; /* insert in the new capability in the local capability set table */ pTotCap->CapId = *pCapId; lError = set_capability(pInstance, pTermCapSet, pTotCap); #if defined(_DEBUG) if (lError == H245_ERROR_OK) { // Validate capability if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap)) { // Bad capability - delete it H245DelLocalCap(dwInst, *pCapId); lError = H245_ERROR_ASN1; } } #endif // (DEBUG) if (lError == H245_ERROR_OK) pInstance->API.LocalCapIdNum++; } else { /* insert in the new capability in the local capability set table */ pTotCap->CapId = *pCapId; lError = set_capability(pInstance, pTermCapSet, pTotCap); #if defined(_DEBUG) if (lError == H245_ERROR_OK) { // Validate capability if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap)) { // Bad capability - delete it H245DelLocalCap(dwInst, *pCapId); lError = H245_ERROR_ASN1; } } #endif // (DEBUG) } if (lError != H245_ERROR_OK) { H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(lError)); pTotCap->CapId = *pCapId = H245_INVALID_CAPID; } else { H245TRACE (dwInst,4,"H245SetLocalCap -> OK"); } InstanceUnlock(pInstance); return lError; } // H245SetLocalCap() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245DelLocalCap * * DESCRIPTION Delete Local Cap simply disables the cap.. it * will not be updated until the client issues * H245SendTermCaps * * * HRESULT H245DelLocalCap( * H245_INST_T dwInst, * H245_CAPID_T CapId * ) * * Description: * This function allows the client to delete a specific * capability id in the H.245 subsystem. * * Note: This function does not communicate this update * to the remote peer until the client calls H245SendTermCaps. * * Input * dwInst Instance handle returned by H245GetInstanceId * CapId Cap Id the client wishes to remove from the * capability table. * * If an error occurs no action is taken and the CapId the * client wished to delete is not changed. * * Call Type: * Synchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK Capability deleted * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * * See Also: * H245SetLocalCap * H245SendTermCaps * H245EnumCaps * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245DelLocalCap ( H245_INST_T dwInst, H245_CAPID_T CapId ) { register struct InstanceStruct *pInstance; struct TerminalCapabilitySet *pTermCapSet; CapabilityTableLink pCapLink; HRESULT lError = H245_ERROR_OK; H245TRACE (dwInst,4,"H245DelLocalCap <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet; if (CapId == 0) { // Delete multiplex capability del_mux_cap(pTermCapSet); } else { /* (TBC) if I delete my capability id.. what about simultaneous caps ?? */ /* should I go through the list and deactivate them ?? */ pCapLink = find_capid_by_entrynumber (pTermCapSet, CapId); if (pCapLink) { // Delete terminal capability disable_cap_link (pCapLink); } else { lError = H245_ERROR_PARAM; } } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245DelLocalCap -> OK"); InstanceUnlock(pInstance); return lError; } // H245DelLocalCap() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245SetCapDescriptor * * DESCRIPTION * * HRESULT H245SetCapDescriptor ( * H245_INST_T dwInst, * H245_CAPDESC_T *pCapDesc, * H245_CAPDESCID_T *pCapDescId (* Optional *) * ) * Description: * This procedure is called to set local capability descriptors. * It will return a capability descriptor id in the parameter * *pCapDescId if it is non null. * * Note: * These capabilities are communicated via the H245SendTermCaps * API call. Any updates to the CapDescriptor table (either * additions or deletions ) will not be communicated to the * remote side until the H245SendTermCaps call is made. * * Input * dwInst Instance handle returned by H245Init * CapDesc This is the capability Descriptor you wish * to set * Output * pCapDescId optional: Capability id that will be returned. * * Call Type: * Synchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK * H245_ERROR_INVALID_CAPID Capid used in CapDesc was not * registred * H245_ERROR_MAXTB Out of table space to store Descriptor * H245_ERROR_PARAM Descriptor is too long or not valid * H245_ERROR_NOMEM * H245_ERROR_INVALID_INST * * See Also: * H245DelCapDescriptor * H245SendTermCaps * * ASSUMES: * SimCapId is the array entry point in the apabilityDescriptors * array.. this has a limitation, in that you can never wrap the * array at 256.. this will be cleaned up when array is turned into * linked list. * *****************************************************************************/ H245DLL HRESULT H245SetCapDescriptor ( H245_INST_T dwInst, H245_CAPDESC_T *pCapDesc, H245_CAPDESCID_T *pCapDescId ) { register struct InstanceStruct *pInstance; HRESULT lError; H245TRACE (dwInst,4,"H245SetCapDescriptor <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* must have capdescriptor && */ /* length must be less than 256 */ if (pCapDesc == NULL || pCapDesc->Length >= 256 || pCapDescId == NULL) { H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } if (*pCapDescId >= 256) { // Assign the next never-used cap id if (pInstance->API.LocalCapDescIdNum >= 256) { // All possible capability identifiers have been assigned H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(H245_ERROR_MAXTBL)); InstanceUnlock(pInstance); return H245_ERROR_MAXTBL; } *pCapDescId = pInstance->API.LocalCapDescIdNum; /* insert in the new capability descriptor in the local capability descriptor table */ lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId, &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet); #if defined(_DEBUG) if (lError == H245_ERROR_OK) { // Validate Capability Descriptor if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap)) { // Capability Descriptor Invalid - delete it H245DelCapDescriptor(dwInst, *pCapDescId); lError = H245_ERROR_ASN1; } } #endif // (DEBUG) if (lError == H245_ERROR_OK) pInstance->API.LocalCapDescIdNum++; } else { /* insert in the new capability in the local capability set table */ lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId, &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet); #if defined(_DEBUG) if (lError == H245_ERROR_OK) { // Validate Capability Descriptor if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap)) { // Capability Descriptor Invalid - delete it H245DelCapDescriptor(dwInst, *pCapDescId); lError = H245_ERROR_ASN1; } } #endif // (DEBUG) } if (lError != H245_ERROR_OK) { H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(lError)); *pCapDescId = H245_INVALID_CAPDESCID; } else { H245TRACE (dwInst,4,"H245CapDescriptor -> OK"); } InstanceUnlock(pInstance); return lError; } // H245SetCapDescriptor() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245DelCapDescriptor * * DESCRIPTION * * HRESULT H245DelCapDescriptor ( * H245_INST_T dwInst, * H245_CAPDESCID_T CapDescId * ) * Description: * This procedure is called to delete local capability descriptors. * * Note: * These capabilities are communicated via the * H245SendTermCaps API call. Any updates to the * CapDescriptor table (either additions or deletions ) * will not be communicated to the remote side until the * H245SendTermCaps call is made. * * Input * dwInst Instance handle returned by H245Init * CapDescId This is the capability Descriptor you wish * to delete * Call Type: * Synchronous * * Return Values: * See Errors * Errors: * H245_ERROR_OK * H245_ERROR_INVALID_INST * * See Also: * H245SetCapDescriptor * H245SendTermCaps * * ASSUMES: * * SimCapId is the array entry point in the apabilityDescriptors * array.. this has a limitation, in that you can never wrap the * array at 256.. this will be cleaned up when array is turned into * linked list. * * *****************************************************************************/ H245DLL HRESULT H245DelCapDescriptor ( H245_INST_T dwInst, H245_CAPDESCID_T CapDescId ) { register struct InstanceStruct *pInstance; CapabilityDescriptor *p_cap_desc; struct TerminalCapabilitySet *pTermCapSet; unsigned int uId; H245TRACE (dwInst,4,"H245DelCapDescriptor <-"); if (CapDescId >= 256) { H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId); return H245_ERROR_INVALID_CAPDESCID; } /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"API:H24DelCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* get pointer to Capability Descriptor */ p_cap_desc = NULL; pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet; for (uId = 0; uId < pTermCapSet->capabilityDescriptors.count; ++uId) { if (pTermCapSet->capabilityDescriptors.value[uId].capabilityDescriptorNumber == CapDescId) { p_cap_desc = &pTermCapSet->capabilityDescriptors.value[uId]; break; } } if (p_cap_desc == NULL || p_cap_desc->smltnsCpblts == NULL || (p_cap_desc->bit_mask & smltnsCpblts_present) == 0) { H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId); InstanceUnlock(pInstance); return H245_ERROR_INVALID_CAPDESCID; } /* free up the list */ dealloc_simultaneous_cap (p_cap_desc); /* (TBC) what if you've removed the last simultaneous cap ? */ /* in this case.. the count does not go down.. it simply */ /* removes the cap descriptor bit from the table.. */ H245TRACE (dwInst,4,"H245DelCapDescriptor -> OK"); InstanceUnlock(pInstance); return H245_ERROR_OK; } // H245DelCapDescriptor() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245SendTermCaps * * DESCRIPTION * * HRESULT * H245SendTermCaps ( * H245_INST_T dwInst, * DWORD dwTransId * ) * * Description: * * Called to send terminal capabilities to the remote H.245 peer. * When remote capabilities are receive the client will be * notified by the H245_IND_CAP indication. When remote side has * acknowledged the local terminal capabilities and has responded * with their terminal capabilities the client will receive an * H245_CONF_ TERMCAP. Between H245Init and H245SendTermCap the * client may call H245SetLocalCap to register capabilities. * These capabilities will not be registered to the remote side * until H245SendTermCap has been called. * * Note: As required by the H245 specification, Mutliplex * capabilities, and Capability descriptors must be * loaded before the first capability PDU is sent. * * Once H245SendTermCap is called, any subsequent calls to * H245SetLocalTermCap will result in that capability being * communicated to the remote H.245 peer. * * Input * dwInst Instance handle returned by * H245GetInstanceId * dwTransId User supplied object used to identify * this request in the asynchronous * response to this call. * Call Type: * Asynchronous * * Return Values: * See Errors * * Callbacks: * H245_CONF_TERMCAP * * Errors: * H245_ERROR_OK Function succeeded * H245_ERROR_NOMEM * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * H245_ERROR_NO_MUX_CAPS no Mux capabilities have been set yet * H245_ERROR_NO_CAPDESC no Capability Descriptors have been set * * See Also: * H245SetLocalCap * H245Init * * callbacks * * H245_IND_CAP * H245_IND_CAPDESC * H245_IND_CAP_DEL * H245_IND_CAPDESC_DEL * * *****************************************************************************/ H245DLL HRESULT H245SendTermCaps ( H245_INST_T dwInst, DWORD_PTR dwTransId ) { struct InstanceStruct *pInstance; Tracker_T *pTracker; HRESULT lError; unsigned char TermCapData = TRUE; struct TerminalCapabilitySet_capabilityTable TermCap = {0}; H245TRACE(dwInst,4,"H245SendTermCaps <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* must have mux parameters set */ if ((pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & multiplexCapability_present) == 0) { H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_MUX_CAPS)); InstanceUnlock(pInstance); return H245_ERROR_NO_MUX_CAPS; } /* must have capability descriptors set */ if (!(pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & capabilityDescriptors_present)) { H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_CAPDESC)); InstanceUnlock(pInstance); return H245_ERROR_NO_CAPDESC; } if (!(pTracker = alloc_link_tracker (pInstance, API_TERMCAP_T, dwTransId, API_ST_WAIT_RMTACK, API_CH_ALLOC_UNDEF, API_CH_TYPE_UNDEF, 0, H245_INVALID_CHANNEL, H245_INVALID_CHANNEL, 0))) { H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } pdu_req_termcap_set (&pInstance->API.PDU_LocalTermCap, 0); TermCap.next = pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable; pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = &TermCap; TermCap.value.bit_mask = capability_present; TermCap.value.capabilityTableEntryNumber = pInstance->API.LocalCapIdNum; TermCap.value.capability.choice = Capability_nonStandard_chosen; TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice = h221NonStandard_chosen; TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = 0xB5; TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension = 0x42; TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = 0x8080; TermCap.value.capability.u.Capability_nonStandard.data.value = &TermCapData; TermCap.value.capability.u.Capability_nonStandard.data.length = sizeof(TermCapData); lError = FsmOutgoing(pInstance, &pInstance->API.PDU_LocalTermCap, (DWORD_PTR)pTracker); pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = TermCap.next; if (lError != H245_ERROR_OK) H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(lError)); else H245TRACE(dwInst,4,"H245SendTermCaps -> OK"); InstanceUnlock(pInstance); return lError; } // H245SendTermCaps() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245EnumCaps * * DESCRIPTION * * HRESULT H245EnumCaps ( * DWORD dwInst, * DWORD dwTransId, * H245_CAPDIR_T Direction, * H245_DATA_T DataType, * H245_CLIENT_T ClientType, * H245_CAP_CALLBACK_T CallBack * ) * * * Callback: * CallBack ( * DWORD dwTransId, * H245_TOTCAP_T *pTotCap, * ) * * Description: * * This function calls the H.245 client back for every * capability as defined in the API call that complies with the * request. If the DataType parameter is set to 0 all of the * caps types are returned (either local or remote based on the * Direction parameter) no mater what is in the ClientType * parameter. If the ClientType parameter is 0, it will return * all of the capabilities of the given DataType. * * The user supplied call back is called within the context of * the call, therefor the call will be considered synchronous. * * Input * dwInst Instance handle returned by H245Init * Direction Local/Remote Receive, Transmit, or Receive and * Transmit * DataType Type of data (Audio, Video, Data, etc.) * ClientType Client type (H.262, G.711. etc. ). * dwTransId User supplied object used to identify this * request in the callback. * * CallBack Output * dwTransId Identical to dwTransId passed in H245EnumCaps * pTotCap Pointer one of the capabilities. * * Note: TotCap parameter must be copied in the callback. This * data structure is reused for each callback. * * Call Type: * Synchronous Callback - i.e. called back in the context of * the API call * * Errors: * H245_ERROR_OK * H245_ERROR_PARAM One or more parameters were invalid * H245_ERROR_INVALID_INST dwInst is not a valid instance handle. * * See Also: * H245SetLocalCap * H245ReplLocalCap * * callback * * H245_IND_CAP * H245_IND_CAPDESC * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245EnumCaps ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_CAPDIR_T Direction, H245_DATA_T DataType, H245_CLIENT_T ClientType, H245_CAP_CALLBACK_T pfCapCallback, H245_CAPDESC_CALLBACK_T pfCapDescCallback ) { register struct InstanceStruct *pInstance; struct TerminalCapabilitySet *pTermCapSet; CapabilityTableLink pCapLink; int lcl_rmt; H245_TOTCAP_T totcap; int nResult = 0; H245TRACE (dwInst,4,"H245EnumCaps <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* check for callback routine */ if (pfCapCallback == NULL && pfCapDescCallback == NULL) { H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } /* ok... check the direction.. either remote or local caps.. */ switch (Direction) { case H245_CAPDIR_RMTRX: case H245_CAPDIR_RMTTX: case H245_CAPDIR_RMTRXTX: pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet; lcl_rmt = H245_REMOTE; break; case H245_CAPDIR_LCLRX: case H245_CAPDIR_LCLTX: case H245_CAPDIR_LCLRXTX: pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet; lcl_rmt = H245_LOCAL; break; /* must be either local or remote */ // case H245_CAPDIR_DONTCARE: default: H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } if (pfCapCallback) { if (pTermCapSet->bit_mask & multiplexCapability_present && build_totcap_from_mux(&totcap, &pTermCapSet->multiplexCapability, Direction) == H245_ERROR_OK) { (*pfCapCallback)(dwTransId, &totcap); } if (ClientType == H245_CLIENT_DONTCARE) { if (DataType == H245_DATA_DONTCARE) { for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next) { /* if capability is present */ if (pCapLink->value.bit_mask & capability_present && build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK) { nResult = (*pfCapCallback)(dwTransId, &totcap); } } // for } // if else { for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next) { /* if capability is present */ if (pCapLink->value.bit_mask & capability_present && build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK && totcap.DataType == DataType) { nResult = (*pfCapCallback)(dwTransId, &totcap); } } // for } // else } // if else { if (DataType == H245_DATA_DONTCARE) { for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next) { /* if capability is present */ if (pCapLink->value.bit_mask & capability_present && build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK && totcap.ClientType == ClientType) { nResult = (*pfCapCallback)(dwTransId, &totcap); } /* if cap match */ } // for } // if else { for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next) { /* if capability is present */ if (pCapLink->value.bit_mask & capability_present && build_totcap_from_captbl(&totcap,pCapLink,lcl_rmt) == H245_ERROR_OK && totcap.ClientType == ClientType && totcap.DataType == DataType) { nResult = (*pfCapCallback)(dwTransId, &totcap); } } // for } // else } // else } // if (pfCapCallback) if (pfCapDescCallback) { // Convert CapabilityDescriptor format to H245_CAPDESC_T format unsigned int uCapDesc; register SmltnsCpbltsLink pSimCap; register unsigned int uAltCap; H245_TOTCAPDESC_T TotCapDesc; for (uCapDesc = 0; uCapDesc < pTermCapSet->capabilityDescriptors.count && nResult == 0; ++uCapDesc) { if (pTermCapSet->capabilityDescriptors.value[uCapDesc].bit_mask & smltnsCpblts_present) { ASSERT(pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber <= 256); TotCapDesc.CapDesc.Length = 0; pSimCap = pTermCapSet->capabilityDescriptors.value[uCapDesc].smltnsCpblts; ASSERT(pSimCap != NULL); while (pSimCap) { if (TotCapDesc.CapDesc.Length >= H245_MAX_SIMCAPS) { H245TRACE (dwInst,1,"H245EnumCaps -> Number of simutaneous capabilities exceeds H245_MAX_SIMCAPS"); InstanceUnlock(pInstance); return H245_ERROR_MAXTBL; } if (pSimCap->value.count > H245_MAX_ALTCAPS) { H245TRACE (dwInst,1,"H245EnumCaps -> Number of alternative capabilities exceeds H245_MAX_ALTCAPS"); InstanceUnlock(pInstance); return H245_ERROR_MAXTBL; } TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].Length = (WORD) pSimCap->value.count; for (uAltCap = 0; uAltCap < pSimCap->value.count; ++uAltCap) { TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].AltCaps[uAltCap] = pSimCap->value.value[uAltCap]; } TotCapDesc.CapDesc.Length++; pSimCap = pSimCap->next; } // while TotCapDesc.CapDescId = pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber; nResult = pfCapDescCallback(dwTransId, &TotCapDesc); } // if } // for } // if (pfCapDescCallback) H245TRACE (dwInst,4,"H245EnumCaps -> OK"); InstanceUnlock(pInstance); return H245_ERROR_OK; } // H245EnumCaps() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245GetCaps * * DESCRIPTION * * RETURN: * *****************************************************************************/ static H245_TOTCAP_T * * ppTotCapGlobal; static unsigned long dwTotCapLen; static unsigned long dwTotCapMax; static H245_TOTCAPDESC_T * * ppCapDescGlobal; static unsigned long dwCapDescLen; static unsigned long dwCapDescMax; static HRESULT dwGetCapsError; static int GetCapsCapCallback(DWORD_PTR dwTransId, H245_TOTCAP_T *pTotCap) { H245_TOTCAP_T *pNewCap; if (dwGetCapsError == H245_ERROR_OK) { if (dwTotCapLen >= dwTotCapMax) { dwGetCapsError = H245_ERROR_MAXTBL; } else { dwGetCapsError = H245CopyCap(&pNewCap, pTotCap); if (dwGetCapsError == H245_ERROR_OK) { *ppTotCapGlobal++ = pNewCap; ++dwTotCapLen; } } } return 0; } // GetCapsCapCallback() static int GetCapsCapDescCallback(DWORD_PTR dwTransId, H245_TOTCAPDESC_T *pCapDesc) { H245_TOTCAPDESC_T *pNewCapDesc; if (dwGetCapsError == H245_ERROR_OK) { if (dwCapDescLen >= dwCapDescMax) { dwGetCapsError = H245_ERROR_MAXTBL; } else { dwGetCapsError = H245CopyCapDescriptor(&pNewCapDesc,pCapDesc); { *ppCapDescGlobal++ = pNewCapDesc; ++dwCapDescLen; } } } return 0; } // GetCapsCapDescCallback() H245DLL HRESULT H245GetCaps ( H245_INST_T dwInst, H245_CAPDIR_T Direction, H245_DATA_T DataType, H245_CLIENT_T ClientType, H245_TOTCAP_T * * ppTotCap, unsigned long * pdwTotCapLen, H245_TOTCAPDESC_T * * ppCapDesc, unsigned long * pdwCapDescLen ) { register struct InstanceStruct *pInstance; H245_CAP_CALLBACK_T CapCallback; H245_CAPDESC_CALLBACK_T CapDescCallback; H245TRACE (dwInst,4,"H245GetCaps <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } dwTotCapLen = 0; if (ppTotCap == NULL || pdwTotCapLen == NULL || *pdwTotCapLen == 0) { CapCallback = NULL; } else { CapCallback = GetCapsCapCallback; ppTotCapGlobal = ppTotCap; dwTotCapMax = *pdwTotCapLen; } dwCapDescLen = 0; if (ppCapDesc == NULL || pdwCapDescLen == NULL || *pdwCapDescLen == 0) { CapDescCallback = NULL; } else { CapDescCallback = GetCapsCapDescCallback; ppCapDescGlobal = ppCapDesc; dwCapDescMax = *pdwCapDescLen; } /* check parameters */ if (CapCallback == NULL && CapDescCallback == NULL) { H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } dwGetCapsError = H245_ERROR_OK; H245EnumCaps(dwInst, 0, Direction, DataType, ClientType, CapCallback, CapDescCallback); if (pdwTotCapLen) *pdwTotCapLen = dwTotCapLen; if (pdwCapDescLen) *pdwCapDescLen = dwCapDescLen; if (dwGetCapsError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245GetCaps -> %s", map_api_error(dwGetCapsError)); else H245TRACE (dwInst,4,"H245GetCaps -> OK"); InstanceUnlock(pInstance); return H245_ERROR_OK; } // H245GetCaps() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CopyCap * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CopyCap (H245_TOTCAP_T **ppDestTotCap, const H245_TOTCAP_T *pTotCap) { POBJECTID pObjectTo; POBJECTID pObjectFrom; HRESULT Status; if (ppDestTotCap == NULL) return H245_ERROR_PARAM; *ppDestTotCap = NULL; if (pTotCap == NULL) return H245_ERROR_PARAM; switch (pTotCap->ClientType) { case H245_CLIENT_NONSTD: case H245_CLIENT_VID_NONSTD: case H245_CLIENT_AUD_NONSTD: case H245_CLIENT_MUX_NONSTD: if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen) { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245_NonStd.data.length + ObjectIdLength(&pTotCap->Cap.H245_NonStd.nonStandardIdentifier) * sizeof(OBJECTID)); } else { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245_NonStd.data.length); } if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; if (pTotCap->Cap.H245_NonStd.data.length != 0) { (*ppDestTotCap)->Cap.H245_NonStd.data.value = (unsigned char *)(*ppDestTotCap + 1); memcpy((*ppDestTotCap)->Cap.H245_NonStd.data.value, pTotCap->Cap.H245_NonStd.data.value, pTotCap->Cap.H245_NonStd.data.length); } else { (*ppDestTotCap)->Cap.H245_NonStd.data.value = NULL; } if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen && pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object != NULL) { pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) + pTotCap->Cap.H245_NonStd.data.length); (*ppDestTotCap)->Cap.H245_NonStd.nonStandardIdentifier.u.object = pObjectTo; pObjectFrom = pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object; do { pObjectTo->value = pObjectFrom->value; pObjectTo->next = pObjectTo + 1; ++pObjectTo; } while ((pObjectFrom = pObjectFrom->next) != NULL); --pObjectTo; pObjectTo->next = NULL; } break; case H245_CLIENT_DAT_NONSTD: if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen) { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length + ObjectIdLength(&pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID)); } else { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length); } if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; if (pTotCap->Cap.H245_NonStd.data.length != 0) { (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value = (unsigned char *)(*ppDestTotCap + 1); memcpy((*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value, pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value, pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length); } else { (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value = NULL; } if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen && pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object != NULL) { pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) + pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length); (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object = pObjectTo; pObjectFrom = pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object; do { pObjectTo->value = pObjectFrom->value; pObjectTo->next = pObjectTo + 1; ++pObjectTo; } while ((pObjectFrom = pObjectFrom->next) != NULL); --pObjectTo; pObjectTo->next = NULL; } break; case H245_CLIENT_DAT_T120: case H245_CLIENT_DAT_DSMCC: case H245_CLIENT_DAT_USERDATA: case H245_CLIENT_DAT_T434: case H245_CLIENT_DAT_H224: case H245_CLIENT_DAT_H222: if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.choice == DtPrtclCpblty_nnStndrd_chosen) { if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen) { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length + ObjectIdLength(&pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID)); } else { *ppDestTotCap = MemAlloc(sizeof(*pTotCap) + pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length); } if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; if (pTotCap->Cap.H245_NonStd.data.length != 0) { (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value = (unsigned char *)(*ppDestTotCap + 1); memcpy((*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value, pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value, pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length); } else { (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value = NULL; } if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen && pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object != NULL) { pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) + pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length); (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object = pObjectTo; pObjectFrom = pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object; do { pObjectTo->value = pObjectFrom->value; pObjectTo->next = pObjectTo + 1; ++pObjectTo; } while ((pObjectFrom = pObjectFrom->next) != NULL); --pObjectTo; pObjectTo->next = NULL; } } else { *ppDestTotCap = MemAlloc(sizeof(*pTotCap)); if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; } break; case H245_CLIENT_CONFERENCE: { NonStandardDataLink pList; NonStandardDataLink pFrom; NonStandardDataLink pTo; // Initialize Status here to prevent compiler warning "returning a possibly // uninitialized value" Status = H245_ERROR_NOMEM; *ppDestTotCap = MemAlloc(sizeof(*pTotCap)); if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; pList = NULL; (*ppDestTotCap)->Cap.H245Conference.nonStandardData = NULL; pFrom = pTotCap->Cap.H245Conference.nonStandardData; while (pFrom) { pTo = MemAlloc(sizeof(*pTo)); if (pTo == NULL) Status = H245_ERROR_NOMEM; if (pTo != NULL) { Status = CopyNonStandardParameter(&pTo->value, &pFrom->value); if (Status != H245_ERROR_OK) { MemFree(pTo); pTo = NULL; } } if (pTo == NULL) { while (pList) { pTo = pList; pList = pList->next; FreeNonStandardParameter(&pTo->value); MemFree(pTo); } MemFree(*ppDestTotCap); *ppDestTotCap = NULL; return Status; } pTo->next = pList; pList = pTo; pFrom = pFrom->next; } // while while (pList) { pTo = pList; pList = pList->next; pTo->next = (*ppDestTotCap)->Cap.H245Conference.nonStandardData; (*ppDestTotCap)->Cap.H245Conference.nonStandardData = pTo; } // while break; } case H245_CLIENT_MUX_H222: { VCCapabilityLink pList = NULL; VCCapabilityLink pFrom; VCCapabilityLink pTo; *ppDestTotCap = MemAlloc(sizeof(*pTotCap)); if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = NULL; pFrom = pTotCap->Cap.H245Mux_H222.vcCapability; while (pFrom) { pTo = MemAlloc(sizeof(*pTo)); if (pTo == NULL) { while (pList) { pTo = pList; pList = pList->next; MemFree(pTo); } MemFree(*ppDestTotCap); *ppDestTotCap = NULL; return H245_ERROR_NOMEM; } pTo->value = pFrom->value; pTo->next = pList; pList = pTo; pFrom = pFrom->next; } // while while (pList) { pTo = pList; pList = pList->next; pTo->next = (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability; (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = pList; } // while break; } case H245_CLIENT_MUX_H2250: *ppDestTotCap = MemAlloc(sizeof(*pTotCap)); if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; Status = CopyH2250Cap(&(*ppDestTotCap)->Cap.H245Mux_H2250, &pTotCap->Cap.H245Mux_H2250); if (Status != H245_ERROR_OK) { MemFree(*ppDestTotCap); *ppDestTotCap = NULL; return Status; } break; default: *ppDestTotCap = MemAlloc(sizeof(*pTotCap)); if (*ppDestTotCap == NULL) return H245_ERROR_NOMEM; **ppDestTotCap = *pTotCap; } // switch return H245_ERROR_OK; } // H245CopyCap() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245FreeCap * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245FreeCap (H245_TOTCAP_T * pTotCap) { if (pTotCap == NULL) { return H245_ERROR_PARAM; } switch (pTotCap->ClientType) { case H245_CLIENT_CONFERENCE: { NonStandardDataLink pList; NonStandardDataLink pTo; pList = pTotCap->Cap.H245Conference.nonStandardData; while (pList) { pTo = pList; pList = pList->next; FreeNonStandardParameter(&pTo->value); MemFree(pTo); } } break; case H245_CLIENT_MUX_H222: { VCCapabilityLink pList; VCCapabilityLink pTo; pList = pTotCap->Cap.H245Mux_H222.vcCapability; while (pList) { pTo = pList; pList = pList->next; MemFree(pTo); } } break; case H245_CLIENT_MUX_H2250: FreeH2250Cap(&pTotCap->Cap.H245Mux_H2250); break; } // switch MemFree(pTotCap); return 0; } // H245FreeCap() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CopyCapDescriptor * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CopyCapDescriptor (H245_TOTCAPDESC_T **ppDestCapDesc, const H245_TOTCAPDESC_T *pCapDesc) { if (ppDestCapDesc == NULL) return H245_ERROR_PARAM; *ppDestCapDesc = NULL; if (pCapDesc == NULL) return H245_ERROR_PARAM; *ppDestCapDesc = MemAlloc(sizeof(**ppDestCapDesc)); if (*ppDestCapDesc == NULL) return H245_ERROR_NOMEM; **ppDestCapDesc = *pCapDesc; return H245_ERROR_OK; } // H245CopyCapDescriptor() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245FreeCapDescriptor * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245FreeCapDescriptor (H245_TOTCAPDESC_T * pCapDesc) { if (pCapDesc == NULL) { return H245_ERROR_PARAM; } MemFree(pCapDesc); return 0; } // H245FreeCapDescriptor() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CopyMux * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL H245_MUX_T * H245CopyMux (const H245_MUX_T * pMux) { register unsigned int uLength; register H245_MUX_T *pNew; H2250LCPs_nnStndrdLink pList; H2250LCPs_nnStndrdLink pFrom; H2250LCPs_nnStndrdLink pTo; switch (pMux->Kind) { case H245_H222: uLength = sizeof(*pMux) + pMux->u.H222.programDescriptors.length + pMux->u.H222.streamDescriptors.length; pNew = MemAlloc(uLength); if (pNew != NULL) { *pNew = *pMux; if (pMux->u.H222.programDescriptors.length != 0) { pNew->u.H222.programDescriptors.value = (unsigned char *)(pNew + 1); memcpy(pNew->u.H222.programDescriptors.value, pMux->u.H222.programDescriptors.value, pMux->u.H222.programDescriptors.length); } else { pNew->u.H222.programDescriptors.value = NULL; } if (pMux->u.H222.streamDescriptors.length != 0) { pNew->u.H222.streamDescriptors.value = ((unsigned char *)pNew) + (uLength - pMux->u.H222.streamDescriptors.length); memcpy(pNew->u.H222.streamDescriptors.value, pMux->u.H222.streamDescriptors.value, pMux->u.H222.streamDescriptors.length); } else { pNew->u.H222.streamDescriptors.value = NULL; } } break; case H245_H223: pNew = MemAlloc(sizeof(*pMux) + pMux->u.H223.H223_NONSTD.data.length); if (pNew != NULL) { *pNew = *pMux; if (pMux->u.H223.H223_NONSTD.data.length != 0) { pNew->u.H223.H223_NONSTD.data.value = (unsigned char *)(pNew + 1); memcpy(pNew->u.H223.H223_NONSTD.data.value, pMux->u.H223.H223_NONSTD.data.value, pMux->u.H223.H223_NONSTD.data.length); } else { pNew->u.H223.H223_NONSTD.data.value = NULL; } } break; case H245_H2250: case H245_H2250ACK: // Caveat: assumes nonstandard list, mediaChannel and mediaControlChannel // in same place in both structures if (pMux->u.H2250.mediaChannelPresent && (pMux->u.H2250.mediaChannel.type == H245_IPSSR_UNICAST || pMux->u.H2250.mediaChannel.type == H245_IPLSR_UNICAST) && pMux->u.H2250.mediaChannel.u.ipSourceRoute.route != NULL && pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount != 0) { if (pMux->u.H2250.mediaControlChannelPresent && (pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST || pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) && pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL && pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0) { unsigned int uLength2; uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2; uLength2 = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2; pNew = MemAlloc(sizeof(*pMux) + uLength + uLength2); if (pNew != NULL) { *pNew = *pMux; pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1); pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route = pNew->u.H2250.mediaChannel.u.ipSourceRoute.route + uLength; memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route, pMux->u.H2250.mediaChannel.u.ipSourceRoute.route, uLength); memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route, pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route, uLength2); } } else { uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2; pNew = MemAlloc(sizeof(*pMux) + uLength); if (pNew != NULL) { *pNew = *pMux; pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1); memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route, pMux->u.H2250.mediaChannel.u.ipSourceRoute.route, uLength); } } } else if (pMux->u.H2250.mediaControlChannelPresent && (pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST || pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) && pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL && pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0) { uLength = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2; pNew = MemAlloc(sizeof(*pMux) + uLength); if (pNew != NULL) { *pNew = *pMux; pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1); memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route, pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route, uLength); } } else { pNew = MemAlloc(sizeof(*pMux)); if (pNew != NULL) { *pNew = *pMux; } } pList = NULL; pNew->u.H2250.nonStandardList = NULL; pFrom = pMux->u.H2250.nonStandardList; while (pFrom) { pTo = MemAlloc(sizeof(*pTo)); if (pTo != NULL) { if (CopyNonStandardParameter(&pTo->value, &pFrom->value) != H245_ERROR_OK) { MemFree(pTo); pTo = NULL; } } if (pTo == NULL) { while (pList) { pTo = pList; pList = pList->next; FreeNonStandardParameter(&pTo->value); MemFree(pTo); } MemFree(pNew); return NULL; } pTo->next = pList; pList = pTo; pFrom = pFrom->next; } // while while (pList) { pTo = pList; pList = pList->next; pTo->next = pNew->u.H2250.nonStandardList; pNew->u.H2250.nonStandardList = pTo; } // while break; // case H245_VGMUX: default: pNew = MemAlloc(sizeof(*pMux)); if (pNew != NULL) { *pNew = *pMux; } } // switch return pNew; } // H245CopyMux() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245FreeMux * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245FreeMux (H245_MUX_T * pMux) { H2250LCPs_nnStndrdLink pLink; if (pMux == NULL) { return H245_ERROR_PARAM; } switch (pMux->Kind) { case H245_H2250: case H245_H2250ACK: // Caveat: assumes nonstandard list is in same place in both structures while (pMux->u.H2250.nonStandardList) { pLink = pMux->u.H2250.nonStandardList; pMux->u.H2250.nonStandardList = pLink->next; FreeNonStandardParameter(&pLink->value); MemFree(pLink); } break; } // switch MemFree(pMux); return 0; } // H245FreeMux() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245OpenChannel * * DESCRIPTION * * HRESULT H245OpenChannel ( * H245_INST_T dwInst, * DWORD dwTransId, * DWORD dwTxChannel, * H245_TOTCAP_T *pTxMode, * H245_MUX_T *pTxMux, * H245_TOTCAP_T *pRxMode, (* bi-dir only *) * H245_MUX_T *pRxMux (* bi-dir only *) * ) * * Description: * This function is called to open either a uni-directional, * or a bi-directional channel. The mode to the remote peer * will be designated by the *pTxMode.. To open a bi-directional * channel the client selects a non-null receive mode ( *pRxMode). * This mode indicates to the remote peer its transmit mode. * For uni-directional channels the *pRxMode must be NULL. * * The dwTxChannel parameter indicates which forward logical * channel the H.245 will open. If this is a bi-directional * channel open, the confirm will indicate the logical channel * specified in the open request by the remote terminal * * The pMux parameter will contain a pointer to H.223, H.222, * VGMUX, or other logical channel parameters depending on the * system configuration. (see H245_H223_LOGICAL_PARAM). This * may be NULL for some clients. * * Note: * 7 pTxMode->CapId is of no significance in this call. * It is not used * 7 pRxMode->CapId is of no significance in this call. * It is not used * * Input * dwInst Instance handle returned by H245Init * dwTransId User supplied object used to identify this * request in the asynchronous confirm to this * call. * dwTxChannel Logical Channel number for forward (Transmit) * Channel * pTxMode The capability (mode) used for transmission * to the remote peer. * Note: pTxMode->CapId is ignored * pTxMux The formward logical channel parameters * for H.223, H.222, VGMUX, etc. * pRxMode Optional: Transmit mode specified for the * remote terminal. This is used only for * Bi-directional Channel opens and must be set * to NULL if opening a Uni-directional channel. * Note: pRxMode->CapId is ignored * pRxMux Optional : The reverse logical channel * parameters for H.223, H.222, VGMUX, etc. or * NULL. * * Call Type: * Asynchronous * * Return Values: * See Errors * * Callback: * H245_CONF_OPEN * H245_CONF_NEEDRSP_OPEN Bi-Directional Channels only * waiting for confirm. * Errors: * H245_ERROR_OK * H245_ERROR_PARAM One or more parameters were * invalid * H245_ERROR_BANDWIDTH_OVERFLOW Open would exceed bandwidth * limitations * H245_ERROR_NOMEM * H245_ERROR_NORESOURCE Out of resources, too many * open channels or outside scope * of simultaneous capabilities. * H245_ERROR_INVALID_INST dwInst is not a valid instance * handle * H245_ERROR_INVALID_STATE Not in the proper state to * issue open * H245_ERROR_CHANNEL_INUSE Channel is currently open * * See Also: * H245CloseChannel * H245OpenChannelIndResp * H245OpenChannelConfResp * * callback * * H245_CONF_OPEN * H245_CONF_NEEDRSP_OPEN * H245_IND_OPEN_CONF * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245OpenChannel ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_CHANNEL_T wTxChannel, const H245_TOTCAP_T * pTxMode, const H245_MUX_T * pTxMux, H245_PORT_T dwTxPort, // optional const H245_TOTCAP_T * pRxMode, // bi-dir only const H245_MUX_T * pRxMux, // bi-dir only const H245_ACCESS_T * pSeparateStack // optional ) { register struct InstanceStruct *pInstance; HRESULT lError; Tracker_T *pTracker; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245OpenChannel <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* must have performed Master Slave Negotiation at this point */ if (pInstance->Configuration == H245_CONF_H324 && pInstance->API.MasterSlave != APIMS_Master && pInstance->API.MasterSlave != APIMS_Slave) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_STATE)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_STATE; } pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL); /* channel is currently in use */ if (pTracker) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_CHANNEL_INUSE)); InstanceUnlock(pInstance); return H245_ERROR_CHANNEL_INUSE; } if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(*pPdu)); /* lock in the transmit side.. */ /* wait until OpenChannelConfResp to setup RxChannel */ lError = pdu_req_open_channel(pPdu, wTxChannel, dwTxPort, /* forward port */ pTxMode, pTxMux, pRxMode, pRxMux, pSeparateStack); if (lError != H245_ERROR_OK) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError)); free_pdu_req_open_channel(pPdu, pTxMode, pRxMode); InstanceUnlock(pInstance); return lError; } /* if allocation error */ if (!(pTracker = alloc_link_tracker (pInstance, API_OPEN_CHANNEL_T, dwTransId, API_ST_WAIT_RMTACK, API_CH_ALLOC_LCL, (pRxMode?API_CH_TYPE_BI:API_CH_TYPE_UNI), pTxMode->DataType, wTxChannel, H245_INVALID_CHANNEL, 0))) { H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM)); free_pdu_req_open_channel(pPdu, pTxMode, pRxMode); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); free_pdu_req_open_channel(pPdu, pTxMode, pRxMode); if (lError != H245_ERROR_OK) { unlink_dealloc_tracker (pInstance, pTracker); H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError)); } else H245TRACE (dwInst,4,"H245OpenChannel -> OK"); InstanceUnlock(pInstance); return lError; } // H245OpenChannel() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245OpenChannelAccept * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245OpenChannelAccept ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN const H245_MUX_T * pRxMux, // optional H2250LogicalChannelAckParameters H245_CHANNEL_T wTxChannel, // bi-dir only const H245_MUX_T * pTxMux, // bi-dir only optional H2250LogicalChannelParameters H245_PORT_T dwTxPort, // bi-dir only optional const H245_ACCESS_T * pSeparateStack // optional ) { register struct InstanceStruct *pInstance; Tracker_T * pTracker; MltmdSystmCntrlMssg * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245OpenChannelAccept <- wRxChannel=%d wTxChannel=%d", wRxChannel, wTxChannel); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if channel not found in tracker list */ /* note that it looks for given channel given who alloced it */ pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT); /* not locking tracker.. since no indication will come in until I issue the request */ if (!pTracker) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* if not open.. invalid op */ if (pTracker->TrackerType != API_OPEN_CHANNEL_T) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* if was uni open w/ TxChannel set.. error */ /* -or - */ /* if was bi open w/ !TxChannel set.. error */ /* AND it wasn't a reject */ if (pTracker->u.Channel.ChannelType == API_CH_TYPE_BI && wTxChannel == 0) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } /* for debug */ ASSERT (pTracker->u.Channel.RxChannel == wRxChannel); ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT); /* check state.. must be returning.. */ if (pTracker->State != API_ST_WAIT_LCLACK) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_STATE)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_STATE; } /* setup tracker object for new transaction */ pTracker->TransId = dwTransId; pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(*pPdu)); switch (pTracker->u.Channel.ChannelType) { case API_CH_TYPE_UNI: pTracker->State = API_ST_IDLE; pTracker->u.Channel.TxChannel = 0; lError = pdu_rsp_open_logical_channel_ack(pPdu, wRxChannel, pRxMux, 0, NULL, dwTxPort, pSeparateStack); if (lError != H245_ERROR_OK) { // If parameter error, we don't want to deallocate tracker MemFree (pPdu); InstanceUnlock(pInstance); return lError; } lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); break; case API_CH_TYPE_BI: pTracker->State = API_ST_WAIT_CONF; /* waiting for confirmation */ pTracker->u.Channel.TxChannel = wTxChannel; lError = pdu_rsp_open_logical_channel_ack(pPdu, wRxChannel, pRxMux, wTxChannel, pTxMux, dwTxPort, pSeparateStack); if (lError != H245_ERROR_OK) { // If parameter error, we don't want to deallocate tracker MemFree (pPdu); InstanceUnlock(pInstance); return lError; } lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); break; default: H245TRACE (dwInst,1,"H245OpenChannelAccept: Invalid Tracker Channel Type %d", pTracker->u.Channel.ChannelType); lError = H245_ERROR_FATAL; } // switch MemFree (pPdu); switch (lError) { case H245_ERROR_OK: H245TRACE (dwInst,4,"H245OpenChannelAccept -> OK"); break; default: // Deallocate tracker object for all errors except parameter error unlink_dealloc_tracker (pInstance, pTracker); // Fall-through to next case is intentional case H245_ERROR_PARAM: // If parameter error, we don't want to deallocate tracker H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(lError)); } // switch InstanceUnlock(pInstance); return lError; } // H245OpenChannelAccept() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245OpenChannelReject * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245OpenChannelReject ( H245_INST_T dwInst, H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN unsigned short wCause ) { register struct InstanceStruct *pInstance; Tracker_T * pTracker; MltmdSystmCntrlMssg * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245OpenChannelReject <- wRxChannel=%d", wRxChannel); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if channel not found in tracker list */ /* note that it looks for given channel given who alloced it */ pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT); /* not locking tracker.. since no indication will come in until I issue the request */ /* if not open.. invalid op */ if (pTracker == NULL || pTracker->TrackerType != API_OPEN_CHANNEL_T) { H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* for debug */ ASSERT (pTracker->u.Channel.RxChannel == wRxChannel); ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT); /* check state.. must be returning.. */ if (pTracker->State != API_ST_WAIT_LCLACK) { H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_STATE)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_STATE; } pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(*pPdu)); pdu_rsp_open_logical_channel_rej(pPdu, wRxChannel, wCause); switch (pTracker->u.Channel.ChannelType) { case API_CH_TYPE_UNI: lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); break; case API_CH_TYPE_BI: lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); break; default: H245TRACE (dwInst,1,"H245OpenChannelReject: Invalid Tracker Channel Type %d", pTracker->u.Channel.ChannelType); lError = H245_ERROR_FATAL; } // switch MemFree (pPdu); unlink_dealloc_tracker (pInstance, pTracker); if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245OpenChannelReject -> OK"); InstanceUnlock(pInstance); return lError; } // H245OpenChannelReject() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245CloseChannel * * DESCRIPTION * * HRESULT H245CloseChannel ( * H245_INST_T dwInst, * DWORD dwTransId, * DWORD wTxChannel, * ) * Description: * Called to close a channel upon which the client previously * issued an OpenChannel request. * * Input * dwInst Instance handle returned by H245Init * dwTransId User supplied object used to identify this * request in the asynchronous confirm to this * call. * wChannel Logical Channel Number to close * * Call Type: * Asynchronous * * Return Values: * See Errors * * Callbacks: * H245_CONF_CLOSE * Errors: * H245_ERROR_OK * H245_ERROR_PARAM wChannel is not a locally opened * channel * H245_ERROR_INVALID_INST dwInst is not a valid intance handle * H245_ERROR_NOT_CONNECTED * H245_ERROR_INVALID_CHANNEL * H245_ERROR_INVALID_OP Can not perform this operation on * this channel.(See H245CloseChannelReq) * See Also: * H245OpenChannel * H245OpenChannelIndResp * H245OpenChannelConfResp * H245CloseChannelReq * * callback * H245_CONF_CLOSE * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CloseChannel ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_CHANNEL_T wTxChannel ) { register struct InstanceStruct *pInstance; Tracker_T *pTracker; DWORD error; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245CloseChannel <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if channel not found in tracker list */ /* note that it looks for given channel given who alloced it */ pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL); /* not locking tracker.. since no indication will come in until I issue the request */ if (!pTracker) { H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_CHANNEL; } /* setup new tracker state */ pTracker->State = API_ST_WAIT_RMTACK; pTracker->TrackerType = API_CLOSE_CHANNEL_T; pTracker->TransId = dwTransId; if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* ok.. get pdu */ pdu_req_close_logical_channel(pPdu, wTxChannel, 0/* user */); error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); MemFree (pPdu); /* error.. so deallocate tracker structure */ if (error != H245_ERROR_OK) { unlink_dealloc_tracker (pInstance, pTracker); H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(error)); } else { H245TRACE (dwInst,4,"H245CloseChannel -> OK"); } InstanceUnlock(pInstance); return H245_ERROR_OK; } // H245CloseChannel() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245CloseChannelReq * * DESCRIPTION * * HRESULT H245CloseChannelReq ( * H245_INST_T dwInst, * DWORD dwTransId, * DWORD wChannel, * ) * Description: * Called to request the remote peer to close a logical channel * it previously opened * * Input * dwInst Instance handle returned by H245Init * dwTransId User supplied object used to identify this * request in the asynchronous confirm to this * call * wChannel Logical Channel Number to close * * Note: This is only asking permission. Even if the Close * Request is accepted the channel still has to be closed from * the remote side. (i.e. this does not close the channel it * only asked the remote side it issue a close) * * Call Type: * Asynchronous * * Return Values: * See Errors * * Callbacks: * H245_CONF_CLOSE * * Errors: * H245_ERROR_OK * H245_ERROR_PARAM wChannel is not a channel * opened by remote peer * H245_ERROR_INVALID_INST dwInst is not a valid instance * handle * H245_ERROR_NOT_CONNECTED * H245_ERROR_INVALID_CHANNEL * H245_ERROR_INVALID_OP Can not perform this operation * on this channel * (see H245CloseChannel) * See Also: * H245OpenChannel * H245OpenChannelIndResp * H245OpenChannelConfResp * H245CloseChannel * * callback * * H245_CONF_CLOSE * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CloseChannelReq ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_CHANNEL_T wRxChannel ) { register struct InstanceStruct *pInstance; Tracker_T *pTracker; DWORD error; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245CloseChannelReq <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if channel not found in tracker list */ /* note that it looks for given channel given who alloced it */ pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT); /* not locking tracker.. since no indication will come in until I issue the request */ if (!pTracker) { H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* verify state of tracker */ pTracker->State = API_ST_WAIT_RMTACK; pTracker->TrackerType = API_CLOSE_CHANNEL_T; pTracker->TransId = dwTransId; if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* ok.. get pdu */ pdu_req_request_close_channel(pPdu, wRxChannel); error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); MemFree (pPdu); if (error != H245_ERROR_OK) { unlink_dealloc_tracker (pInstance, pTracker); H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(error)); } else H245TRACE (dwInst,4,"H245CloseChannelReq -> OK"); InstanceUnlock(pInstance); return error; } // H245CloseChannelReq() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245CloseChannelReqResp * * DESCRIPTION * * HRESULT H245CloseChannelReqResp ( * H245_INST_T dwInst, * H245_ACC_REJ_T AccRej, * DWORD wChannel * ) * * Description: * This routine is called to accept or reject a * RequestChannelClose (H245_IND_REQ_CLOSE indication) from the * remote peer. The channel must have been locally opened. The * parameter AccRej is H245_ACC to accept or H245_REJ to reject * the close. The local client should follow this response with * a H245CloseChannel call. * * If there was a Release CloseChannelRequest event that * occurred during this transaction there error code returned * will be H245_ERROR_CANCELED. This indicates to the H.245 * client that no action should be taken. * * Input * dwInst Instance handle returned by H245GetInstanceId * AccRej this parameter contains either H245_ACC or * H245_REJ. This indicates to H.245 which * action to take. * wChannel Logical Channel Number to close * * Call Type: * Synchronous * * Return Values: * See Errors * Errors: * H245_ERROR_OK * H245_ERROR_PARAM * H245_ERROR_NOMEM * H245_ERROR_INVALID_CHANNEL * H245_ERROR_INVALID_OP Can not perform this operation on this * channel (see H245CloseChannel) * H245_ERROR_INVALID_INST dwInst is not a valid instance handle * H245_ERROR_CANCELED if release was received during the * processing of this request.. * See Also: * H245CloseChannel * * callback * * H245_IND_REQ_CLOSE * H245_IND_CLOSE * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CloseChannelReqResp ( H245_INST_T dwInst, H245_ACC_REJ_T AccRej, H245_CHANNEL_T wChannel ) { register struct InstanceStruct *pInstance; Tracker_T *pTracker; DWORD error; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245CloseChannelReqResp <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if channel not found in tracker list */ /* note that it looks for given channel given who alloced it */ pTracker = find_tracker_by_txchannel (pInstance, wChannel, API_CH_ALLOC_LCL); /* not locking tracker.. since no indication will come in until I issue the request */ if (!pTracker) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* if the request was canceled.. tell useer */ if (pTracker->State == API_ST_WAIT_LCLACK_CANCEL) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_CANCELED)); InstanceUnlock(pInstance); return H245_ERROR_CANCELED; } /* verify state of tracker */ if ((pTracker->State != API_ST_WAIT_LCLACK) || (pTracker->TrackerType != API_CLOSE_CHANNEL_T)) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } /* set the state to idle.. expect this side to close the channel next */ pTracker->State = API_ST_IDLE; if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* ok.. get pdu */ if (AccRej == H245_ACC) { pTracker = NULL; pdu_rsp_request_channel_close_ack(pPdu, wChannel); } else { pdu_rsp_request_channel_close_rej(pPdu, wChannel, AccRej); } error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); MemFree (pPdu); if (error != H245_ERROR_OK) H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(error)); else H245TRACE (dwInst,4,"H245CloseChannelReqResp ->"); InstanceUnlock(pInstance); return error; } // H245CloseChannelReqResp() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245SendLocalMuxTable * * DESCRIPTION * * HRESULT H245SendLocalMuxTable ( * H245_INST_T dwInst, * DWORD dwTransId, * H245_MUX_TABLE_T *pMuxTbl * ) * Description: * This routine is called to send a mux table to the remote * side. The remote side can either reject or accept each mux * table entry in a message. The confirm is sent back to the * calling H.245 client based on the acceptance or non * acceptance of each Mux table entry with H245_CONF_MUXTBL_SND. * * This is a fairly dangerous call, since the mux table * structure is a linked lise of mux table entries. Invalid * data structures could cause an access error. Example code is * supplied in the appendix. * Input * dwInst Instance handle returned by H245Init * dwTransId User supplied object used to identify * this request in the asynchronous * confirm to this call. * pMuxTbl Mux table entry structure * * Call Type: * Asynchronous * * Return Values: * See Errors * * Callbacks: * H245_CONF_MUXTBLSND * * Errors: * H245_ERROR_OK * H245_ERROR_INVALID_MUXTBLENTRY * H245_ERROR_PARAM * H245_ERROR_INVALID_INST * H245_ERROR_NOT_CONNECTED * H245_ERROR_NOMEM * * See Also: * APPENDIX Examples * * callback * * H245_CONF_MUXTBL_SND * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245SendLocalMuxTable ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_MUX_TABLE_T *pMuxTable ) { register struct InstanceStruct *pInstance; HRESULT lError; Tracker_T *pTracker; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245SendLocalMuxTable <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* make sure parameters ar ok.. */ if (!pMuxTable) { H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } /* allocate tracker for event */ pTracker = alloc_link_tracker (pInstance, API_SEND_MUX_T, dwTransId, API_ST_WAIT_RMTACK, API_CH_ALLOC_UNDEF, API_CH_TYPE_UNDEF, 0, H245_INVALID_CHANNEL, H245_INVALID_CHANNEL, 0); if (pTracker == NULL) { H245TRACE(dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } // Allocate PDU buffer pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)); if (pPdu == NULL) { H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",H245_ERROR_NOMEM); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); lError = pdu_req_send_mux_table(pInstance, pPdu, pMuxTable, 0, &pTracker->u.MuxEntryCount); if (lError == H245_ERROR_OK) { lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker); /* free the list just built */ free_mux_desc_list(pPdu->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend.multiplexEntryDescriptors); } /* free the pdu */ MemFree (pPdu); if (lError != H245_ERROR_OK) { unlink_dealloc_tracker (pInstance, pTracker); H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(lError)); } else H245TRACE (dwInst,4,"H245SendLocalMuxTable -> OK"); InstanceUnlock(pInstance); return lError; } // H245SendLocalMuxTable() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245MuxTableIndResp * * DESCRIPTION * * HRESULT H245MuxTableIndResp ( * H45_INST_T dwInst, * H245_ACC_REJ_MUX_T AccRejMux, * DWORD Count * ) * Description: * This procedure is called to either accept or reject mux * table entries sent up in the H245_IND_MUX_TBL indication. * * Input * dwInst Instance handle returned by H245Init * AccRejMux Accept Reject Mux structure * Count number of entries in the structure * * Call Type: * Asynchronous * * Return Values: * See Errors * Errors: * H245_ERROR_OK * H245_ERROR_INVALID_MUXTBLENTRY * H245_ERROR_PARAM * H245_ERROR_INVALID_INST * H245_ERROR_INVALID_OP * H245_ERROR_NOT_CONNECTED * H245_ERROR_NOMEM * See Also: * H245SendLocalMuxTable * * callback * * H245_IND_MUX_TBL * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MuxTableIndResp ( H245_INST_T dwInst, H245_ACC_REJ_MUX_T AccRejMux, unsigned long dwCount ) { register struct InstanceStruct *pInstance; DWORD ii; Tracker_T *pTracker; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245MuxTableIndResp <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* look for tracker.. */ pTracker = NULL; pTracker = find_tracker_by_type (pInstance, API_RECV_MUX_T, pTracker); /* if tracker not found.. issue invalid op */ if (!pTracker) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_OP)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_OP; } ASSERT (pTracker->State == API_ST_WAIT_LCLACK); /* can't ack or reject more than you got */ if ((dwCount > pTracker->u.MuxEntryCount) || (dwCount > 15)) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } /* verify the mux table entry id's */ for (ii=0;ii 15) || (AccRejMux[ii].MuxEntryId <= 0)) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } } if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* if there are any rejects in the list.. send reject */ memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); if (pdu_rsp_mux_table_rej (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK) FsmOutgoing(pInstance, pPdu, 0); /* if there are any accepts in the list.. send accept */ memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); if (pdu_rsp_mux_table_ack (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK) FsmOutgoing(pInstance, pPdu, 0); /* if we've acked all the entries */ if (!(pTracker->u.MuxEntryCount -= dwCount)) unlink_dealloc_tracker (pInstance, pTracker); MemFree (pPdu); H245TRACE (dwInst,4,"H245MuxTableIndResp -> %s",H245_ERROR_OK); InstanceUnlock(pInstance); return H245_ERROR_OK; } // H245MuxTableIndResp() #if 0 /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245MiscCommand * * DESCRIPTION * * HRESULT H245MiscCommand ( * H245_INST_T dwInst, * DWORD wChannel, * H245_MISC_T *pMisc * ) * Description: * Send a Misc. command to the remote side (see H245_MISC_T * data Structure) * * Input * dwInst Instance handle returned by H245Init * wChannel Logical Channel Number * pMisc pointer to a misc. command structure * * Call Type: * Synchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK * H245_ERROR_NOT_CONNECTED * H245_ERROR_INVALID_CHANNEL * H245_ERROR_NOMEM * H245_ERROR_PARAM * H245_ERROR_INVALID_INST * * callback * * H245_IND_MISC * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MiscCommand ( H245_INST_T dwInst, WORD wChannel, H245_MISC_T *pMisc ) { register struct InstanceStruct *pInstance; HRESULT lError; MltmdSystmCntrlMssg *pPdu; H245TRACE (dwInst,4,"H245MiscCommand <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } /* if the channel can not be found */ if (!find_tracker_by_txchannel(pInstance, wChannel, API_CH_ALLOC_LCL) && !find_tracker_by_rxchannel(pInstance, wChannel, API_CH_ALLOC_RMT)) { H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL)); InstanceUnlock(pInstance); return H245_ERROR_INVALID_CHANNEL; } if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)))) { H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* budld pdu for misc command */ pdu_cmd_misc (pPdu, pMisc, wChannel); lError = FsmOutgoing(pInstance, pPdu, 0); MemFree (pPdu); if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MiscCommand -> OK"); InstanceUnlock(pInstance); return lError; } // H245MiscCommand() #endif /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestMultiplexEntry * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestMultiplexEntry ( H245_INST_T dwInst, DWORD_PTR dwTransId, const unsigned short * pwMultiplexTableEntryNumbers, unsigned long dwCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; DWORD dwIndex; H245TRACE (dwInst,4,"H245RequestMultiplexEntry <-"); if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15) { H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) { if (pwMultiplexTableEntryNumbers[dwIndex] < 1 || pwMultiplexTableEntryNumbers[dwIndex] > 15) { H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMultiplexEntry_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count = (WORD)dwCount; for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) { pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex] = (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex]; } lError = FsmOutgoing(pInstance, pPdu, dwTransId); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestMultiplexEntry -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestMultiplexEntry() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestMultiplexEntryAck * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestMultiplexEntryAck ( H245_INST_T dwInst, const unsigned short * pwMultiplexTableEntryNumbers, unsigned long dwCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; DWORD dwIndex; H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck <-"); if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15) { H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = requestMultiplexEntryAck_chosen; pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count = (WORD)dwCount; for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) { pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex] = (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex]; } lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestMultiplexEntryAck() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestMultiplexEntryReject * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestMultiplexEntryReject ( H245_INST_T dwInst, const unsigned short * pwMultiplexTableEntryNumbers, unsigned long dwCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; DWORD dwIndex; H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject <-"); if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15) { H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = rqstMltplxEntryRjct_chosen; pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count = (WORD)dwCount; for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) { pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber = (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex]; pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].cause.choice = RMERDs_cs_unspcfdCs_chosen; } lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestMultiplexEntryReject() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestMode * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestMode ( H245_INST_T dwInst, DWORD_PTR dwTransId, // const ModeElement * pModeElements, //tomitowoju@intel.com ModeDescription ModeDescriptions[], //tomitowoju@intel.com unsigned long dwCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; RequestedModesLink pLink; RequestedModesLink pLink_First; DWORD dwIndex; // tomitowoju@intel.com ULONG ulPDUsize; // tomitowoju@intel.com H245TRACE (dwInst,4,"H245RequestMode <-"); //tomitowoju@intel.com // if (pModeElements == NULL || dwCount == 0 || dwCount > 256) if (ModeDescriptions == NULL || dwCount == 0 || dwCount > 256) //tomitowoju@intel.com { H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } //tomitowoju@intel.com // pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + sizeof(*pLink)); pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + (sizeof(*pLink)*(dwCount))); //tomitowoju@intel.com if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { USHORT usModeDescIndex =0; memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMode_chosen; //tomitowoju@intel.com // pLink = (RequestedModesLink)(pPdu + 1); pLink = (RequestedModesLink)(pPdu + usModeDescIndex+1); //tomitowoju@intel.com //tomitowoju@intel.com // pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink; //tomitowoju@intel.com //tomitowoju@intel.com pLink_First = pLink; //tomitowoju@intel.com // --> linked list of mode descriptions ... up to 1..256 //tomitowoju@intel.com while(usModeDescIndex<=(dwCount-1)) { //tomitowoju@intel.com //tomitowoju@intel.com // pLink->next = NULL; //tomitowoju@intel.com // --> number of actual mode-elements associated with this mode description //tomitowoju@intel.com // pLink->value.count = (WORD)dwCount; pLink->value.count = (WORD)ModeDescriptions[usModeDescIndex].count; //tomitowoju@intel.com // for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) for (dwIndex = 0; dwIndex < ModeDescriptions[usModeDescIndex].count; ++dwIndex) { //tomitowoju@intel.com // pLink->value.value[dwIndex] = pModeElements[dwIndex]; pLink->value.value[dwIndex] = ModeDescriptions[usModeDescIndex].value[dwIndex]; //tomitowoju@intel.com } //tomitowoju@intel.com usModeDescIndex++; if(usModeDescIndex<=(dwCount-1)) { pLink->next = (RequestedModesLink)(pPdu + usModeDescIndex+1); pLink = pLink->next; pLink->next = NULL; } //tomitowoju@intel.com //tomitowoju@intel.com } //tomitowoju@intel.com //tomitowoju@intel.com pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink_First; //tomitowoju@intel.com //-- ulPDUsize = (sizeof(*pPdu) + (sizeof(*pLink)*(dwCount))); //-- lError = FsmOutgoing(pInstance, pPdu, dwTransId); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestMode -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestMode() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestModeAck * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestModeAck ( H245_INST_T dwInst, unsigned short wResponse ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245RequestModeAck <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = requestModeAck_chosen; pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice = wResponse; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestModeAck -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestModeAck() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RequestModeReject * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RequestModeReject ( H245_INST_T dwInst, unsigned short wCause ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245RequestModeReject <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = requestModeReject_chosen; pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice = wCause; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RequestModeReject -> OK"); InstanceUnlock(pInstance); return lError; } // H245RequestModeReject() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245RoundTripDelayRequest * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245RoundTripDelayRequest ( H245_INST_T dwInst, DWORD_PTR dwTransId ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245RoundTripDelayRequest <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = roundTripDelayRequest_chosen; lError = FsmOutgoing(pInstance, pPdu, dwTransId); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245RoundTripDelayRequest -> OK"); InstanceUnlock(pInstance); return lError; } // H245RoundTripDelayRequest() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245MaintenanceLoop * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MaintenanceLoop ( H245_INST_T dwInst, DWORD_PTR dwTransId, H245_LOOP_TYPE_T dwLoopType, H245_CHANNEL_T wChannel ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245MaintenanceLoop <-"); if (dwLoopType < systemLoop_chosen || dwLoopType > logicalChannelLoop_chosen || (dwLoopType != systemLoop_chosen && wChannel == 0)) { H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = maintenanceLoopRequest_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice = (WORD)dwLoopType; pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop = wChannel; lError = FsmOutgoing(pInstance, pPdu, dwTransId); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MaintenanceLoop -> OK"); InstanceUnlock(pInstance); return lError; } // H245MaintenanceLoop() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245MaintenanceLoopRelease * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MaintenanceLoopRelease (H245_INST_T dwInst) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245MaintenanceLoopRelease <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = mntnncLpOffCmmnd_chosen; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MaintenanceLoopRelease -> OK"); InstanceUnlock(pInstance); return lError; } // H245MaintenanceLoopRelease() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245MaintenanceLoopAccept * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MaintenanceLoopAccept ( H245_INST_T dwInst, H245_CHANNEL_T wChannel ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245MaintenanceLoopAccept <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = maintenanceLoopAck_chosen; pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop = wChannel; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MaintenanceLoopAccept -> OK"); InstanceUnlock(pInstance); return lError; } // H245MaintenanceLoopAccept() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245MaintenanceLoopReject * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MaintenanceLoopReject ( H245_INST_T dwInst, H245_CHANNEL_T wChannel, unsigned short wCause ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245MaintenanceLoopReject <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = maintenanceLoopReject_chosen; pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop = wChannel; pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.cause.choice = wCause; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MaintenanceLoopReject -> OK"); InstanceUnlock(pInstance); return lError; } // H245MaintenanceLoopReject() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245NonStandardObject * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245NonStandardObject ( H245_INST_T dwInst, H245_MESSAGE_TYPE_T MessageType, const unsigned char * pData, unsigned long dwDataLength, const unsigned short * pwObjectId, unsigned long dwObjectIdLength ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; POBJECTID pObject; H245TRACE (dwInst,4,"H245NonStandardObject <-"); if (pData == NULL || dwDataLength == 0 || pwObjectId == NULL || dwObjectIdLength == 0) { H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + dwObjectIdLength * sizeof(*pObject)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); switch (MessageType) { case H245_MESSAGE_REQUEST: pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen; break; case H245_MESSAGE_RESPONSE: pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen; break; case H245_MESSAGE_COMMAND: pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen; break; case H245_MESSAGE_INDICATION: pPdu->choice = indication_chosen; pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen; break; default: H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } // switch pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = object_chosen; // Copy the object identifier pObject = (POBJECTID) (pPdu + 1); pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object = pObject; do { pObject->next = pObject + 1; pObject->value = *pwObjectId++; ++pObject; } while (--dwObjectIdLength); // Null terminate the linked list --pObject; pObject->next = NULL; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245NonStandardObject -> OK"); InstanceUnlock(pInstance); return lError; } // H245NonStandardObject() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245NonStandardH221 * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245NonStandardH221 ( H245_INST_T dwInst, H245_MESSAGE_TYPE_T MessageType, const unsigned char * pData, unsigned long dwDataLength, unsigned char byCountryCode, unsigned char byExtension, unsigned short wManufacturerCode ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245NonStandard221 <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); switch (MessageType) { case H245_MESSAGE_REQUEST: pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen; break; case H245_MESSAGE_RESPONSE: pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen; break; case H245_MESSAGE_COMMAND: pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen; break; case H245_MESSAGE_INDICATION: pPdu->choice = indication_chosen; pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen; break; default: H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_PARAM)); InstanceUnlock(pInstance); return H245_ERROR_PARAM; } // switch pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = h221NonStandard_chosen; // Fill in the H.221 identifier pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = byCountryCode; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension = byExtension; pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = wManufacturerCode; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245NonStandardH221 -> OK"); InstanceUnlock(pInstance); return lError; } // H245NonStandardH221 /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CommunicationModeRequest * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CommunicationModeRequest(H245_INST_T dwInst) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245CommunicationModeRequest <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = communicationModeRequest_chosen; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245CommunicationModeRequest -> OK"); InstanceUnlock(pInstance); return lError; } // H245CommunicationModeRequest /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CommunicationModeResponse * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CommunicationModeResponse( H245_INST_T dwInst, const H245_COMM_MODE_ENTRY_T *pTable, unsigned char byTableCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError = H245_ERROR_OK; CommunicationModeTableLink pLink; unsigned int uIndex; H245TRACE (dwInst,4,"H245CommunicationModeResponse <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = cmmnctnMdRspns_chosen; pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice = communicationModeTable_chosen; pLink = (CommunicationModeTableLink)(pPdu + 1); pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable = pLink; for (uIndex = 0; uIndex < byTableCount; ++uIndex) { pLink[uIndex].next = &pLink[uIndex + 1]; lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]); if (lError != H245_ERROR_OK) break; } pLink[byTableCount - 1].next = NULL; if (lError == H245_ERROR_OK) { lError = FsmOutgoing(pInstance, pPdu, 0); } MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245CommunicationModeResponse -> OK"); InstanceUnlock(pInstance); return lError; } // H245CommunicationModeResponse() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245CommunicationModeCommand * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245CommunicationModeCommand( H245_INST_T dwInst, const H245_COMM_MODE_ENTRY_T *pTable, unsigned char byTableCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError = H245_ERROR_OK; CommunicationModeCommandLink pLink; unsigned int uIndex; H245TRACE (dwInst,4,"H245CommunicationModeCommand <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = communicationModeCommand_chosen; pLink = (CommunicationModeCommandLink)(pPdu + 1); pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable = pLink; for (uIndex = 0; uIndex < byTableCount; ++uIndex) { pLink[uIndex].next = &pLink[uIndex + 1]; lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]); if (lError != H245_ERROR_OK) break; } pLink[byTableCount - 1].next = NULL; if (lError == H245_ERROR_OK) { lError = FsmOutgoing(pInstance, pPdu, 0); } MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245CommunicationModeCommand -> OK"); InstanceUnlock(pInstance); return lError; } // H245CommunicationModeCommand() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245ConferenceRequest * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245ConferenceRequest ( H245_INST_T dwInst, H245_CONFER_REQ_ENUM_T RequestType, unsigned char byMcuNumber, unsigned char byTerminalNumber ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245ConferenceRequest <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.choice = conferenceRequest_chosen; pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice = (WORD)RequestType; switch (RequestType) { case dropTerminal_chosen: case requestTerminalID_chosen: pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber = byMcuNumber; pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber = byTerminalNumber; // Fall-through to next case is intentional case terminalListRequest_chosen: case makeMeChair_chosen: case cancelMakeMeChair_chosen: case enterH243Password_chosen: case enterH243TerminalID_chosen: case enterH243ConferenceID_chosen: lError = FsmOutgoing(pInstance, pPdu, 0); break; default: lError = H245_ERROR_PARAM; } // switch MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245ConferenceRequest -> OK"); InstanceUnlock(pInstance); return lError; } // H245ConferenceRequest() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245ConferenceResponse * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245ConferenceResponse ( H245_INST_T dwInst, H245_CONFER_RSP_ENUM_T ResponseType, unsigned char byMcuNumber, unsigned char byTerminalNumber, const unsigned char *pOctetString, unsigned char byOctetStringLength, const TerminalLabel *pTerminalList, unsigned short wTerminalListCount ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; unsigned uIndex; H245TRACE (dwInst,4,"H245ConferenceResponse <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_rspns_chosen; pPdu->u.MSCMg_rspns.choice = conferenceResponse_chosen; pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = (WORD)ResponseType; switch (ResponseType) { case mCTerminalIDResponse_chosen: case terminalIDResponse_chosen: case conferenceIDResponse_chosen: case passwordResponse_chosen: if (pOctetString == NULL || byOctetStringLength == 0 || byOctetStringLength > 128) { H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber = byMcuNumber; pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber = byTerminalNumber; pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length = byOctetStringLength; memcpy(pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value, pOctetString, byOctetStringLength); // Fall-through to next case is intentional case videoCommandReject_chosen: case terminalDropReject_chosen: lError = FsmOutgoing(pInstance, pPdu, 0); break; case terminalListResponse_chosen: if (pTerminalList == NULL || wTerminalListCount == 0 || wTerminalListCount > 256) { H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM)); return H245_ERROR_PARAM; } pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count = wTerminalListCount; for (uIndex = 0; uIndex < wTerminalListCount; ++uIndex) { pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value[uIndex] = pTerminalList[uIndex]; } lError = FsmOutgoing(pInstance, pPdu, 0); break; case H245_RSP_DENIED_CHAIR_TOKEN: pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen; pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = deniedChairToken_chosen; lError = FsmOutgoing(pInstance, pPdu, 0); break; case H245_RSP_GRANTED_CHAIR_TOKEN: pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen; pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = grantedChairToken_chosen; lError = FsmOutgoing(pInstance, pPdu, 0); break; default: lError = H245_ERROR_PARAM; } // switch MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245ConferenceResponse -> OK"); InstanceUnlock(pInstance); return lError; } // H245ConferenceResponse() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245ConferenceCommand * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245ConferenceCommand ( H245_INST_T dwInst, H245_CONFER_CMD_ENUM_T CommandType, H245_CHANNEL_T Channel, unsigned char byMcuNumber, unsigned char byTerminalNumber ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245ConferenceCommand <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = conferenceCommand_chosen; pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice = (WORD)CommandType; switch (CommandType) { case brdcstMyLgclChnnl_chosen: case cnclBrdcstMyLgclChnnl_chosen: pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl = Channel; lError = FsmOutgoing(pInstance, pPdu, 0); break; case ConferenceCommand_makeTerminalBroadcaster_chosen: case ConferenceCommand_sendThisSource_chosen: pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.mcuNumber = byMcuNumber; pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.terminalNumber = byTerminalNumber; // Fall-through to next case is intentional case cnclMkTrmnlBrdcstr_chosen: case cancelSendThisSource_chosen: case dropConference_chosen: lError = FsmOutgoing(pInstance, pPdu, 0); break; default: lError = H245_ERROR_PARAM; } // switch MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245ConferenceCommand -> OK"); InstanceUnlock(pInstance); return lError; } // H245ConferenceCommand() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245ConferenceIndication * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245ConferenceIndication( H245_INST_T dwInst, H245_CONFER_IND_ENUM_T IndicationType, unsigned char bySbeNumber, unsigned char byMcuNumber, unsigned char byTerminalNumber ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245ConferenceIndication <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = indication_chosen; pPdu->u.indication.choice = conferenceIndication_chosen; pPdu->u.indication.u.conferenceIndication.choice = (WORD)IndicationType; switch (IndicationType) { case sbeNumber_chosen: pPdu->u.indication.u.conferenceIndication.u.sbeNumber = bySbeNumber; lError = FsmOutgoing(pInstance, pPdu, 0); break; case terminalNumberAssign_chosen: case terminalJoinedConference_chosen: case terminalLeftConference_chosen: case terminalYouAreSeeing_chosen: pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber = byMcuNumber; pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber = byTerminalNumber; // Fall-through to next case is intentional case seenByAtLeastOneOther_chosen: case cnclSnByAtLstOnOthr_chosen: case seenByAll_chosen: case cancelSeenByAll_chosen: case requestForFloor_chosen: lError = FsmOutgoing(pInstance, pPdu, 0); break; default: lError = H245_ERROR_PARAM; } // switch MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245ConferenceIndication -> OK"); InstanceUnlock(pInstance); return lError; } // H245ConferenceIndication() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245UserInput * * DESCRIPTION * * HRESULT H245UserInput ( * H245_INST_T dwInst, * char *pGenString, * H245_NONSTANDARD_PARAMETER_T *pNonStd * ) * Description: * * Send a User Input indiation to the remote side. One of the * two parameters must be set (pGenString, pNonStd). The client * can either send a string or a NonStandard parameter set to the * remote client. Only one of the two parameters can contain a * value. The other is required to be NULL. * * Input * dwInst Instance handle returned by H245Init * pGenString choice: String to be sent to remote * side in accordance with T.51 specification. * pNonStd choice: NonStandard Parameter * * Call Type: * Synchronous * * Return Values: * See Errors * * Errors: * H245_ERROR_OK * H245_ERROR_NOT_CONNECTED * H245_ERROR_NOMEM * H245_ERROR_PARAM * * callback * H245_IND_USERINPUT * * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245UserInput ( H245_INST_T dwInst, const WCHAR * pGenString, const H245_NONSTANDARD_PARAMETER_T * pNonStd ) { register struct InstanceStruct *pInstance; HRESULT lError; MltmdSystmCntrlMssg *pPdu; #if 1 int nLength; char * pszGeneral = NULL; #endif H245TRACE (dwInst,4,"H245UserInput <-"); /* check for valid instance handle */ pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } /* system should be in connected state */ if (pInstance->API.SystemState != APIST_Connected) { H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOT_CONNECTED)); InstanceUnlock(pInstance); return H245_ERROR_NOT_CONNECTED; } pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg)); if (pPdu == NULL) { H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg)); /* build PDU */ #if 1 if (pGenString) { nLength = WideCharToMultiByte(CP_ACP, // code page 0, // dwFlags pGenString, // Unicode string -1, // Unicode string length (bytes) NULL, // ASCII string 0, // max ASCII string length NULL, // default character NULL); // default character used pszGeneral = MemAlloc(nLength); if (pszGeneral == NULL) { H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM)); InstanceUnlock(pInstance); return H245_ERROR_NOMEM; } nLength = WideCharToMultiByte(CP_ACP, // code page 0, // dwFlags pGenString, // Unicode string -1, // Unicode string length (bytes) pszGeneral, // ASCII string nLength, // max ASCII string length NULL, // default character NULL); // default character used lError = pdu_ind_usrinpt (pPdu, NULL, pszGeneral); } else { lError = pdu_ind_usrinpt (pPdu, pNonStd, NULL); } #else lError = pdu_ind_usrinpt (pPdu, pNonStd, pGenString); #endif if (lError == H245_ERROR_OK) lError = FsmOutgoing(pInstance, pPdu, 0); #if 1 if (pszGeneral) MemFree(pszGeneral); #endif MemFree (pPdu); if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245UserInput -> OK"); InstanceUnlock(pInstance); return lError; } // H245UserInput() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245FlowControl * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245FlowControl ( H245_INST_T dwInst, H245_SCOPE_T Scope, H245_CHANNEL_T Channel, // only used if Scope is H245_SCOPE_CHANNEL_NUMBER unsigned short wResourceID, // only used if Scope is H245_SCOPE_RESOURCE_ID unsigned long dwRestriction // H245_NO_RESTRICTION if no restriction ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245FlowControl <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = MSCMg_cmmnd_chosen; pPdu->u.MSCMg_cmmnd.choice = flowControlCommand_chosen; pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice = (WORD)Scope; if (dwRestriction == H245_NO_RESTRICTION) { pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = noRestriction_chosen; } else { pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = maximumBitRate_chosen; pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate = dwRestriction; } switch (Scope) { case FCCd_scp_lgclChnnlNmbr_chosen: pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr = Channel; lError = FsmOutgoing(pInstance, pPdu, 0); break; case FlwCntrlCmmnd_scp_rsrcID_chosen: pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID = wResourceID; // Fall-through to next case case FCCd_scp_whlMltplx_chosen: lError = FsmOutgoing(pInstance, pPdu, 0); break; default: lError = H245_ERROR_PARAM; } // switch MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245FlowControl -> OK"); InstanceUnlock(pInstance); return lError; } // H245FlowControl() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245H223SkewIndication * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245H223SkewIndication ( H245_INST_T dwInst, H245_CHANNEL_T wLogicalChannelNumber1, H245_CHANNEL_T wLogicalChannelNumber2, unsigned short wSkew ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245H223SkewIndication <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = indication_chosen; pPdu->u.indication.choice = h223SkewIndication_chosen; pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1 = wLogicalChannelNumber1; pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2 = wLogicalChannelNumber2; pPdu->u.indication.u.h223SkewIndication.skew = wSkew; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245H223SkewIndication -> OK"); InstanceUnlock(pInstance); return lError; } // H245H223SkewIndication() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245H2250MaximumSkewIndication * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245H2250MaximumSkewIndication( H245_INST_T dwInst, H245_CHANNEL_T wLogicalChannelNumber1, H245_CHANNEL_T wLogicalChannelNumber2, unsigned short wMaximumSkew ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = indication_chosen; pPdu->u.indication.choice = h2250MxmmSkwIndctn_chosen; pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1 = wLogicalChannelNumber1; pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2 = wLogicalChannelNumber2; pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew = wMaximumSkew; lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication -> OK"); InstanceUnlock(pInstance); return lError; } // H245H2250MaximumSkewIndication() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245MCLocationIndication * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245MCLocationIndication( H245_INST_T dwInst, const H245_TRANSPORT_ADDRESS_T * pSignalAddress ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245MCLocationIndication <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = indication_chosen; pPdu->u.indication.choice = mcLocationIndication_chosen; lError = SetupTransportAddress(&pPdu->u.indication.u.mcLocationIndication.signalAddress, pSignalAddress); if (lError == H245_ERROR_OK) { lError = FsmOutgoing(pInstance, pPdu, 0); } MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245MCLocationIndication -> OK"); InstanceUnlock(pInstance); return lError; } // H245MCLocationIndication() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245VendorIdentification * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245VendorIdentification( H245_INST_T dwInst, const H245_NONSTANDID_T *pIdentifier, const unsigned char *pProductNumber, unsigned char byProductNumberLength, const unsigned char *pVersionNumber, unsigned char byVersionNumberLength ) { register struct InstanceStruct *pInstance; register PDU_T * pPdu; HRESULT lError; H245TRACE (dwInst,4,"H245VendorIdentification <-"); pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu)); if (pPdu == NULL) { lError = H245_ERROR_NOMEM; } else { memset(pPdu, 0, sizeof(*pPdu)); pPdu->choice = indication_chosen; pPdu->u.indication.choice = vendorIdentification_chosen; pPdu->u.indication.u.vendorIdentification.bit_mask = 0; pPdu->u.indication.u.vendorIdentification.vendor = *pIdentifier; if (pProductNumber != NULL && byProductNumberLength != 0) { pPdu->u.indication.u.vendorIdentification.bit_mask |= productNumber_present; pPdu->u.indication.u.vendorIdentification.productNumber.length = byProductNumberLength; memcpy(pPdu->u.indication.u.vendorIdentification.productNumber.value, pProductNumber, byProductNumberLength); } if (pVersionNumber != NULL && byVersionNumberLength != 0) { pPdu->u.indication.u.vendorIdentification.bit_mask |= versionNumber_present; pPdu->u.indication.u.vendorIdentification.versionNumber.length = byVersionNumberLength; memcpy(pPdu->u.indication.u.vendorIdentification.versionNumber.value, pVersionNumber, byVersionNumberLength); } lError = FsmOutgoing(pInstance, pPdu, 0); MemFree(pPdu); } if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245VendorIdentification -> OK"); InstanceUnlock(pInstance); return lError; } // H245VendorIdentification() /***************************************************************************** * * TYPE: H245 API * * PROCEDURE: H245SendPDU * * DESCRIPTION * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245SendPDU ( H245_INST_T dwInst, PDU_T * pPdu ) { register struct InstanceStruct *pInstance; HRESULT lError; H245TRACE (dwInst,4,"H245SendPDU <-"); // Check for valid instance handle pInstance = InstanceLock(dwInst); if (pInstance == NULL) { H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(H245_ERROR_INVALID_INST)); return H245_ERROR_INVALID_INST; } lError = FsmOutgoing(pInstance, pPdu, 0); if (lError != H245_ERROR_OK) H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(lError)); else H245TRACE (dwInst,4,"H245SendPDU -> OK"); InstanceUnlock(pInstance); return lError; } // H245SendPDU() /***************************************************************************** * * TYPE: H245 API * ***************************************************************************** * * PROCEDURE: H245SystemControl * * DESCRIPTION * * HRESULT H245SystemControl * ( H245_INST_T dwInst, * DWORD Request , * VOID *pData * ) * * Description: * This function should not be used by clients who * normally interface to the H.245 subsystem. It is * defined here to help during development and debug * of the H.245 subsystem. * * This is a roll your own.. and can do what * ever the user needs.. It's a hook to allow * IOCTL (unix) calls that can either be * passed to lower stack elements (AT&T Streams IOCTL * would be an example - :) or simply to get or put * information to the H245 SubSytem. * * Input * dwInst Instance handle returned by H245Init * Request Requested system control * pData In the case of sending information * down to H.245 this is an input * parameter, and it's data format * is determined by the Request. * output * pData In the case of retrieving information * from H.245 this can be an output * parameter, and it's data format is * determined by the Request. It may not * have valid data if the request is a * synchronous request. (See Request Options). * Call Type: * * Synchronous * * Request Options: * * H245_SYSCON_GET_STATS Retrieves Statistics * from H.245 subsystem * parameter pData = &H245_SYSCON_STAT_T * H245_ SYSCON_RESET_STATS Resets the statistics * pData = NULL * H245_SYS_TRACE Set Trace Level * pData = &DWORD (Trace Level) * * Return Values: * See Request Options * * Errors: * H245_ERROR_OK * * RETURN: * *****************************************************************************/ H245DLL HRESULT H245SystemControl ( H245_INST_T dwInst, unsigned long dwRequest, void * pData ) { HRESULT lError; DWORD dwTemp; H245TRACE(dwInst,4,"H245SystemControl <-"); if (dwRequest == H245_SYSCON_DUMP_TRACKER) { register struct InstanceStruct *pInstance = InstanceLock(dwInst); if (pInstance == NULL) { lError = H245_ERROR_INVALID_INST; } else { dump_tracker(pInstance); InstanceUnlock(pInstance); lError = H245_ERROR_OK; } } else if (pData == NULL) { lError = H245_ERROR_PARAM; } else { lError = H245_ERROR_OK; switch (dwRequest) { case H245_SYSCON_GET_FSM_N100: *((DWORD *)pData) = (DWORD) uN100; H245TRACE(dwInst,20,"H245SystemControl: Get N100 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T101: *((DWORD *)pData) = (DWORD) uT101; H245TRACE(dwInst,20,"H245SystemControl: Get T101 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T102: *((DWORD *)pData) = (DWORD) uT102; H245TRACE(dwInst,20,"H245SystemControl: Get T102 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T103: *((DWORD *)pData) = (DWORD) uT103; H245TRACE(dwInst,20,"H245SystemControl: Get T103 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T104: *((DWORD *)pData) = (DWORD) uT104; H245TRACE(dwInst,20,"H245SystemControl: Get T104 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T105: *((DWORD *)pData) = (DWORD) uT105; H245TRACE(dwInst,20,"H245SystemControl: Get T105 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T106: *((DWORD *)pData) = (DWORD) uT106; H245TRACE(dwInst,20,"H245SystemControl: Get T106 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T107: *((DWORD *)pData) = (DWORD) uT107; H245TRACE(dwInst,20,"H245SystemControl: Get T107 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T108: *((DWORD *)pData) = (DWORD) uT108; H245TRACE(dwInst,20,"H245SystemControl: Get T108 = %d",*((DWORD *)pData)); break; case H245_SYSCON_GET_FSM_T109: *((DWORD *)pData) = (DWORD) uT109; H245TRACE(dwInst,20,"H245SystemControl: Get T109 = %d",*((DWORD *)pData)); break; case H245_SYSCON_SET_FSM_N100: dwTemp = (DWORD) uN100; uN100 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set N100 = %d",uN100); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T101: dwTemp = (DWORD) uT101; uT101 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T101 = %d",uT101); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T102: dwTemp = (DWORD) uT102; uT102 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T102 = %d",uT102); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T103: dwTemp = (DWORD) uT103; uT103 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T103 = %d",uT103); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T104: dwTemp = (DWORD) uT104; uT104 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T104 = %d",uT104); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T105: dwTemp = (DWORD) uT105; uT105 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T105 = %d",uT105); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T106: dwTemp = (DWORD) uT106; uT106 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T106 = %d",uT106); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T107: dwTemp = (DWORD) uT107; uT107 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T107 = %d",uT107); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T108: dwTemp = (DWORD) uT108; uT108 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T108 = %d",uT108); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_SET_FSM_T109: dwTemp = (DWORD) uT109; uT109 = (unsigned int) *((DWORD *)pData); H245TRACE(dwInst,20,"H245SystemControl: Set T109 = %d",uT109); *((DWORD *)pData) = dwTemp; break; case H245_SYSCON_TRACE_LVL: dwTemp = TraceLevel; TraceLevel = *(DWORD *)pData; H245TRACE(dwInst,20,"H245SystemControl: Set TraceLevel = %d",TraceLevel); *((DWORD *)pData) = dwTemp; break; default: lError = H245_ERROR_NOTIMP; } // switch } // else if (lError != H245_ERROR_OK) H245TRACE(dwInst,1,"H245SystemControl -> %s",map_api_error(lError)); else H245TRACE(dwInst,4,"H245SystemControl -> OK"); return lError; } // H245SystemControl()