Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6322 lines
205 KiB

  1. /******************************************************************************
  2. *
  3. * INTEL Corporation Proprietary Information
  4. * Copyright (c) 1994, 1995, 1996 Intel Corporation.
  5. *
  6. * This listing is supplied under the terms of a license agreement
  7. * with INTEL Corporation and may not be used, copied, nor disclosed
  8. * except in accordance with the terms of that agreement.
  9. *
  10. *****************************************************************************/
  11. /******************************************************************************
  12. *
  13. * AUTHOR: cjutzi (Curt Jutzi) Intel Corporation
  14. *
  15. * $Workfile: api_dwn.c $
  16. * $Revision: 1.45 $
  17. * $Modtime: 05 Mar 1997 09:53:36 $
  18. * $Log: S:/STURGEON/SRC/H245/SRC/VCS/api_dwn.c_v $
  19. *
  20. * Rev 1.45 05 Mar 1997 09:56:04 MANDREWS
  21. * Fixed compiler warning in release mode.
  22. *
  23. * Rev 1.44 04 Mar 1997 17:33:26 MANDREWS
  24. * H245CopyCap() and H245CopyCapDescriptor() now return HRESULTs.
  25. *
  26. * Rev 1.43 26 Feb 1997 11:12:06 MANDREWS
  27. * Fixed problem in assigning dynamic term cap IDs; the dynamic IDs were
  28. * overlapping with static IDs.
  29. *
  30. * Rev 1.42 Feb 24 1997 18:30:18 tomitowx
  31. * multiple modedescriptor support
  32. *
  33. * Rev 1.41 07 Feb 1997 15:33:58 EHOWARDX
  34. * Changed H245DelCapDescriptor to match changes to set_cap_descriptor.
  35. *
  36. * Rev 1.40 27 Jan 1997 12:40:16 MANDREWS
  37. *
  38. * Fixed warnings.
  39. *
  40. * Rev 1.39 09 Jan 1997 19:17:04 EHOWARDX
  41. *
  42. * Initialize lError to H245_ERROR_OK to prevent "may be uninitialized"
  43. * warning.
  44. *
  45. * Rev 1.38 19 Dec 1996 17:18:50 EHOWARDX
  46. * Changed to use h245asn1.h definitions instead of _setof3 and _setof8.
  47. *
  48. * Rev 1.37 12 Dec 1996 15:57:22 EHOWARDX
  49. * Master Slave Determination kludge.
  50. *
  51. * Rev 1.36 11 Dec 1996 13:55:44 SBELL1
  52. * Changed H245Init parameters.
  53. *
  54. * Rev 1.35 17 Oct 1996 18:17:36 EHOWARDX
  55. * Changed general string to always be Unicode.
  56. *
  57. * Rev 1.34 14 Oct 1996 14:01:26 EHOWARDX
  58. * Unicode changes.
  59. *
  60. * Rev 1.33 11 Oct 1996 15:19:56 EHOWARDX
  61. * Fixed H245CopyCap() bug.
  62. *
  63. * Rev 1.32 28 Aug 1996 11:37:10 EHOWARDX
  64. * const changes.
  65. *
  66. * Rev 1.31 19 Aug 1996 16:28:36 EHOWARDX
  67. * H245CommunicationModeResponse/H245CommunicationModeCommand bug fixes.
  68. *
  69. * Rev 1.30 15 Aug 1996 15:19:46 EHOWARDX
  70. * First pass at new H245_COMM_MODE_ENTRY_T requested by Mike Andrews.
  71. * Use at your own risk!
  72. *
  73. * Rev 1.29 08 Aug 1996 16:02:58 EHOWARDX
  74. *
  75. * Eliminated api_vers.h.
  76. * Changed H245Init Debug trace to eliminate API_VERSION.
  77. *
  78. * Rev 1.28 19 Jul 1996 12:48:22 EHOWARDX
  79. *
  80. * Multipoint clean-up.
  81. *
  82. * Rev 1.27 01 Jul 1996 22:13:42 EHOWARDX
  83. *
  84. * Added Conference and CommunicationMode structures and functions.
  85. *
  86. * Rev 1.26 18 Jun 1996 14:53:16 EHOWARDX
  87. * Eliminated Channel parameter to MaintenanceLoopRelease.
  88. * Made Multiplex Capability mandatory -- H245SendTermCaps now returns
  89. * H245_ERROR_NO_MUX_CAPS if no Multiplex Capability has been defined.
  90. *
  91. * Rev 1.25 14 Jun 1996 18:57:38 EHOWARDX
  92. * Geneva update.
  93. *
  94. * Rev 1.24 10 Jun 1996 16:59:02 EHOWARDX
  95. * Moved init/shutdown of submodules to CreateInstance/InstanceUnlock.
  96. *
  97. * Rev 1.23 06 Jun 1996 18:50:10 EHOWARDX
  98. * Equivalent of H.324 bugs #808 and 875 fixed.
  99. *
  100. * Rev 1.22 05 Jun 1996 17:16:48 EHOWARDX
  101. * MaintenanceLoop bug fix.
  102. *
  103. * Rev 1.21 04 Jun 1996 13:56:42 EHOWARDX
  104. * Fixed Release build warnings.
  105. *
  106. * Rev 1.20 30 May 1996 23:38:52 EHOWARDX
  107. * Cleanup.
  108. *
  109. * Rev 1.19 29 May 1996 16:08:04 unknown
  110. * Fixed bug in copying nonstandard identifiers.
  111. *
  112. * Rev 1.18 29 May 1996 15:19:48 EHOWARDX
  113. * Change to use HRESULT.
  114. *
  115. * Rev 1.17 28 May 1996 14:25:12 EHOWARDX
  116. * Tel Aviv update.
  117. *
  118. * Rev 1.16 21 May 1996 15:46:54 EHOWARDX
  119. * Fixed bugs in NonStandard messages using object identifier.
  120. *
  121. * Rev 1.15 20 May 1996 22:17:54 EHOWARDX
  122. * Completed NonStandard Message and H.225.0 Maximum Skew indication
  123. * implementation. Added ASN.1 validation to H245SetLocalCap and
  124. * H245SetCapDescriptor. Check-in from Microsoft drop on 17-May-96.
  125. *
  126. * Rev 1.14 20 May 1996 14:35:12 EHOWARDX
  127. * Got rid of asynchronous H245EndConnection/H245ShutDown stuff...
  128. *
  129. * Rev 1.13 17 May 1996 14:53:38 EHOWARDX
  130. * Added calls to StartSystemClose() and EndSystemClose().
  131. *
  132. * Rev 1.12 16 May 1996 19:40:30 EHOWARDX
  133. * Fixed multiplex capability bug.
  134. *
  135. * Rev 1.11 16 May 1996 16:36:10 EHOWARDX
  136. * Fixed typo in H245SetCapDescriptor.
  137. *
  138. * Rev 1.10 16 May 1996 16:14:06 EHOWARDX
  139. * Fixed backwards-compatibility problem in H245SetLocalCap
  140. * (CapId of zero should result in dynamically-allocated cap id being used)
  141. *
  142. * Rev 1.9 16 May 1996 16:03:44 EHOWARDX
  143. * Fixed typo in H245SetCapDescriptor.
  144. *
  145. * Rev 1.8 16 May 1996 15:58:32 EHOWARDX
  146. * Fine-tuning H245SetLocalCap/H245DelLocalCap/H245SetCapDescriptor/
  147. * H245DelCapDescriptor behaviour.
  148. *
  149. * Rev 1.7 15 May 1996 21:49:46 unknown
  150. * Added call to InstanceLock() to increment lock count before call
  151. * to InstanceDelete() in H245EndConnectionPhase2().
  152. *
  153. * Rev 1.6 15 May 1996 19:54:02 unknown
  154. * Fixed H245SetCapDescriptor.
  155. *
  156. * Rev 1.5 14 May 1996 16:56:22 EHOWARDX
  157. * Last minute change from H245_IND_CAPDESC_T to H245_TOTCAPDESC_T.
  158. * H245EnumCaps() callback now uses H245_TOTCAPDESC_T instead
  159. * of separate H245_CAPDESCID_T and H245_CAPDESC_T for consistency.
  160. *
  161. * Rev 1.4 14 May 1996 15:55:44 EHOWARDX
  162. * Added mux cap handling to H245DelLocalCap.
  163. *
  164. * Rev 1.3 14 May 1996 14:06:06 EHOWARDX
  165. * Fixed abort from H245EnumCaps - if Cap Callback returns non-zero,
  166. * Cap Desc Callback is never called.
  167. *
  168. * Rev 1.2 13 May 1996 23:16:42 EHOWARDX
  169. * Fixed remote terminal capability handling.
  170. *
  171. * Rev 1.1 11 May 1996 20:32:52 EHOWARDX
  172. * Checking in for the night...
  173. *
  174. * Rev 1.0 09 May 1996 21:06:06 EHOWARDX
  175. * Initial revision.
  176. *
  177. * Rev 1.25.1.10 09 May 1996 19:31:02 EHOWARDX
  178. * Redesigned thread locking logic.
  179. * Added new API functions.
  180. *
  181. * Rev 1.25.1.9 01 May 1996 19:31:16 EHOWARDX
  182. * Added H245CopyCap(), H245FreeCap(), H245CopyMux(), H245FreeMux().
  183. * Changed H2250_xxx definitions for H.225.0 address types to H245_xxx.
  184. *
  185. * Rev 1.25.1.8 27 Apr 1996 21:09:20 EHOWARDX
  186. * Changed Channel Numbers to words, added H.225.0 support.
  187. *
  188. * Rev 1.25.1.7 25 Apr 1996 20:06:26 EHOWARDX
  189. * Moved setting of EndSessionPdu in EndSessionPhase1 to before call to api_fs
  190. *
  191. * Rev 1.25.1.6 25 Apr 1996 17:57:00 EHOWARDX
  192. * Added dwTxPort argument to H245OpenChannel().
  193. *
  194. * Rev 1.25.1.5 25 Apr 1996 16:51:00 EHOWARDX
  195. * Function changes as per H.245 API Changes spec.
  196. *
  197. * Rev 1.25.1.4 24 Apr 1996 20:54:32 EHOWARDX
  198. * Added new OpenLogicalChannelAck/OpenLogicalChannelReject support.
  199. *
  200. * Rev 1.25.1.3 19 Apr 1996 12:54:40 EHOWARDX
  201. * Updated to 1.30
  202. *
  203. * Rev 1.25.1.2 15 Apr 1996 15:10:48 EHOWARDX
  204. * Updated to match Curt's current version.
  205. *
  206. * Rev 1.25.1.1 03 Apr 1996 17:12:50 EHOWARDX
  207. * Integrated latest H.323 changes.
  208. *
  209. * Rev 1.25.1.0 03 Apr 1996 15:53:42 cjutzi
  210. * Branched for H.323.
  211. *
  212. * Rev 1.20 27 Mar 1996 15:25:34 cjutzi
  213. * - fixed a bug from this morning checkin dynamically allocating
  214. * pdu's.. free_mux_tbl was getting called after pdu was free'd..
  215. * this was a problem since the mux table pointer was in the pdu
  216. *
  217. * Rev 1.19 27 Mar 1996 08:37:08 cjutzi
  218. *
  219. * - removed PDU from stack.. made them dynamically allocated
  220. *
  221. * Rev 1.18 20 Mar 1996 14:47:32 cjutzi
  222. * - added ERROR H245_ERROR_NO_CAPDESC to SendTermCaps.
  223. *
  224. * Rev 1.17 18 Mar 1996 15:23:16 cjutzi
  225. *
  226. *
  227. *
  228. * Rev 1.16 13 Mar 1996 09:15:44 cjutzi
  229. *
  230. * - changed LLPCRITICAL_SECTION to CRITICAL_SECTION *
  231. *
  232. * Rev 1.15 12 Mar 1996 15:51:48 cjutzi
  233. *
  234. * - implemented locking
  235. * - fixed callback bug w/ clenaup on term caps..
  236. * - implemented End Session
  237. * - fixed shutdown
  238. *
  239. * Rev 1.14 08 Mar 1996 14:02:48 cjutzi
  240. *
  241. * - removed H245SetSimultaneous stuff..
  242. * - added H245SetCapDescriptor Stuff..
  243. * - completeed MuxTable Entry Stuff.
  244. * - required H223 -or- some portion of MuxCapbilities to be
  245. * there before you issue SendCaps..
  246. * - NOTE: need to inforce the Simultaneous capabilities in
  247. * the same mannor..
  248. *
  249. * Rev 1.13 05 Mar 1996 17:35:38 cjutzi
  250. *
  251. * - implemented SendMultiplexTable..
  252. * - removed bcopy/bzero and changed free call
  253. * - added master slave indication
  254. *
  255. * Rev 1.12 01 Mar 1996 13:48:24 cjutzi
  256. *
  257. * - added hani's new fsm id's
  258. * - added some support for release on close request.
  259. *
  260. * Rev 1.11 29 Feb 1996 17:27:10 cjutzi
  261. *
  262. * - bi-directional channel working..
  263. *
  264. * Rev 1.10 29 Feb 1996 08:35:52 cjutzi
  265. *
  266. * - added p_ossWorld to initialization
  267. *
  268. * Rev 1.9 27 Feb 1996 13:30:18 cjutzi
  269. *
  270. * - fixed master slave problem with conf_ind and tracker type
  271. * - removed RSP_LCSE in close channel resp
  272. *
  273. * Rev 1.8 26 Feb 1996 17:23:18 cjutzi
  274. *
  275. * - MiscCommand API added
  276. * - Fixed Assert for H245Init.. was not NULL'n out the pointers for the
  277. * context blocks..
  278. *
  279. * Rev 1.7 26 Feb 1996 11:05:16 cjutzi
  280. *
  281. * - added simultaneous caps.. and fixed bugs..
  282. * lot's of changes..
  283. *
  284. * Rev 1.6 16 Feb 1996 13:01:08 cjutzi
  285. *
  286. * - got open / close / request close working in both directions.
  287. *
  288. * Rev 1.5 15 Feb 1996 14:42:54 cjutzi
  289. *
  290. * - fixed trace level bind w/ Instance.. no other change but had to
  291. * add when h245deb.c when in..
  292. *
  293. *
  294. * Rev 1.4 15 Feb 1996 10:50:54 cjutzi
  295. *
  296. * - termcaps working
  297. * - changed API interface for MUX_T
  298. * - changed callback or IND_OPEN
  299. * - changed constants IND_OPEN/IND_OPEN_NEEDRSP etc..
  300. * - cleaned up the open.. (not complete yet.. )
  301. *
  302. * Rev 1.3 09 Feb 1996 16:58:36 cjutzi
  303. *
  304. * - cleanup.. and some fixes..
  305. * - added and or changed headers to reflect the log of changes
  306. *
  307. *****************************************************************************/
  308. /****************************************************************************/
  309. /****************************************************************************/
  310. /****************************************************************************/
  311. /**** *****/
  312. /**** NOTES TO THE READER *****/
  313. /**** *****/
  314. /**** This program has been put together using a a screen which is *****/
  315. /**** wider than 80 characters.. It is best if a similar screen size is *****/
  316. /**** used.. Of course emacs is my preference but 80 col screens will *****/
  317. /**** cause you much frustration.. *****/
  318. /**** *****/
  319. /**** Tabs are set to 8 *****/
  320. /**** *****/
  321. /**** NOTE: *****/
  322. /**** Headers are documented, however they may or may not *****/
  323. /**** coorispond to reality. See the H245Spec.doc from Intel for the *****/
  324. /**** current :-> H245 specification *****/
  325. /**** *****/
  326. /**** DISCLAMER: *****/
  327. /**** *****/
  328. /**** Since this code wasn't developed in Word 7.0, I am fully *****/
  329. /**** responsable for all spelling mistakes in the comments. Please *****/
  330. /**** disregard the spelling mistakes.. or fix them, if you are *****/
  331. /**** currently modifying the code. *****/
  332. /**** *****/
  333. /**** - Thankyou *****/
  334. /**** *****/
  335. /**** Curt Jutzi *****/
  336. /**** Oregon, USA *****/
  337. /**** *****/
  338. /****************************************************************************/
  339. /****************************************************************************/
  340. /****************************************************************************/
  341. #ifndef STRICT
  342. #define STRICT
  343. #endif
  344. #include "precomp.h"
  345. /***********************/
  346. /* H245 INCLUDES */
  347. /***********************/
  348. #define H245DLL_EXPORT
  349. #include "h245api.h"
  350. #include "h245com.h"
  351. #include "h245sys.x"
  352. #include "api_util.x"
  353. #include "pdu.x"
  354. #include "fsmexpor.h"
  355. #include "api_debu.x"
  356. #include "sr_api.h"
  357. #include "h245deb.x"
  358. /*****************************************************************************
  359. *
  360. * TYPE: H245 API
  361. *
  362. *****************************************************************************
  363. *
  364. * PROCEDURE: H245Init
  365. *
  366. * DESCRIPTION
  367. *
  368. * H245_INST_T H245Init (
  369. * H245_CONF_T Configuration,
  370. * DWORD dwH245PhysId,
  371. * DWORD dwLinkLayerPhysId,
  372. * DWORD dwPreserved,
  373. * H245_CONF_IND_CALLBACK_T Callback
  374. * )
  375. * Description:
  376. *
  377. * Called to create an H.245 instance and its related sublayers
  378. * (e.g., SRP). This function must be called before any other
  379. * API calls may be called The current H.245 implementation can
  380. * only have, at most, one client. Therefore H245Init can only be
  381. * called once per physical ID.
  382. * Input
  383. *
  384. * Configuration Indicates the type of configuration the client
  385. * wishes to establish, e.g. H.324, H.323, H.310,
  386. * or DSVD.
  387. * dwH245PhysId Parameter identifying the H245 entry
  388. * pdwLinkLayerPhysId
  389. * Output parameter identifying the linkLayer
  390. * entry.
  391. * dwPreserved Parameter that may be used by H.245 client to
  392. * provide context, passed back to client in all
  393. * confirms and indications.
  394. * Callback Callback routine supplied by the client which
  395. * will be used by the H.245 subsystem to convey
  396. * confirm and indication messages back to the
  397. * client.
  398. * Call Type:
  399. *
  400. * Synchronous
  401. *
  402. * Return Values:
  403. *
  404. * Return value of 0 indicates Failure
  405. * Return value of non 0 is a valid H245_INST_T
  406. *
  407. * Errors:
  408. * N/A
  409. *
  410. * See Also:
  411. * H245EndSession
  412. * H245Shutdown
  413. *
  414. *
  415. *****************************************************************************/
  416. H245DLL H245_INST_T
  417. H245Init (
  418. H245_CONFIG_T Configuration,
  419. unsigned long dwH245PhysId,
  420. unsigned long *pdwLinkLayerPhysId,
  421. DWORD_PTR dwPreserved,
  422. H245_CONF_IND_CALLBACK_T CallBack,
  423. unsigned char byTerminalType
  424. )
  425. {
  426. register struct InstanceStruct *pInstance;
  427. HRESULT lError;
  428. H245TRACE(dwH245PhysId,4,"H245Init(%d, 0x%x, 0x%x, 0x%x, %d) <-",
  429. Configuration, dwH245PhysId, dwPreserved, CallBack, byTerminalType);
  430. switch (Configuration)
  431. {
  432. case H245_CONF_H324:
  433. case H245_CONF_H323:
  434. break;
  435. default:
  436. H245TRACE(dwH245PhysId,1,"H245Init -> Invalid Configuration %d", Configuration);
  437. return H245_INVALID_ID;
  438. } // switch
  439. if (CallBack == NULL)
  440. {
  441. H245TRACE(dwH245PhysId,1,"H245Init -> Null CallBack");
  442. return H245_INVALID_ID;
  443. }
  444. /* see if this physical identifier has been initialized already */
  445. // Send down H245PhysId that was input.
  446. pInstance = InstanceCreate(dwH245PhysId, Configuration);
  447. if (pInstance == NULL)
  448. {
  449. return H245_INVALID_ID;
  450. }
  451. // Get the linkLayer PhysId.
  452. *pdwLinkLayerPhysId = pInstance->SendReceive.hLinkLayerInstance;
  453. // Initialize instance API structure
  454. pInstance->API.dwPreserved = dwPreserved;
  455. pInstance->API.ConfIndCallBack = CallBack;
  456. // Initialize instance FSM structure
  457. pInstance->StateMachine.sv_TT = byTerminalType;
  458. pInstance->StateMachine.sv_STATUS = INDETERMINATE;
  459. H245TRACE(pInstance->dwInst,4,"H245Init -> %d", pInstance->dwInst);
  460. lError = pInstance->dwInst;
  461. InstanceUnlock(pInstance);
  462. return lError;
  463. } // H245Init()
  464. /*****************************************************************************
  465. *
  466. * TYPE: H245 API
  467. *
  468. *****************************************************************************
  469. *
  470. * PROCEDURE: H245EndSession
  471. *
  472. * DESCRIPTION
  473. *
  474. * Yes.. this should be explained.. Since Send Receive needs
  475. * to flush some buffers and send out an End Session.. what we've
  476. * hopefully done is a 2 phase shut down...
  477. *
  478. * call StartSessionClose which initiates the flush..
  479. * when flush is complete EndSessionPhase1 is called..
  480. * The end session pdu is then placed in the send queue..
  481. * When the End Session Pdu is sent.. the EndSession Phase
  482. * 2 is called, and the result is sent up to the client..
  483. *
  484. * Hope that helps..
  485. *
  486. *
  487. * HRESULT H245EndSession ( H245_INST_T dwInst,
  488. * H245_ENDSESSION_T Mode,
  489. * H245_NONSTANDARD_T *pNonStd (*optional*)
  490. * )
  491. *
  492. * Description:
  493. * Called to shutdown the peer to peer session between this H.245
  494. * session and the remote peers H.245 layer.
  495. *
  496. * It will terminate by issuing an EndSession command to the
  497. * remote side and call end session for all the H.245 subsystems.
  498. * All resources are returned; therefore no further action is
  499. * permitted, except H245ShutDown until another H245Init API call
  500. * is made.
  501. *
  502. * input
  503. * dwInst Instance handle returned by H245Init
  504. * Mode Mode which the client wishes to terminat
  505. * the session
  506. * pNonStd If the mode is non standard this is the non
  507. * standard parameter passes to the remote client.
  508. * This parameter is optional, and should be set
  509. * to NULL if not used
  510. *
  511. * Call Type:
  512. * Asynchronous
  513. *
  514. * Return Values:
  515. * See Errors
  516. *
  517. * Errors:
  518. * H245_ERROR_OK
  519. * H245_ERROR_PARAM
  520. * H245_ERROR_INVALID_INST
  521. * H245_ERROR_NOT_CONNECTED
  522. * See Also:
  523. * H245Shutdown
  524. * H245Init
  525. *
  526. *****************************************************************************/
  527. H245DLL HRESULT
  528. H245EndSession (
  529. H245_INST_T dwInst,
  530. H245_ENDSESSION_T Mode,
  531. const H245_NONSTANDARD_PARAMETER_T * pNonStd
  532. )
  533. {
  534. register struct InstanceStruct *pInstance;
  535. register MltmdSystmCntrlMssg *pPdu;
  536. HRESULT lError;
  537. H245TRACE (dwInst,4,"H245EndSession <-");
  538. /* check for valid instance handle */
  539. pInstance = InstanceLock(dwInst);
  540. if (pInstance == NULL)
  541. {
  542. H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_INVALID_INST));
  543. return H245_ERROR_INVALID_INST;
  544. }
  545. /* system should be in either connecting or connected */
  546. switch (pInstance->API.SystemState)
  547. {
  548. case APIST_Connecting:
  549. case APIST_Connected:
  550. break;
  551. default:
  552. H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  553. InstanceUnlock(pInstance);
  554. return H245_ERROR_NOT_CONNECTED;
  555. }
  556. // Allocate the PDU buffer
  557. pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
  558. if (pPdu == NULL)
  559. {
  560. H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(H245_ERROR_NOMEM));
  561. InstanceUnlock(pInstance);
  562. return H245_ERROR_NOMEM;
  563. }
  564. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  565. // Build the PDU
  566. lError = pdu_cmd_end_session (pPdu, Mode, pNonStd);
  567. if (lError == H245_ERROR_OK)
  568. {
  569. // Send the PDU
  570. lError = FsmOutgoing(pInstance, pPdu, 0);
  571. }
  572. // Free the PDU buffer
  573. MemFree(pPdu);
  574. if (lError != H245_ERROR_OK)
  575. {
  576. H245TRACE (dwInst,1,"H245EndSession -> %s",map_api_error(lError));
  577. }
  578. else
  579. {
  580. H245TRACE (dwInst,4,"H245EndSession -> OK");
  581. pInstance->API.SystemState = APIST_Disconnected;
  582. }
  583. InstanceUnlock(pInstance);
  584. return lError;
  585. } // H245EndSession()
  586. /*****************************************************************************
  587. *
  588. * TYPE: H245 API
  589. *
  590. *****************************************************************************
  591. *
  592. * PROCEDURE: H245ShutDown
  593. *
  594. * DESCRIPTION
  595. *
  596. * HRESULT H245Shutdown ( H245_INST_T dwInst);
  597. *
  598. * Description:
  599. *
  600. * Called to terminate the specified instance of H.245. If there
  601. * is currently an active session (see H245Init) then the H.245
  602. * subsystem will issue an EndSession to the other side and wait
  603. * for H.245 sublayer termination notifications before it queues
  604. * Callback confirm.
  605. *
  606. * This call will force the client to issue another H245Init
  607. * before it can use any of the H.245 API functions.
  608. *
  609. * Input
  610. * dwInst Instance handle returned by H245Init
  611. *
  612. * Call Type:
  613. * asynchronous
  614. *
  615. * Return Values:
  616. * See Errors
  617. *
  618. * Errors:
  619. * H245_ERROR_OK
  620. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  621. *
  622. * See Also:
  623. * H245Init
  624. *
  625. *****************************************************************************/
  626. H245DLL HRESULT
  627. H245ShutDown (H245_INST_T dwInst)
  628. {
  629. register struct InstanceStruct *pInstance;
  630. register HRESULT lError;
  631. H245TRACE (dwInst,4,"H245ShutDown <-");
  632. /* check for valid instance handle */
  633. pInstance = InstanceLock(dwInst);
  634. if (pInstance == NULL)
  635. {
  636. H245TRACE (dwInst,1,"H245ShutDown -> %s",map_api_error(H245_ERROR_INVALID_INST));
  637. return H245_ERROR_INVALID_INST;
  638. }
  639. switch (pInstance->API.SystemState)
  640. {
  641. case APIST_Connecting:
  642. case APIST_Connected:
  643. lError = H245EndSession(dwInst,H245_ENDSESSION_DISCONNECT,NULL);
  644. break;
  645. default:
  646. lError = H245_ERROR_OK;
  647. }
  648. if (lError != H245_ERROR_OK)
  649. H245TRACE (dwInst,1,"H245ShutDown -> %s", map_api_error(lError));
  650. else
  651. H245TRACE (dwInst,4,"H245ShutDown -> OK");
  652. InstanceDelete (pInstance);
  653. return H245_ERROR_OK;
  654. } // H245ShutDown()
  655. /*****************************************************************************
  656. *
  657. * TYPE: H245 API
  658. *
  659. *****************************************************************************
  660. *
  661. * PROCEDURE: H245InitMasterSlave
  662. *
  663. * DESCRIPTION
  664. *
  665. * HRESULT H245InitMasterSlave ( H245_INST_T dwInst,
  666. * DWORD dwTransId )
  667. *
  668. * Description:
  669. * Called to initiate the H.245 master slave negotiation.
  670. * Upon completion of the negotiation the local client will
  671. * receive an H245_CONF_INIT_MSTSLV message indicating the
  672. * result of the negotiation.
  673. * Input
  674. * dwInst Instance handle returned by
  675. * H245GetInstanceId
  676. * dwTransId User supplied object used to identify this
  677. * request in the asynchronous response to
  678. * this call.
  679. *
  680. * Call Type:
  681. * Asynchronous
  682. *
  683. * Return Values:
  684. * See Errors
  685. *
  686. * Callbacks:
  687. * H245_CONF_INIT_MSTSLV
  688. *
  689. * Errors:
  690. * H245_ERROR_OK Master Slave Determination started
  691. * H245_ERROR_INPROCESS Master Slave Determination currently
  692. * in process
  693. * H245_ERROR_NOMEM
  694. * H245_ERROR_INPROCESS In process
  695. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  696. *
  697. * See Also:
  698. * H245Init
  699. *
  700. * callbacks
  701. * H245_IND_MSTSLV
  702. *
  703. *
  704. *****************************************************************************/
  705. H245DLL HRESULT
  706. H245InitMasterSlave (
  707. H245_INST_T dwInst,
  708. DWORD_PTR dwTransId
  709. )
  710. {
  711. struct InstanceStruct *pInstance;
  712. Tracker_T *pTracker;
  713. HRESULT lError;
  714. MltmdSystmCntrlMssg *pPdu = NULL;
  715. /* check for valid instance handle */
  716. H245TRACE (dwInst,4,"H245InitMasterSlave <-");
  717. pInstance = InstanceLock(dwInst);
  718. if (pInstance == NULL)
  719. {
  720. H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INVALID_INST));
  721. return H245_ERROR_INVALID_INST;
  722. }
  723. /* if the transaction is in process.. tell client */
  724. if (pInstance->API.MasterSlave == APIMS_InProcess)
  725. {
  726. H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_INPROCESS));
  727. InstanceUnlock(pInstance);
  728. return H245_ERROR_INPROCESS;
  729. }
  730. /* if the transaction is already complete */
  731. if (pInstance->API.MasterSlave != APIMS_Undef)
  732. {
  733. if (pInstance->API.ConfIndCallBack)
  734. {
  735. H245_CONF_IND_T confirm_ind_event;
  736. confirm_ind_event.Kind = H245_CONF;
  737. confirm_ind_event.u.Confirm.Confirm = H245_CONF_INIT_MSTSLV;
  738. confirm_ind_event.u.Confirm.dwPreserved = pInstance->API.dwPreserved;
  739. confirm_ind_event.u.Confirm.dwTransId = dwTransId;
  740. confirm_ind_event.u.Confirm.Error = H245_ERROR_OK;
  741. confirm_ind_event.u.Confirm.u.ConfMstSlv =
  742. (pInstance->API.MasterSlave == APIMS_Master) ? H245_MASTER : H245_SLAVE;
  743. (*pInstance->API.ConfIndCallBack)(&confirm_ind_event, NULL);
  744. }
  745. H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
  746. InstanceUnlock(pInstance);
  747. return H245_ERROR_OK;
  748. }
  749. /* get somthing to keep track of what the heck you're doing.. */
  750. if (!(pTracker = alloc_link_tracker (pInstance,
  751. API_MSTSLV_T,
  752. dwTransId,
  753. API_ST_WAIT_RMTACK,
  754. API_CH_ALLOC_UNDEF,
  755. API_CH_TYPE_UNDEF,
  756. 0,
  757. H245_INVALID_CHANNEL,
  758. H245_INVALID_CHANNEL,
  759. 0)))
  760. {
  761. H245TRACE(dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
  762. InstanceUnlock(pInstance);
  763. return H245_ERROR_NOMEM;
  764. }
  765. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  766. {
  767. H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(H245_ERROR_NOMEM));
  768. InstanceUnlock(pInstance);
  769. return H245_ERROR_NOMEM;
  770. }
  771. /* set master slave in process */
  772. pInstance->API.SystemState = APIST_Connecting;
  773. pInstance->API.MasterSlave = APIMS_InProcess;
  774. memset(pPdu, 0, sizeof(*pPdu));
  775. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  776. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = masterSlaveDetermination_chosen;
  777. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  778. MemFree(pPdu);
  779. if (lError != H245_ERROR_OK)
  780. {
  781. unlink_dealloc_tracker (pInstance, pTracker);
  782. H245TRACE (dwInst,1,"H245InitMasterSlave -> %s",map_api_error(lError));
  783. }
  784. else
  785. H245TRACE (dwInst,4,"H245InitMasterSlave -> OK");
  786. InstanceUnlock(pInstance);
  787. return lError;
  788. } // H245InitMasterSlave()
  789. /*****************************************************************************
  790. *
  791. * TYPE: H245 API
  792. *
  793. *****************************************************************************
  794. *
  795. * PROCEDURE: H245SetLocalCap
  796. *
  797. * DESCRIPTION
  798. *
  799. * HRESULT H245SetLocalCap (
  800. * H245_INST_T dwInst,
  801. * H245_TOTCAP_T *pTotCap,
  802. * H245_CAPID_T *pCapId
  803. * )
  804. *
  805. * Description:
  806. * This function allows the client to define a specific
  807. * capability to the H.245 subsystem. When this function is
  808. * called a new capability entry is made in the local capability
  809. * table. The returned value in *pCapId can be used by the client
  810. * to refer to that registered capability. NULL in the *pCapId
  811. * is valid.
  812. *
  813. * This call is used for both client (Audio / Video / Data / Mux)
  814. * capabilities. It is not used for setting capability descriptors.
  815. *
  816. * Note:
  817. * 7 This function does not communicate this update to the
  818. * remote peer until the client calls H245SendTermCaps.
  819. * 7 pTotCap->CapId is of no significance in this call.
  820. *
  821. * pTotCap->CapId is of no significance in this call and should
  822. * be set to 0
  823. *
  824. * if DataType of H245_DATA_MUX is used (i.e. in setting the
  825. * mux table capabilities) No capid is returned, and it can not
  826. * be used in H245SetCapDescritptor api call.
  827. *
  828. * Input
  829. * dwInst Instance handle returned by GetInstanceId
  830. * pTotCap Capability set defining the capability
  831. *
  832. * Note: pTotCap->CapId is of no significance in this call.
  833. *
  834. * output
  835. * pCapId Capability id which client can use to reference
  836. * this capability in the H.245 subsystem. This can
  837. * be NULL, in this case nothing is returned.
  838. *
  839. * Call Type:
  840. * Synchronous
  841. *
  842. * Return Values:
  843. * If pCap is not null, the local cap table id is returned
  844. * to the client in this parameter.
  845. *
  846. * Errors:
  847. * H245_ERROR_OK
  848. * H245_ERROR_PARAM There was an invalid parameter passed
  849. * H245_ERROR_MAXTBL Entry not made because local cap table
  850. * is full
  851. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  852. *
  853. * See Also:
  854. * H245DelLocalCap
  855. * H245EnumCaps
  856. * H245SetCapDescriptor
  857. *
  858. *
  859. * ASSUMPTION:
  860. * pTotCap->CapId will be set to H245_INVALID_CAPID
  861. * pTotCap->Dir will be set
  862. *
  863. *****************************************************************************/
  864. H245DLL HRESULT
  865. H245SetLocalCap (
  866. H245_INST_T dwInst,
  867. H245_TOTCAP_T * pTotCap,
  868. H245_CAPID_T * pCapId
  869. )
  870. {
  871. register struct InstanceStruct *pInstance;
  872. struct TerminalCapabilitySet *pTermCapSet;
  873. HRESULT lError;
  874. H245TRACE (dwInst,4,"H245SetLocalCap <-");
  875. /* check for valid instance handle */
  876. pInstance = InstanceLock(dwInst);
  877. if (pInstance == NULL)
  878. {
  879. H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
  880. return H245_ERROR_INVALID_INST;
  881. }
  882. /* check for valid parameters */
  883. if (pTotCap == NULL ||
  884. pCapId == NULL ||
  885. ((*pCapId > H245_MAX_CAPID) && (*pCapId != H245_INVALID_CAPID)) ||
  886. pTotCap->Dir < H245_CAPDIR_LCLRX ||
  887. pTotCap->Dir > H245_CAPDIR_LCLRXTX ||
  888. pTotCap->ClientType < H245_CLIENT_NONSTD ||
  889. pTotCap->ClientType > H245_CLIENT_MUX_H2250)
  890. {
  891. H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_PARAM));
  892. InstanceUnlock(pInstance);
  893. return H245_ERROR_PARAM;
  894. }
  895. pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  896. // Don't trust the user filled-in data type!
  897. pTotCap->DataType = DataTypeMap[pTotCap->ClientType];
  898. /* if it's a MUX type handle here */
  899. if (pTotCap->DataType == H245_DATA_MUX)
  900. {
  901. // Add multiplex capability
  902. if (pTermCapSet->bit_mask & multiplexCapability_present)
  903. {
  904. del_mux_cap(pTermCapSet);
  905. }
  906. *pCapId = pTotCap->CapId = 0;
  907. lError = set_mux_cap(pInstance, pTermCapSet, pTotCap);
  908. #if defined(_DEBUG)
  909. if (lError == H245_ERROR_OK)
  910. {
  911. // Validate mux capability
  912. if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
  913. {
  914. // Bad mux capability - delete it
  915. del_mux_cap(pTermCapSet);
  916. lError = H245_ERROR_ASN1;
  917. }
  918. }
  919. #endif // (DEBUG)
  920. }
  921. else if (*pCapId == 0 || *pCapId == H245_INVALID_CAPID)
  922. {
  923. // Assign the next never-used cap id
  924. if (pInstance->API.LocalCapIdNum == H245_INVALID_CAPID)
  925. {
  926. // All possible capability identifiers have been assigned
  927. H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(H245_ERROR_MAXTBL));
  928. InstanceUnlock(pInstance);
  929. return H245_ERROR_MAXTBL;
  930. }
  931. *pCapId = pInstance->API.LocalCapIdNum;
  932. /* insert in the new capability in the local capability set table */
  933. pTotCap->CapId = *pCapId;
  934. lError = set_capability(pInstance, pTermCapSet, pTotCap);
  935. #if defined(_DEBUG)
  936. if (lError == H245_ERROR_OK)
  937. {
  938. // Validate capability
  939. if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
  940. {
  941. // Bad capability - delete it
  942. H245DelLocalCap(dwInst, *pCapId);
  943. lError = H245_ERROR_ASN1;
  944. }
  945. }
  946. #endif // (DEBUG)
  947. if (lError == H245_ERROR_OK)
  948. pInstance->API.LocalCapIdNum++;
  949. }
  950. else
  951. {
  952. /* insert in the new capability in the local capability set table */
  953. pTotCap->CapId = *pCapId;
  954. lError = set_capability(pInstance, pTermCapSet, pTotCap);
  955. #if defined(_DEBUG)
  956. if (lError == H245_ERROR_OK)
  957. {
  958. // Validate capability
  959. if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
  960. {
  961. // Bad capability - delete it
  962. H245DelLocalCap(dwInst, *pCapId);
  963. lError = H245_ERROR_ASN1;
  964. }
  965. }
  966. #endif // (DEBUG)
  967. }
  968. if (lError != H245_ERROR_OK)
  969. {
  970. H245TRACE (dwInst,1,"H245SetLocalCap -> %s",map_api_error(lError));
  971. pTotCap->CapId = *pCapId = H245_INVALID_CAPID;
  972. }
  973. else
  974. {
  975. H245TRACE (dwInst,4,"H245SetLocalCap -> OK");
  976. }
  977. InstanceUnlock(pInstance);
  978. return lError;
  979. } // H245SetLocalCap()
  980. /*****************************************************************************
  981. *
  982. * TYPE: H245 API
  983. *
  984. *****************************************************************************
  985. *
  986. * PROCEDURE: H245DelLocalCap
  987. *
  988. * DESCRIPTION Delete Local Cap simply disables the cap.. it
  989. * will not be updated until the client issues
  990. * H245SendTermCaps
  991. *
  992. *
  993. * HRESULT H245DelLocalCap(
  994. * H245_INST_T dwInst,
  995. * H245_CAPID_T CapId
  996. * )
  997. *
  998. * Description:
  999. * This function allows the client to delete a specific
  1000. * capability id in the H.245 subsystem.
  1001. *
  1002. * Note: This function does not communicate this update
  1003. * to the remote peer until the client calls H245SendTermCaps.
  1004. *
  1005. * Input
  1006. * dwInst Instance handle returned by H245GetInstanceId
  1007. * CapId Cap Id the client wishes to remove from the
  1008. * capability table.
  1009. *
  1010. * If an error occurs no action is taken and the CapId the
  1011. * client wished to delete is not changed.
  1012. *
  1013. * Call Type:
  1014. * Synchronous
  1015. *
  1016. * Return Values:
  1017. * See Errors
  1018. *
  1019. * Errors:
  1020. * H245_ERROR_OK Capability deleted
  1021. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  1022. *
  1023. * See Also:
  1024. * H245SetLocalCap
  1025. * H245SendTermCaps
  1026. * H245EnumCaps
  1027. *
  1028. * RETURN:
  1029. *
  1030. *****************************************************************************/
  1031. H245DLL HRESULT
  1032. H245DelLocalCap (
  1033. H245_INST_T dwInst,
  1034. H245_CAPID_T CapId
  1035. )
  1036. {
  1037. register struct InstanceStruct *pInstance;
  1038. struct TerminalCapabilitySet *pTermCapSet;
  1039. CapabilityTableLink pCapLink;
  1040. HRESULT lError = H245_ERROR_OK;
  1041. H245TRACE (dwInst,4,"H245DelLocalCap <-");
  1042. /* check for valid instance handle */
  1043. pInstance = InstanceLock(dwInst);
  1044. if (pInstance == NULL)
  1045. {
  1046. H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1047. return H245_ERROR_INVALID_INST;
  1048. }
  1049. pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  1050. if (CapId == 0)
  1051. {
  1052. // Delete multiplex capability
  1053. del_mux_cap(pTermCapSet);
  1054. }
  1055. else
  1056. {
  1057. /* (TBC) if I delete my capability id.. what about simultaneous caps ?? */
  1058. /* should I go through the list and deactivate them ?? */
  1059. pCapLink = find_capid_by_entrynumber (pTermCapSet, CapId);
  1060. if (pCapLink)
  1061. {
  1062. // Delete terminal capability
  1063. disable_cap_link (pCapLink);
  1064. }
  1065. else
  1066. {
  1067. lError = H245_ERROR_PARAM;
  1068. }
  1069. }
  1070. if (lError != H245_ERROR_OK)
  1071. H245TRACE (dwInst,1,"H245DelLocalCap -> %s",map_api_error(lError));
  1072. else
  1073. H245TRACE (dwInst,4,"H245DelLocalCap -> OK");
  1074. InstanceUnlock(pInstance);
  1075. return lError;
  1076. } // H245DelLocalCap()
  1077. /*****************************************************************************
  1078. *
  1079. * TYPE: H245 API
  1080. *
  1081. *****************************************************************************
  1082. *
  1083. * PROCEDURE: H245SetCapDescriptor
  1084. *
  1085. * DESCRIPTION
  1086. *
  1087. * HRESULT H245SetCapDescriptor (
  1088. * H245_INST_T dwInst,
  1089. * H245_CAPDESC_T *pCapDesc,
  1090. * H245_CAPDESCID_T *pCapDescId (* Optional *)
  1091. * )
  1092. * Description:
  1093. * This procedure is called to set local capability descriptors.
  1094. * It will return a capability descriptor id in the parameter
  1095. * *pCapDescId if it is non null.
  1096. *
  1097. * Note:
  1098. * These capabilities are communicated via the H245SendTermCaps
  1099. * API call. Any updates to the CapDescriptor table (either
  1100. * additions or deletions ) will not be communicated to the
  1101. * remote side until the H245SendTermCaps call is made.
  1102. *
  1103. * Input
  1104. * dwInst Instance handle returned by H245Init
  1105. * CapDesc This is the capability Descriptor you wish
  1106. * to set
  1107. * Output
  1108. * pCapDescId optional: Capability id that will be returned.
  1109. *
  1110. * Call Type:
  1111. * Synchronous
  1112. *
  1113. * Return Values:
  1114. * See Errors
  1115. *
  1116. * Errors:
  1117. * H245_ERROR_OK
  1118. * H245_ERROR_INVALID_CAPID Capid used in CapDesc was not
  1119. * registred
  1120. * H245_ERROR_MAXTB Out of table space to store Descriptor
  1121. * H245_ERROR_PARAM Descriptor is too long or not valid
  1122. * H245_ERROR_NOMEM
  1123. * H245_ERROR_INVALID_INST
  1124. *
  1125. * See Also:
  1126. * H245DelCapDescriptor
  1127. * H245SendTermCaps
  1128. *
  1129. * ASSUMES:
  1130. * SimCapId is the array entry point in the apabilityDescriptors
  1131. * array.. this has a limitation, in that you can never wrap the
  1132. * array at 256.. this will be cleaned up when array is turned into
  1133. * linked list.
  1134. *
  1135. *****************************************************************************/
  1136. H245DLL HRESULT
  1137. H245SetCapDescriptor (
  1138. H245_INST_T dwInst,
  1139. H245_CAPDESC_T *pCapDesc,
  1140. H245_CAPDESCID_T *pCapDescId
  1141. )
  1142. {
  1143. register struct InstanceStruct *pInstance;
  1144. HRESULT lError;
  1145. H245TRACE (dwInst,4,"H245SetCapDescriptor <-");
  1146. /* check for valid instance handle */
  1147. pInstance = InstanceLock(dwInst);
  1148. if (pInstance == NULL)
  1149. {
  1150. H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1151. return H245_ERROR_INVALID_INST;
  1152. }
  1153. /* must have capdescriptor && */
  1154. /* length must be less than 256 */
  1155. if (pCapDesc == NULL ||
  1156. pCapDesc->Length >= 256 ||
  1157. pCapDescId == NULL)
  1158. {
  1159. H245TRACE (dwInst,1,"H245SetCapDescriptor -> %s",map_api_error(H245_ERROR_PARAM));
  1160. InstanceUnlock(pInstance);
  1161. return H245_ERROR_PARAM;
  1162. }
  1163. if (*pCapDescId >= 256)
  1164. {
  1165. // Assign the next never-used cap id
  1166. if (pInstance->API.LocalCapDescIdNum >= 256)
  1167. {
  1168. // All possible capability identifiers have been assigned
  1169. H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(H245_ERROR_MAXTBL));
  1170. InstanceUnlock(pInstance);
  1171. return H245_ERROR_MAXTBL;
  1172. }
  1173. *pCapDescId = pInstance->API.LocalCapDescIdNum;
  1174. /* insert in the new capability descriptor in the local capability descriptor table */
  1175. lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
  1176. &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
  1177. #if defined(_DEBUG)
  1178. if (lError == H245_ERROR_OK)
  1179. {
  1180. // Validate Capability Descriptor
  1181. if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
  1182. {
  1183. // Capability Descriptor Invalid - delete it
  1184. H245DelCapDescriptor(dwInst, *pCapDescId);
  1185. lError = H245_ERROR_ASN1;
  1186. }
  1187. }
  1188. #endif // (DEBUG)
  1189. if (lError == H245_ERROR_OK)
  1190. pInstance->API.LocalCapDescIdNum++;
  1191. }
  1192. else
  1193. {
  1194. /* insert in the new capability in the local capability set table */
  1195. lError = set_cap_descriptor(pInstance, pCapDesc, pCapDescId,
  1196. &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet);
  1197. #if defined(_DEBUG)
  1198. if (lError == H245_ERROR_OK)
  1199. {
  1200. // Validate Capability Descriptor
  1201. if (check_pdu(pInstance, &pInstance->API.PDU_LocalTermCap))
  1202. {
  1203. // Capability Descriptor Invalid - delete it
  1204. H245DelCapDescriptor(dwInst, *pCapDescId);
  1205. lError = H245_ERROR_ASN1;
  1206. }
  1207. }
  1208. #endif // (DEBUG)
  1209. }
  1210. if (lError != H245_ERROR_OK)
  1211. {
  1212. H245TRACE (dwInst,1,"H245CapDescriptor -> %s",map_api_error(lError));
  1213. *pCapDescId = H245_INVALID_CAPDESCID;
  1214. }
  1215. else
  1216. {
  1217. H245TRACE (dwInst,4,"H245CapDescriptor -> OK");
  1218. }
  1219. InstanceUnlock(pInstance);
  1220. return lError;
  1221. } // H245SetCapDescriptor()
  1222. /*****************************************************************************
  1223. *
  1224. * TYPE: H245 API
  1225. *
  1226. *****************************************************************************
  1227. *
  1228. * PROCEDURE: H245DelCapDescriptor
  1229. *
  1230. * DESCRIPTION
  1231. *
  1232. * HRESULT H245DelCapDescriptor (
  1233. * H245_INST_T dwInst,
  1234. * H245_CAPDESCID_T CapDescId
  1235. * )
  1236. * Description:
  1237. * This procedure is called to delete local capability descriptors.
  1238. *
  1239. * Note:
  1240. * These capabilities are communicated via the
  1241. * H245SendTermCaps API call. Any updates to the
  1242. * CapDescriptor table (either additions or deletions )
  1243. * will not be communicated to the remote side until the
  1244. * H245SendTermCaps call is made.
  1245. *
  1246. * Input
  1247. * dwInst Instance handle returned by H245Init
  1248. * CapDescId This is the capability Descriptor you wish
  1249. * to delete
  1250. * Call Type:
  1251. * Synchronous
  1252. *
  1253. * Return Values:
  1254. * See Errors
  1255. * Errors:
  1256. * H245_ERROR_OK
  1257. * H245_ERROR_INVALID_INST
  1258. *
  1259. * See Also:
  1260. * H245SetCapDescriptor
  1261. * H245SendTermCaps
  1262. *
  1263. * ASSUMES:
  1264. *
  1265. * SimCapId is the array entry point in the apabilityDescriptors
  1266. * array.. this has a limitation, in that you can never wrap the
  1267. * array at 256.. this will be cleaned up when array is turned into
  1268. * linked list.
  1269. *
  1270. *
  1271. *****************************************************************************/
  1272. H245DLL HRESULT
  1273. H245DelCapDescriptor (
  1274. H245_INST_T dwInst,
  1275. H245_CAPDESCID_T CapDescId
  1276. )
  1277. {
  1278. register struct InstanceStruct *pInstance;
  1279. CapabilityDescriptor *p_cap_desc;
  1280. struct TerminalCapabilitySet *pTermCapSet;
  1281. unsigned int uId;
  1282. H245TRACE (dwInst,4,"H245DelCapDescriptor <-");
  1283. if (CapDescId >= 256)
  1284. {
  1285. H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
  1286. return H245_ERROR_INVALID_CAPDESCID;
  1287. }
  1288. /* check for valid instance handle */
  1289. pInstance = InstanceLock(dwInst);
  1290. if (pInstance == NULL)
  1291. {
  1292. H245TRACE (dwInst,1,"API:H24DelCapDescriptor -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1293. return H245_ERROR_INVALID_INST;
  1294. }
  1295. /* get pointer to Capability Descriptor */
  1296. p_cap_desc = NULL;
  1297. pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  1298. for (uId = 0; uId < pTermCapSet->capabilityDescriptors.count; ++uId)
  1299. {
  1300. if (pTermCapSet->capabilityDescriptors.value[uId].capabilityDescriptorNumber == CapDescId)
  1301. {
  1302. p_cap_desc = &pTermCapSet->capabilityDescriptors.value[uId];
  1303. break;
  1304. }
  1305. }
  1306. if (p_cap_desc == NULL ||
  1307. p_cap_desc->smltnsCpblts == NULL ||
  1308. (p_cap_desc->bit_mask & smltnsCpblts_present) == 0)
  1309. {
  1310. H245TRACE(dwInst,1,"API:H24DelCapDescriptor -> Invalid cap desc id %d",CapDescId);
  1311. InstanceUnlock(pInstance);
  1312. return H245_ERROR_INVALID_CAPDESCID;
  1313. }
  1314. /* free up the list */
  1315. dealloc_simultaneous_cap (p_cap_desc);
  1316. /* (TBC) what if you've removed the last simultaneous cap ? */
  1317. /* in this case.. the count does not go down.. it simply */
  1318. /* removes the cap descriptor bit from the table.. */
  1319. H245TRACE (dwInst,4,"H245DelCapDescriptor -> OK");
  1320. InstanceUnlock(pInstance);
  1321. return H245_ERROR_OK;
  1322. } // H245DelCapDescriptor()
  1323. /*****************************************************************************
  1324. *
  1325. * TYPE: H245 API
  1326. *
  1327. *****************************************************************************
  1328. *
  1329. * PROCEDURE: H245SendTermCaps
  1330. *
  1331. * DESCRIPTION
  1332. *
  1333. * HRESULT
  1334. * H245SendTermCaps (
  1335. * H245_INST_T dwInst,
  1336. * DWORD dwTransId
  1337. * )
  1338. *
  1339. * Description:
  1340. *
  1341. * Called to send terminal capabilities to the remote H.245 peer.
  1342. * When remote capabilities are receive the client will be
  1343. * notified by the H245_IND_CAP indication. When remote side has
  1344. * acknowledged the local terminal capabilities and has responded
  1345. * with their terminal capabilities the client will receive an
  1346. * H245_CONF_ TERMCAP. Between H245Init and H245SendTermCap the
  1347. * client may call H245SetLocalCap to register capabilities.
  1348. * These capabilities will not be registered to the remote side
  1349. * until H245SendTermCap has been called.
  1350. *
  1351. * Note: As required by the H245 specification, Mutliplex
  1352. * capabilities, and Capability descriptors must be
  1353. * loaded before the first capability PDU is sent.
  1354. *
  1355. * Once H245SendTermCap is called, any subsequent calls to
  1356. * H245SetLocalTermCap will result in that capability being
  1357. * communicated to the remote H.245 peer.
  1358. *
  1359. * Input
  1360. * dwInst Instance handle returned by
  1361. * H245GetInstanceId
  1362. * dwTransId User supplied object used to identify
  1363. * this request in the asynchronous
  1364. * response to this call.
  1365. * Call Type:
  1366. * Asynchronous
  1367. *
  1368. * Return Values:
  1369. * See Errors
  1370. *
  1371. * Callbacks:
  1372. * H245_CONF_TERMCAP
  1373. *
  1374. * Errors:
  1375. * H245_ERROR_OK Function succeeded
  1376. * H245_ERROR_NOMEM
  1377. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  1378. * H245_ERROR_NO_MUX_CAPS no Mux capabilities have been set yet
  1379. * H245_ERROR_NO_CAPDESC no Capability Descriptors have been set
  1380. *
  1381. * See Also:
  1382. * H245SetLocalCap
  1383. * H245Init
  1384. *
  1385. * callbacks
  1386. *
  1387. * H245_IND_CAP
  1388. * H245_IND_CAPDESC
  1389. * H245_IND_CAP_DEL
  1390. * H245_IND_CAPDESC_DEL
  1391. *
  1392. *
  1393. *****************************************************************************/
  1394. H245DLL HRESULT
  1395. H245SendTermCaps (
  1396. H245_INST_T dwInst,
  1397. DWORD_PTR dwTransId
  1398. )
  1399. {
  1400. struct InstanceStruct *pInstance;
  1401. Tracker_T *pTracker;
  1402. HRESULT lError;
  1403. unsigned char TermCapData = TRUE;
  1404. struct TerminalCapabilitySet_capabilityTable TermCap = {0};
  1405. H245TRACE(dwInst,4,"H245SendTermCaps <-");
  1406. /* check for valid instance handle */
  1407. pInstance = InstanceLock(dwInst);
  1408. if (pInstance == NULL)
  1409. {
  1410. H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1411. return H245_ERROR_INVALID_INST;
  1412. }
  1413. /* must have mux parameters set */
  1414. if ((pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & multiplexCapability_present) == 0)
  1415. {
  1416. H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_MUX_CAPS));
  1417. InstanceUnlock(pInstance);
  1418. return H245_ERROR_NO_MUX_CAPS;
  1419. }
  1420. /* must have capability descriptors set */
  1421. if (!(pInstance->API.PDU_LocalTermCap.TERMCAPSET.bit_mask & capabilityDescriptors_present))
  1422. {
  1423. H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NO_CAPDESC));
  1424. InstanceUnlock(pInstance);
  1425. return H245_ERROR_NO_CAPDESC;
  1426. }
  1427. if (!(pTracker = alloc_link_tracker (pInstance,
  1428. API_TERMCAP_T,
  1429. dwTransId,
  1430. API_ST_WAIT_RMTACK,
  1431. API_CH_ALLOC_UNDEF,
  1432. API_CH_TYPE_UNDEF,
  1433. 0,
  1434. H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
  1435. 0)))
  1436. {
  1437. H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(H245_ERROR_NOMEM));
  1438. InstanceUnlock(pInstance);
  1439. return H245_ERROR_NOMEM;
  1440. }
  1441. pdu_req_termcap_set (&pInstance->API.PDU_LocalTermCap, 0);
  1442. TermCap.next = pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable;
  1443. pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = &TermCap;
  1444. TermCap.value.bit_mask = capability_present;
  1445. TermCap.value.capabilityTableEntryNumber = pInstance->API.LocalCapIdNum;
  1446. TermCap.value.capability.choice = Capability_nonStandard_chosen;
  1447. TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.choice = h221NonStandard_chosen;
  1448. TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = 0xB5;
  1449. TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.t35Extension = 0x42;
  1450. TermCap.value.capability.u.Capability_nonStandard.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = 0x8080;
  1451. TermCap.value.capability.u.Capability_nonStandard.data.value = &TermCapData;
  1452. TermCap.value.capability.u.Capability_nonStandard.data.length = sizeof(TermCapData);
  1453. lError = FsmOutgoing(pInstance, &pInstance->API.PDU_LocalTermCap, (DWORD_PTR)pTracker);
  1454. pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet.capabilityTable = TermCap.next;
  1455. if (lError != H245_ERROR_OK)
  1456. H245TRACE(dwInst,1,"H245SendTermCaps -> %s",map_api_error(lError));
  1457. else
  1458. H245TRACE(dwInst,4,"H245SendTermCaps -> OK");
  1459. InstanceUnlock(pInstance);
  1460. return lError;
  1461. } // H245SendTermCaps()
  1462. /*****************************************************************************
  1463. *
  1464. * TYPE: H245 API
  1465. *
  1466. *****************************************************************************
  1467. *
  1468. * PROCEDURE: H245EnumCaps
  1469. *
  1470. * DESCRIPTION
  1471. *
  1472. * HRESULT H245EnumCaps (
  1473. * DWORD dwInst,
  1474. * DWORD dwTransId,
  1475. * H245_CAPDIR_T Direction,
  1476. * H245_DATA_T DataType,
  1477. * H245_CLIENT_T ClientType,
  1478. * H245_CAP_CALLBACK_T CallBack
  1479. * )
  1480. *
  1481. *
  1482. * Callback:
  1483. * CallBack (
  1484. * DWORD dwTransId,
  1485. * H245_TOTCAP_T *pTotCap,
  1486. * )
  1487. *
  1488. * Description:
  1489. *
  1490. * This function calls the H.245 client back for every
  1491. * capability as defined in the API call that complies with the
  1492. * request. If the DataType parameter is set to 0 all of the
  1493. * caps types are returned (either local or remote based on the
  1494. * Direction parameter) no mater what is in the ClientType
  1495. * parameter. If the ClientType parameter is 0, it will return
  1496. * all of the capabilities of the given DataType.
  1497. *
  1498. * The user supplied call back is called within the context of
  1499. * the call, therefor the call will be considered synchronous.
  1500. *
  1501. * Input
  1502. * dwInst Instance handle returned by H245Init
  1503. * Direction Local/Remote Receive, Transmit, or Receive and
  1504. * Transmit
  1505. * DataType Type of data (Audio, Video, Data, etc.)
  1506. * ClientType Client type (H.262, G.711. etc. ).
  1507. * dwTransId User supplied object used to identify this
  1508. * request in the callback.
  1509. *
  1510. * CallBack Output
  1511. * dwTransId Identical to dwTransId passed in H245EnumCaps
  1512. * pTotCap Pointer one of the capabilities.
  1513. *
  1514. * Note: TotCap parameter must be copied in the callback. This
  1515. * data structure is reused for each callback.
  1516. *
  1517. * Call Type:
  1518. * Synchronous Callback - i.e. called back in the context of
  1519. * the API call
  1520. *
  1521. * Errors:
  1522. * H245_ERROR_OK
  1523. * H245_ERROR_PARAM One or more parameters were invalid
  1524. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle.
  1525. *
  1526. * See Also:
  1527. * H245SetLocalCap
  1528. * H245ReplLocalCap
  1529. *
  1530. * callback
  1531. *
  1532. * H245_IND_CAP
  1533. * H245_IND_CAPDESC
  1534. *
  1535. * RETURN:
  1536. *
  1537. *****************************************************************************/
  1538. H245DLL HRESULT
  1539. H245EnumCaps (
  1540. H245_INST_T dwInst,
  1541. DWORD_PTR dwTransId,
  1542. H245_CAPDIR_T Direction,
  1543. H245_DATA_T DataType,
  1544. H245_CLIENT_T ClientType,
  1545. H245_CAP_CALLBACK_T pfCapCallback,
  1546. H245_CAPDESC_CALLBACK_T pfCapDescCallback
  1547. )
  1548. {
  1549. register struct InstanceStruct *pInstance;
  1550. struct TerminalCapabilitySet *pTermCapSet;
  1551. CapabilityTableLink pCapLink;
  1552. int lcl_rmt;
  1553. H245_TOTCAP_T totcap;
  1554. int nResult = 0;
  1555. H245TRACE (dwInst,4,"H245EnumCaps <-");
  1556. /* check for valid instance handle */
  1557. pInstance = InstanceLock(dwInst);
  1558. if (pInstance == NULL)
  1559. {
  1560. H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1561. return H245_ERROR_INVALID_INST;
  1562. }
  1563. /* check for callback routine */
  1564. if (pfCapCallback == NULL && pfCapDescCallback == NULL)
  1565. {
  1566. H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
  1567. InstanceUnlock(pInstance);
  1568. return H245_ERROR_PARAM;
  1569. }
  1570. /* ok... check the direction.. either remote or local caps.. */
  1571. switch (Direction)
  1572. {
  1573. case H245_CAPDIR_RMTRX:
  1574. case H245_CAPDIR_RMTTX:
  1575. case H245_CAPDIR_RMTRXTX:
  1576. pTermCapSet = &pInstance->API.PDU_RemoteTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  1577. lcl_rmt = H245_REMOTE;
  1578. break;
  1579. case H245_CAPDIR_LCLRX:
  1580. case H245_CAPDIR_LCLTX:
  1581. case H245_CAPDIR_LCLRXTX:
  1582. pTermCapSet = &pInstance->API.PDU_LocalTermCap.u.MltmdSystmCntrlMssg_rqst.u.terminalCapabilitySet;
  1583. lcl_rmt = H245_LOCAL;
  1584. break;
  1585. /* must be either local or remote */
  1586. // case H245_CAPDIR_DONTCARE:
  1587. default:
  1588. H245TRACE (dwInst,1,"H245EnumCaps -> %s",map_api_error(H245_ERROR_PARAM));
  1589. InstanceUnlock(pInstance);
  1590. return H245_ERROR_PARAM;
  1591. }
  1592. if (pfCapCallback)
  1593. {
  1594. if (pTermCapSet->bit_mask & multiplexCapability_present &&
  1595. build_totcap_from_mux(&totcap, &pTermCapSet->multiplexCapability, Direction) == H245_ERROR_OK)
  1596. {
  1597. (*pfCapCallback)(dwTransId, &totcap);
  1598. }
  1599. if (ClientType == H245_CLIENT_DONTCARE)
  1600. {
  1601. if (DataType == H245_DATA_DONTCARE)
  1602. {
  1603. for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
  1604. {
  1605. /* if capability is present */
  1606. if (pCapLink->value.bit_mask & capability_present &&
  1607. build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK)
  1608. {
  1609. nResult = (*pfCapCallback)(dwTransId, &totcap);
  1610. }
  1611. } // for
  1612. } // if
  1613. else
  1614. {
  1615. for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
  1616. {
  1617. /* if capability is present */
  1618. if (pCapLink->value.bit_mask & capability_present &&
  1619. build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
  1620. totcap.DataType == DataType)
  1621. {
  1622. nResult = (*pfCapCallback)(dwTransId, &totcap);
  1623. }
  1624. } // for
  1625. } // else
  1626. } // if
  1627. else
  1628. {
  1629. if (DataType == H245_DATA_DONTCARE)
  1630. {
  1631. for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
  1632. {
  1633. /* if capability is present */
  1634. if (pCapLink->value.bit_mask & capability_present &&
  1635. build_totcap_from_captbl(&totcap, pCapLink, lcl_rmt) == H245_ERROR_OK &&
  1636. totcap.ClientType == ClientType)
  1637. {
  1638. nResult = (*pfCapCallback)(dwTransId, &totcap);
  1639. } /* if cap match */
  1640. } // for
  1641. } // if
  1642. else
  1643. {
  1644. for (pCapLink = pTermCapSet->capabilityTable; pCapLink && nResult == 0; pCapLink = pCapLink->next)
  1645. {
  1646. /* if capability is present */
  1647. if (pCapLink->value.bit_mask & capability_present &&
  1648. build_totcap_from_captbl(&totcap,pCapLink,lcl_rmt) == H245_ERROR_OK &&
  1649. totcap.ClientType == ClientType &&
  1650. totcap.DataType == DataType)
  1651. {
  1652. nResult = (*pfCapCallback)(dwTransId, &totcap);
  1653. }
  1654. } // for
  1655. } // else
  1656. } // else
  1657. } // if (pfCapCallback)
  1658. if (pfCapDescCallback)
  1659. {
  1660. // Convert CapabilityDescriptor format to H245_CAPDESC_T format
  1661. unsigned int uCapDesc;
  1662. register SmltnsCpbltsLink pSimCap;
  1663. register unsigned int uAltCap;
  1664. H245_TOTCAPDESC_T TotCapDesc;
  1665. for (uCapDesc = 0;
  1666. uCapDesc < pTermCapSet->capabilityDescriptors.count && nResult == 0;
  1667. ++uCapDesc)
  1668. {
  1669. if (pTermCapSet->capabilityDescriptors.value[uCapDesc].bit_mask & smltnsCpblts_present)
  1670. {
  1671. ASSERT(pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber <= 256);
  1672. TotCapDesc.CapDesc.Length = 0;
  1673. pSimCap = pTermCapSet->capabilityDescriptors.value[uCapDesc].smltnsCpblts;
  1674. ASSERT(pSimCap != NULL);
  1675. while (pSimCap)
  1676. {
  1677. if (TotCapDesc.CapDesc.Length >= H245_MAX_SIMCAPS)
  1678. {
  1679. H245TRACE (dwInst,1,"H245EnumCaps -> Number of simutaneous capabilities exceeds H245_MAX_SIMCAPS");
  1680. InstanceUnlock(pInstance);
  1681. return H245_ERROR_MAXTBL;
  1682. }
  1683. if (pSimCap->value.count > H245_MAX_ALTCAPS)
  1684. {
  1685. H245TRACE (dwInst,1,"H245EnumCaps -> Number of alternative capabilities exceeds H245_MAX_ALTCAPS");
  1686. InstanceUnlock(pInstance);
  1687. return H245_ERROR_MAXTBL;
  1688. }
  1689. TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].Length = (WORD) pSimCap->value.count;
  1690. for (uAltCap = 0; uAltCap < pSimCap->value.count; ++uAltCap)
  1691. {
  1692. TotCapDesc.CapDesc.SimCapArray[TotCapDesc.CapDesc.Length].AltCaps[uAltCap] = pSimCap->value.value[uAltCap];
  1693. }
  1694. TotCapDesc.CapDesc.Length++;
  1695. pSimCap = pSimCap->next;
  1696. } // while
  1697. TotCapDesc.CapDescId = pTermCapSet->capabilityDescriptors.value[uCapDesc].capabilityDescriptorNumber;
  1698. nResult = pfCapDescCallback(dwTransId, &TotCapDesc);
  1699. } // if
  1700. } // for
  1701. } // if (pfCapDescCallback)
  1702. H245TRACE (dwInst,4,"H245EnumCaps -> OK");
  1703. InstanceUnlock(pInstance);
  1704. return H245_ERROR_OK;
  1705. } // H245EnumCaps()
  1706. /*****************************************************************************
  1707. *
  1708. * TYPE: H245 API
  1709. *
  1710. * PROCEDURE: H245GetCaps
  1711. *
  1712. * DESCRIPTION
  1713. *
  1714. * RETURN:
  1715. *
  1716. *****************************************************************************/
  1717. static H245_TOTCAP_T * * ppTotCapGlobal;
  1718. static unsigned long dwTotCapLen;
  1719. static unsigned long dwTotCapMax;
  1720. static H245_TOTCAPDESC_T * * ppCapDescGlobal;
  1721. static unsigned long dwCapDescLen;
  1722. static unsigned long dwCapDescMax;
  1723. static HRESULT dwGetCapsError;
  1724. static int
  1725. GetCapsCapCallback(DWORD_PTR dwTransId, H245_TOTCAP_T *pTotCap)
  1726. {
  1727. H245_TOTCAP_T *pNewCap;
  1728. if (dwGetCapsError == H245_ERROR_OK)
  1729. {
  1730. if (dwTotCapLen >= dwTotCapMax)
  1731. {
  1732. dwGetCapsError = H245_ERROR_MAXTBL;
  1733. }
  1734. else
  1735. {
  1736. dwGetCapsError = H245CopyCap(&pNewCap, pTotCap);
  1737. if (dwGetCapsError == H245_ERROR_OK)
  1738. {
  1739. *ppTotCapGlobal++ = pNewCap;
  1740. ++dwTotCapLen;
  1741. }
  1742. }
  1743. }
  1744. return 0;
  1745. } // GetCapsCapCallback()
  1746. static int
  1747. GetCapsCapDescCallback(DWORD_PTR dwTransId, H245_TOTCAPDESC_T *pCapDesc)
  1748. {
  1749. H245_TOTCAPDESC_T *pNewCapDesc;
  1750. if (dwGetCapsError == H245_ERROR_OK)
  1751. {
  1752. if (dwCapDescLen >= dwCapDescMax)
  1753. {
  1754. dwGetCapsError = H245_ERROR_MAXTBL;
  1755. }
  1756. else
  1757. {
  1758. dwGetCapsError = H245CopyCapDescriptor(&pNewCapDesc,pCapDesc);
  1759. {
  1760. *ppCapDescGlobal++ = pNewCapDesc;
  1761. ++dwCapDescLen;
  1762. }
  1763. }
  1764. }
  1765. return 0;
  1766. } // GetCapsCapDescCallback()
  1767. H245DLL HRESULT
  1768. H245GetCaps (
  1769. H245_INST_T dwInst,
  1770. H245_CAPDIR_T Direction,
  1771. H245_DATA_T DataType,
  1772. H245_CLIENT_T ClientType,
  1773. H245_TOTCAP_T * * ppTotCap,
  1774. unsigned long * pdwTotCapLen,
  1775. H245_TOTCAPDESC_T * * ppCapDesc,
  1776. unsigned long * pdwCapDescLen
  1777. )
  1778. {
  1779. register struct InstanceStruct *pInstance;
  1780. H245_CAP_CALLBACK_T CapCallback;
  1781. H245_CAPDESC_CALLBACK_T CapDescCallback;
  1782. H245TRACE (dwInst,4,"H245GetCaps <-");
  1783. /* check for valid instance handle */
  1784. pInstance = InstanceLock(dwInst);
  1785. if (pInstance == NULL)
  1786. {
  1787. H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_INVALID_INST));
  1788. return H245_ERROR_INVALID_INST;
  1789. }
  1790. dwTotCapLen = 0;
  1791. if (ppTotCap == NULL || pdwTotCapLen == NULL || *pdwTotCapLen == 0)
  1792. {
  1793. CapCallback = NULL;
  1794. }
  1795. else
  1796. {
  1797. CapCallback = GetCapsCapCallback;
  1798. ppTotCapGlobal = ppTotCap;
  1799. dwTotCapMax = *pdwTotCapLen;
  1800. }
  1801. dwCapDescLen = 0;
  1802. if (ppCapDesc == NULL || pdwCapDescLen == NULL || *pdwCapDescLen == 0)
  1803. {
  1804. CapDescCallback = NULL;
  1805. }
  1806. else
  1807. {
  1808. CapDescCallback = GetCapsCapDescCallback;
  1809. ppCapDescGlobal = ppCapDesc;
  1810. dwCapDescMax = *pdwCapDescLen;
  1811. }
  1812. /* check parameters */
  1813. if (CapCallback == NULL && CapDescCallback == NULL)
  1814. {
  1815. H245TRACE (dwInst,1,"H245GetCaps -> %s",map_api_error(H245_ERROR_PARAM));
  1816. InstanceUnlock(pInstance);
  1817. return H245_ERROR_PARAM;
  1818. }
  1819. dwGetCapsError = H245_ERROR_OK;
  1820. H245EnumCaps(dwInst,
  1821. 0,
  1822. Direction,
  1823. DataType,
  1824. ClientType,
  1825. CapCallback,
  1826. CapDescCallback);
  1827. if (pdwTotCapLen)
  1828. *pdwTotCapLen = dwTotCapLen;
  1829. if (pdwCapDescLen)
  1830. *pdwCapDescLen = dwCapDescLen;
  1831. if (dwGetCapsError != H245_ERROR_OK)
  1832. H245TRACE (dwInst,1,"H245GetCaps -> %s", map_api_error(dwGetCapsError));
  1833. else
  1834. H245TRACE (dwInst,4,"H245GetCaps -> OK");
  1835. InstanceUnlock(pInstance);
  1836. return H245_ERROR_OK;
  1837. } // H245GetCaps()
  1838. /*****************************************************************************
  1839. *
  1840. * TYPE: H245 API
  1841. *
  1842. * PROCEDURE: H245CopyCap
  1843. *
  1844. * DESCRIPTION
  1845. *
  1846. * RETURN:
  1847. *
  1848. *****************************************************************************/
  1849. H245DLL HRESULT
  1850. H245CopyCap (H245_TOTCAP_T **ppDestTotCap,
  1851. const H245_TOTCAP_T *pTotCap)
  1852. {
  1853. POBJECTID pObjectTo;
  1854. POBJECTID pObjectFrom;
  1855. HRESULT Status;
  1856. if (ppDestTotCap == NULL)
  1857. return H245_ERROR_PARAM;
  1858. *ppDestTotCap = NULL;
  1859. if (pTotCap == NULL)
  1860. return H245_ERROR_PARAM;
  1861. switch (pTotCap->ClientType)
  1862. {
  1863. case H245_CLIENT_NONSTD:
  1864. case H245_CLIENT_VID_NONSTD:
  1865. case H245_CLIENT_AUD_NONSTD:
  1866. case H245_CLIENT_MUX_NONSTD:
  1867. if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen)
  1868. {
  1869. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1870. pTotCap->Cap.H245_NonStd.data.length +
  1871. ObjectIdLength(&pTotCap->Cap.H245_NonStd.nonStandardIdentifier) * sizeof(OBJECTID));
  1872. }
  1873. else
  1874. {
  1875. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1876. pTotCap->Cap.H245_NonStd.data.length);
  1877. }
  1878. if (*ppDestTotCap == NULL)
  1879. return H245_ERROR_NOMEM;
  1880. **ppDestTotCap = *pTotCap;
  1881. if (pTotCap->Cap.H245_NonStd.data.length != 0)
  1882. {
  1883. (*ppDestTotCap)->Cap.H245_NonStd.data.value = (unsigned char *)(*ppDestTotCap + 1);
  1884. memcpy((*ppDestTotCap)->Cap.H245_NonStd.data.value,
  1885. pTotCap->Cap.H245_NonStd.data.value,
  1886. pTotCap->Cap.H245_NonStd.data.length);
  1887. }
  1888. else
  1889. {
  1890. (*ppDestTotCap)->Cap.H245_NonStd.data.value = NULL;
  1891. }
  1892. if (pTotCap->Cap.H245_NonStd.nonStandardIdentifier.choice == object_chosen &&
  1893. pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object != NULL)
  1894. {
  1895. pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
  1896. pTotCap->Cap.H245_NonStd.data.length);
  1897. (*ppDestTotCap)->Cap.H245_NonStd.nonStandardIdentifier.u.object = pObjectTo;
  1898. pObjectFrom = pTotCap->Cap.H245_NonStd.nonStandardIdentifier.u.object;
  1899. do
  1900. {
  1901. pObjectTo->value = pObjectFrom->value;
  1902. pObjectTo->next = pObjectTo + 1;
  1903. ++pObjectTo;
  1904. } while ((pObjectFrom = pObjectFrom->next) != NULL);
  1905. --pObjectTo;
  1906. pObjectTo->next = NULL;
  1907. }
  1908. break;
  1909. case H245_CLIENT_DAT_NONSTD:
  1910. if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen)
  1911. {
  1912. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1913. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length +
  1914. ObjectIdLength(&pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
  1915. }
  1916. else
  1917. {
  1918. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1919. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
  1920. }
  1921. if (*ppDestTotCap == NULL)
  1922. return H245_ERROR_NOMEM;
  1923. **ppDestTotCap = *pTotCap;
  1924. if (pTotCap->Cap.H245_NonStd.data.length != 0)
  1925. {
  1926. (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value =
  1927. (unsigned char *)(*ppDestTotCap + 1);
  1928. memcpy((*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
  1929. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value,
  1930. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
  1931. }
  1932. else
  1933. {
  1934. (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.value = NULL;
  1935. }
  1936. if (pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
  1937. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object != NULL)
  1938. {
  1939. pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
  1940. pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.data.length);
  1941. (*ppDestTotCap)->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
  1942. pObjectFrom = pTotCap->Cap.H245Dat_NONSTD.application.u.DACy_applctn_nnStndrd.nonStandardIdentifier.u.object;
  1943. do
  1944. {
  1945. pObjectTo->value = pObjectFrom->value;
  1946. pObjectTo->next = pObjectTo + 1;
  1947. ++pObjectTo;
  1948. } while ((pObjectFrom = pObjectFrom->next) != NULL);
  1949. --pObjectTo;
  1950. pObjectTo->next = NULL;
  1951. }
  1952. break;
  1953. case H245_CLIENT_DAT_T120:
  1954. case H245_CLIENT_DAT_DSMCC:
  1955. case H245_CLIENT_DAT_USERDATA:
  1956. case H245_CLIENT_DAT_T434:
  1957. case H245_CLIENT_DAT_H224:
  1958. case H245_CLIENT_DAT_H222:
  1959. if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.choice == DtPrtclCpblty_nnStndrd_chosen)
  1960. {
  1961. if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen)
  1962. {
  1963. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1964. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length +
  1965. ObjectIdLength(&pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier) * sizeof(OBJECTID));
  1966. }
  1967. else
  1968. {
  1969. *ppDestTotCap = MemAlloc(sizeof(*pTotCap) +
  1970. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
  1971. }
  1972. if (*ppDestTotCap == NULL)
  1973. return H245_ERROR_NOMEM;
  1974. **ppDestTotCap = *pTotCap;
  1975. if (pTotCap->Cap.H245_NonStd.data.length != 0)
  1976. {
  1977. (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value =
  1978. (unsigned char *)(*ppDestTotCap + 1);
  1979. memcpy((*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
  1980. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value,
  1981. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
  1982. }
  1983. else
  1984. {
  1985. (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.value = NULL;
  1986. }
  1987. if (pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.choice == object_chosen &&
  1988. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object != NULL)
  1989. {
  1990. pObjectTo = (POBJECTID)(((unsigned char *)(*ppDestTotCap + 1)) +
  1991. pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.data.length);
  1992. (*ppDestTotCap)->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object = pObjectTo;
  1993. pObjectFrom = pTotCap->Cap.H245Dat_T120.application.u.DACy_applctn_t120.u.DtPrtclCpblty_nnStndrd.nonStandardIdentifier.u.object;
  1994. do
  1995. {
  1996. pObjectTo->value = pObjectFrom->value;
  1997. pObjectTo->next = pObjectTo + 1;
  1998. ++pObjectTo;
  1999. } while ((pObjectFrom = pObjectFrom->next) != NULL);
  2000. --pObjectTo;
  2001. pObjectTo->next = NULL;
  2002. }
  2003. }
  2004. else
  2005. {
  2006. *ppDestTotCap = MemAlloc(sizeof(*pTotCap));
  2007. if (*ppDestTotCap == NULL)
  2008. return H245_ERROR_NOMEM;
  2009. **ppDestTotCap = *pTotCap;
  2010. }
  2011. break;
  2012. case H245_CLIENT_CONFERENCE:
  2013. {
  2014. NonStandardDataLink pList;
  2015. NonStandardDataLink pFrom;
  2016. NonStandardDataLink pTo;
  2017. // Initialize Status here to prevent compiler warning "returning a possibly
  2018. // uninitialized value"
  2019. Status = H245_ERROR_NOMEM;
  2020. *ppDestTotCap = MemAlloc(sizeof(*pTotCap));
  2021. if (*ppDestTotCap == NULL)
  2022. return H245_ERROR_NOMEM;
  2023. **ppDestTotCap = *pTotCap;
  2024. pList = NULL;
  2025. (*ppDestTotCap)->Cap.H245Conference.nonStandardData = NULL;
  2026. pFrom = pTotCap->Cap.H245Conference.nonStandardData;
  2027. while (pFrom)
  2028. {
  2029. pTo = MemAlloc(sizeof(*pTo));
  2030. if (pTo == NULL)
  2031. Status = H245_ERROR_NOMEM;
  2032. if (pTo != NULL)
  2033. {
  2034. Status = CopyNonStandardParameter(&pTo->value, &pFrom->value);
  2035. if (Status != H245_ERROR_OK)
  2036. {
  2037. MemFree(pTo);
  2038. pTo = NULL;
  2039. }
  2040. }
  2041. if (pTo == NULL)
  2042. {
  2043. while (pList)
  2044. {
  2045. pTo = pList;
  2046. pList = pList->next;
  2047. FreeNonStandardParameter(&pTo->value);
  2048. MemFree(pTo);
  2049. }
  2050. MemFree(*ppDestTotCap);
  2051. *ppDestTotCap = NULL;
  2052. return Status;
  2053. }
  2054. pTo->next = pList;
  2055. pList = pTo;
  2056. pFrom = pFrom->next;
  2057. } // while
  2058. while (pList)
  2059. {
  2060. pTo = pList;
  2061. pList = pList->next;
  2062. pTo->next = (*ppDestTotCap)->Cap.H245Conference.nonStandardData;
  2063. (*ppDestTotCap)->Cap.H245Conference.nonStandardData = pTo;
  2064. } // while
  2065. break;
  2066. }
  2067. case H245_CLIENT_MUX_H222:
  2068. {
  2069. VCCapabilityLink pList = NULL;
  2070. VCCapabilityLink pFrom;
  2071. VCCapabilityLink pTo;
  2072. *ppDestTotCap = MemAlloc(sizeof(*pTotCap));
  2073. if (*ppDestTotCap == NULL)
  2074. return H245_ERROR_NOMEM;
  2075. **ppDestTotCap = *pTotCap;
  2076. (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = NULL;
  2077. pFrom = pTotCap->Cap.H245Mux_H222.vcCapability;
  2078. while (pFrom)
  2079. {
  2080. pTo = MemAlloc(sizeof(*pTo));
  2081. if (pTo == NULL)
  2082. {
  2083. while (pList)
  2084. {
  2085. pTo = pList;
  2086. pList = pList->next;
  2087. MemFree(pTo);
  2088. }
  2089. MemFree(*ppDestTotCap);
  2090. *ppDestTotCap = NULL;
  2091. return H245_ERROR_NOMEM;
  2092. }
  2093. pTo->value = pFrom->value;
  2094. pTo->next = pList;
  2095. pList = pTo;
  2096. pFrom = pFrom->next;
  2097. } // while
  2098. while (pList)
  2099. {
  2100. pTo = pList;
  2101. pList = pList->next;
  2102. pTo->next = (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability;
  2103. (*ppDestTotCap)->Cap.H245Mux_H222.vcCapability = pList;
  2104. } // while
  2105. break;
  2106. }
  2107. case H245_CLIENT_MUX_H2250:
  2108. *ppDestTotCap = MemAlloc(sizeof(*pTotCap));
  2109. if (*ppDestTotCap == NULL)
  2110. return H245_ERROR_NOMEM;
  2111. **ppDestTotCap = *pTotCap;
  2112. Status = CopyH2250Cap(&(*ppDestTotCap)->Cap.H245Mux_H2250, &pTotCap->Cap.H245Mux_H2250);
  2113. if (Status != H245_ERROR_OK)
  2114. {
  2115. MemFree(*ppDestTotCap);
  2116. *ppDestTotCap = NULL;
  2117. return Status;
  2118. }
  2119. break;
  2120. default:
  2121. *ppDestTotCap = MemAlloc(sizeof(*pTotCap));
  2122. if (*ppDestTotCap == NULL)
  2123. return H245_ERROR_NOMEM;
  2124. **ppDestTotCap = *pTotCap;
  2125. } // switch
  2126. return H245_ERROR_OK;
  2127. } // H245CopyCap()
  2128. /*****************************************************************************
  2129. *
  2130. * TYPE: H245 API
  2131. *
  2132. * PROCEDURE: H245FreeCap
  2133. *
  2134. * DESCRIPTION
  2135. *
  2136. * RETURN:
  2137. *
  2138. *****************************************************************************/
  2139. H245DLL HRESULT
  2140. H245FreeCap (H245_TOTCAP_T * pTotCap)
  2141. {
  2142. if (pTotCap == NULL)
  2143. {
  2144. return H245_ERROR_PARAM;
  2145. }
  2146. switch (pTotCap->ClientType)
  2147. {
  2148. case H245_CLIENT_CONFERENCE:
  2149. {
  2150. NonStandardDataLink pList;
  2151. NonStandardDataLink pTo;
  2152. pList = pTotCap->Cap.H245Conference.nonStandardData;
  2153. while (pList)
  2154. {
  2155. pTo = pList;
  2156. pList = pList->next;
  2157. FreeNonStandardParameter(&pTo->value);
  2158. MemFree(pTo);
  2159. }
  2160. }
  2161. break;
  2162. case H245_CLIENT_MUX_H222:
  2163. {
  2164. VCCapabilityLink pList;
  2165. VCCapabilityLink pTo;
  2166. pList = pTotCap->Cap.H245Mux_H222.vcCapability;
  2167. while (pList)
  2168. {
  2169. pTo = pList;
  2170. pList = pList->next;
  2171. MemFree(pTo);
  2172. }
  2173. }
  2174. break;
  2175. case H245_CLIENT_MUX_H2250:
  2176. FreeH2250Cap(&pTotCap->Cap.H245Mux_H2250);
  2177. break;
  2178. } // switch
  2179. MemFree(pTotCap);
  2180. return 0;
  2181. } // H245FreeCap()
  2182. /*****************************************************************************
  2183. *
  2184. * TYPE: H245 API
  2185. *
  2186. * PROCEDURE: H245CopyCapDescriptor
  2187. *
  2188. * DESCRIPTION
  2189. *
  2190. * RETURN:
  2191. *
  2192. *****************************************************************************/
  2193. H245DLL HRESULT
  2194. H245CopyCapDescriptor (H245_TOTCAPDESC_T **ppDestCapDesc,
  2195. const H245_TOTCAPDESC_T *pCapDesc)
  2196. {
  2197. if (ppDestCapDesc == NULL)
  2198. return H245_ERROR_PARAM;
  2199. *ppDestCapDesc = NULL;
  2200. if (pCapDesc == NULL)
  2201. return H245_ERROR_PARAM;
  2202. *ppDestCapDesc = MemAlloc(sizeof(**ppDestCapDesc));
  2203. if (*ppDestCapDesc == NULL)
  2204. return H245_ERROR_NOMEM;
  2205. **ppDestCapDesc = *pCapDesc;
  2206. return H245_ERROR_OK;
  2207. } // H245CopyCapDescriptor()
  2208. /*****************************************************************************
  2209. *
  2210. * TYPE: H245 API
  2211. *
  2212. * PROCEDURE: H245FreeCapDescriptor
  2213. *
  2214. * DESCRIPTION
  2215. *
  2216. * RETURN:
  2217. *
  2218. *****************************************************************************/
  2219. H245DLL HRESULT
  2220. H245FreeCapDescriptor (H245_TOTCAPDESC_T * pCapDesc)
  2221. {
  2222. if (pCapDesc == NULL)
  2223. {
  2224. return H245_ERROR_PARAM;
  2225. }
  2226. MemFree(pCapDesc);
  2227. return 0;
  2228. } // H245FreeCapDescriptor()
  2229. /*****************************************************************************
  2230. *
  2231. * TYPE: H245 API
  2232. *
  2233. * PROCEDURE: H245CopyMux
  2234. *
  2235. * DESCRIPTION
  2236. *
  2237. * RETURN:
  2238. *
  2239. *****************************************************************************/
  2240. H245DLL H245_MUX_T *
  2241. H245CopyMux (const H245_MUX_T * pMux)
  2242. {
  2243. register unsigned int uLength;
  2244. register H245_MUX_T *pNew;
  2245. H2250LCPs_nnStndrdLink pList;
  2246. H2250LCPs_nnStndrdLink pFrom;
  2247. H2250LCPs_nnStndrdLink pTo;
  2248. switch (pMux->Kind)
  2249. {
  2250. case H245_H222:
  2251. uLength = sizeof(*pMux) +
  2252. pMux->u.H222.programDescriptors.length +
  2253. pMux->u.H222.streamDescriptors.length;
  2254. pNew = MemAlloc(uLength);
  2255. if (pNew != NULL)
  2256. {
  2257. *pNew = *pMux;
  2258. if (pMux->u.H222.programDescriptors.length != 0)
  2259. {
  2260. pNew->u.H222.programDescriptors.value = (unsigned char *)(pNew + 1);
  2261. memcpy(pNew->u.H222.programDescriptors.value,
  2262. pMux->u.H222.programDescriptors.value,
  2263. pMux->u.H222.programDescriptors.length);
  2264. }
  2265. else
  2266. {
  2267. pNew->u.H222.programDescriptors.value = NULL;
  2268. }
  2269. if (pMux->u.H222.streamDescriptors.length != 0)
  2270. {
  2271. pNew->u.H222.streamDescriptors.value = ((unsigned char *)pNew) +
  2272. (uLength - pMux->u.H222.streamDescriptors.length);
  2273. memcpy(pNew->u.H222.streamDescriptors.value,
  2274. pMux->u.H222.streamDescriptors.value,
  2275. pMux->u.H222.streamDescriptors.length);
  2276. }
  2277. else
  2278. {
  2279. pNew->u.H222.streamDescriptors.value = NULL;
  2280. }
  2281. }
  2282. break;
  2283. case H245_H223:
  2284. pNew = MemAlloc(sizeof(*pMux) + pMux->u.H223.H223_NONSTD.data.length);
  2285. if (pNew != NULL)
  2286. {
  2287. *pNew = *pMux;
  2288. if (pMux->u.H223.H223_NONSTD.data.length != 0)
  2289. {
  2290. pNew->u.H223.H223_NONSTD.data.value = (unsigned char *)(pNew + 1);
  2291. memcpy(pNew->u.H223.H223_NONSTD.data.value,
  2292. pMux->u.H223.H223_NONSTD.data.value,
  2293. pMux->u.H223.H223_NONSTD.data.length);
  2294. }
  2295. else
  2296. {
  2297. pNew->u.H223.H223_NONSTD.data.value = NULL;
  2298. }
  2299. }
  2300. break;
  2301. case H245_H2250:
  2302. case H245_H2250ACK:
  2303. // Caveat: assumes nonstandard list, mediaChannel and mediaControlChannel
  2304. // in same place in both structures
  2305. if (pMux->u.H2250.mediaChannelPresent &&
  2306. (pMux->u.H2250.mediaChannel.type == H245_IPSSR_UNICAST ||
  2307. pMux->u.H2250.mediaChannel.type == H245_IPLSR_UNICAST) &&
  2308. pMux->u.H2250.mediaChannel.u.ipSourceRoute.route != NULL &&
  2309. pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount != 0)
  2310. {
  2311. if (pMux->u.H2250.mediaControlChannelPresent &&
  2312. (pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
  2313. pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
  2314. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
  2315. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
  2316. {
  2317. unsigned int uLength2;
  2318. uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
  2319. uLength2 = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
  2320. pNew = MemAlloc(sizeof(*pMux) + uLength + uLength2);
  2321. if (pNew != NULL)
  2322. {
  2323. *pNew = *pMux;
  2324. pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
  2325. pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route =
  2326. pNew->u.H2250.mediaChannel.u.ipSourceRoute.route + uLength;
  2327. memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
  2328. pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
  2329. uLength);
  2330. memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
  2331. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
  2332. uLength2);
  2333. }
  2334. }
  2335. else
  2336. {
  2337. uLength = pMux->u.H2250.mediaChannel.u.ipSourceRoute.dwCount << 2;
  2338. pNew = MemAlloc(sizeof(*pMux) + uLength);
  2339. if (pNew != NULL)
  2340. {
  2341. *pNew = *pMux;
  2342. pNew->u.H2250.mediaChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
  2343. memcpy(pNew->u.H2250.mediaChannel.u.ipSourceRoute.route,
  2344. pMux->u.H2250.mediaChannel.u.ipSourceRoute.route,
  2345. uLength);
  2346. }
  2347. }
  2348. }
  2349. else if (pMux->u.H2250.mediaControlChannelPresent &&
  2350. (pMux->u.H2250.mediaControlChannel.type == H245_IPSSR_UNICAST ||
  2351. pMux->u.H2250.mediaControlChannel.type == H245_IPLSR_UNICAST) &&
  2352. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route != NULL &&
  2353. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount != 0)
  2354. {
  2355. uLength = pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.dwCount << 2;
  2356. pNew = MemAlloc(sizeof(*pMux) + uLength);
  2357. if (pNew != NULL)
  2358. {
  2359. *pNew = *pMux;
  2360. pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route = (unsigned char *) (pNew + 1);
  2361. memcpy(pNew->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
  2362. pMux->u.H2250.mediaControlChannel.u.ipSourceRoute.route,
  2363. uLength);
  2364. }
  2365. }
  2366. else
  2367. {
  2368. pNew = MemAlloc(sizeof(*pMux));
  2369. if (pNew != NULL)
  2370. {
  2371. *pNew = *pMux;
  2372. }
  2373. }
  2374. pList = NULL;
  2375. pNew->u.H2250.nonStandardList = NULL;
  2376. pFrom = pMux->u.H2250.nonStandardList;
  2377. while (pFrom)
  2378. {
  2379. pTo = MemAlloc(sizeof(*pTo));
  2380. if (pTo != NULL)
  2381. {
  2382. if (CopyNonStandardParameter(&pTo->value, &pFrom->value) != H245_ERROR_OK)
  2383. {
  2384. MemFree(pTo);
  2385. pTo = NULL;
  2386. }
  2387. }
  2388. if (pTo == NULL)
  2389. {
  2390. while (pList)
  2391. {
  2392. pTo = pList;
  2393. pList = pList->next;
  2394. FreeNonStandardParameter(&pTo->value);
  2395. MemFree(pTo);
  2396. }
  2397. MemFree(pNew);
  2398. return NULL;
  2399. }
  2400. pTo->next = pList;
  2401. pList = pTo;
  2402. pFrom = pFrom->next;
  2403. } // while
  2404. while (pList)
  2405. {
  2406. pTo = pList;
  2407. pList = pList->next;
  2408. pTo->next = pNew->u.H2250.nonStandardList;
  2409. pNew->u.H2250.nonStandardList = pTo;
  2410. } // while
  2411. break;
  2412. // case H245_VGMUX:
  2413. default:
  2414. pNew = MemAlloc(sizeof(*pMux));
  2415. if (pNew != NULL)
  2416. {
  2417. *pNew = *pMux;
  2418. }
  2419. } // switch
  2420. return pNew;
  2421. } // H245CopyMux()
  2422. /*****************************************************************************
  2423. *
  2424. * TYPE: H245 API
  2425. *
  2426. * PROCEDURE: H245FreeMux
  2427. *
  2428. * DESCRIPTION
  2429. *
  2430. * RETURN:
  2431. *
  2432. *****************************************************************************/
  2433. H245DLL HRESULT
  2434. H245FreeMux (H245_MUX_T * pMux)
  2435. {
  2436. H2250LCPs_nnStndrdLink pLink;
  2437. if (pMux == NULL)
  2438. {
  2439. return H245_ERROR_PARAM;
  2440. }
  2441. switch (pMux->Kind)
  2442. {
  2443. case H245_H2250:
  2444. case H245_H2250ACK:
  2445. // Caveat: assumes nonstandard list is in same place in both structures
  2446. while (pMux->u.H2250.nonStandardList)
  2447. {
  2448. pLink = pMux->u.H2250.nonStandardList;
  2449. pMux->u.H2250.nonStandardList = pLink->next;
  2450. FreeNonStandardParameter(&pLink->value);
  2451. MemFree(pLink);
  2452. }
  2453. break;
  2454. } // switch
  2455. MemFree(pMux);
  2456. return 0;
  2457. } // H245FreeMux()
  2458. /*****************************************************************************
  2459. *
  2460. * TYPE: H245 API
  2461. *
  2462. *****************************************************************************
  2463. *
  2464. * PROCEDURE: H245OpenChannel
  2465. *
  2466. * DESCRIPTION
  2467. *
  2468. * HRESULT H245OpenChannel (
  2469. * H245_INST_T dwInst,
  2470. * DWORD dwTransId,
  2471. * DWORD dwTxChannel,
  2472. * H245_TOTCAP_T *pTxMode,
  2473. * H245_MUX_T *pTxMux,
  2474. * H245_TOTCAP_T *pRxMode, (* bi-dir only *)
  2475. * H245_MUX_T *pRxMux (* bi-dir only *)
  2476. * )
  2477. *
  2478. * Description:
  2479. * This function is called to open either a uni-directional,
  2480. * or a bi-directional channel. The mode to the remote peer
  2481. * will be designated by the *pTxMode.. To open a bi-directional
  2482. * channel the client selects a non-null receive mode ( *pRxMode).
  2483. * This mode indicates to the remote peer its transmit mode.
  2484. * For uni-directional channels the *pRxMode must be NULL.
  2485. *
  2486. * The dwTxChannel parameter indicates which forward logical
  2487. * channel the H.245 will open. If this is a bi-directional
  2488. * channel open, the confirm will indicate the logical channel
  2489. * specified in the open request by the remote terminal
  2490. *
  2491. * The pMux parameter will contain a pointer to H.223, H.222,
  2492. * VGMUX, or other logical channel parameters depending on the
  2493. * system configuration. (see H245_H223_LOGICAL_PARAM). This
  2494. * may be NULL for some clients.
  2495. *
  2496. * Note:
  2497. * 7 pTxMode->CapId is of no significance in this call.
  2498. * It is not used
  2499. * 7 pRxMode->CapId is of no significance in this call.
  2500. * It is not used
  2501. *
  2502. * Input
  2503. * dwInst Instance handle returned by H245Init
  2504. * dwTransId User supplied object used to identify this
  2505. * request in the asynchronous confirm to this
  2506. * call.
  2507. * dwTxChannel Logical Channel number for forward (Transmit)
  2508. * Channel
  2509. * pTxMode The capability (mode) used for transmission
  2510. * to the remote peer.
  2511. * Note: pTxMode->CapId is ignored
  2512. * pTxMux The formward logical channel parameters
  2513. * for H.223, H.222, VGMUX, etc.
  2514. * pRxMode Optional: Transmit mode specified for the
  2515. * remote terminal. This is used only for
  2516. * Bi-directional Channel opens and must be set
  2517. * to NULL if opening a Uni-directional channel.
  2518. * Note: pRxMode->CapId is ignored
  2519. * pRxMux Optional : The reverse logical channel
  2520. * parameters for H.223, H.222, VGMUX, etc. or
  2521. * NULL.
  2522. *
  2523. * Call Type:
  2524. * Asynchronous
  2525. *
  2526. * Return Values:
  2527. * See Errors
  2528. *
  2529. * Callback:
  2530. * H245_CONF_OPEN
  2531. * H245_CONF_NEEDRSP_OPEN Bi-Directional Channels only
  2532. * waiting for confirm.
  2533. * Errors:
  2534. * H245_ERROR_OK
  2535. * H245_ERROR_PARAM One or more parameters were
  2536. * invalid
  2537. * H245_ERROR_BANDWIDTH_OVERFLOW Open would exceed bandwidth
  2538. * limitations
  2539. * H245_ERROR_NOMEM
  2540. * H245_ERROR_NORESOURCE Out of resources, too many
  2541. * open channels or outside scope
  2542. * of simultaneous capabilities.
  2543. * H245_ERROR_INVALID_INST dwInst is not a valid instance
  2544. * handle
  2545. * H245_ERROR_INVALID_STATE Not in the proper state to
  2546. * issue open
  2547. * H245_ERROR_CHANNEL_INUSE Channel is currently open
  2548. *
  2549. * See Also:
  2550. * H245CloseChannel
  2551. * H245OpenChannelIndResp
  2552. * H245OpenChannelConfResp
  2553. *
  2554. * callback
  2555. *
  2556. * H245_CONF_OPEN
  2557. * H245_CONF_NEEDRSP_OPEN
  2558. * H245_IND_OPEN_CONF
  2559. *
  2560. *
  2561. * RETURN:
  2562. *
  2563. *****************************************************************************/
  2564. H245DLL HRESULT
  2565. H245OpenChannel (
  2566. H245_INST_T dwInst,
  2567. DWORD_PTR dwTransId,
  2568. H245_CHANNEL_T wTxChannel,
  2569. const H245_TOTCAP_T * pTxMode,
  2570. const H245_MUX_T * pTxMux,
  2571. H245_PORT_T dwTxPort, // optional
  2572. const H245_TOTCAP_T * pRxMode, // bi-dir only
  2573. const H245_MUX_T * pRxMux, // bi-dir only
  2574. const H245_ACCESS_T * pSeparateStack // optional
  2575. )
  2576. {
  2577. register struct InstanceStruct *pInstance;
  2578. HRESULT lError;
  2579. Tracker_T *pTracker;
  2580. MltmdSystmCntrlMssg *pPdu;
  2581. H245TRACE (dwInst,4,"H245OpenChannel <-");
  2582. /* check for valid instance handle */
  2583. pInstance = InstanceLock(dwInst);
  2584. if (pInstance == NULL)
  2585. {
  2586. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
  2587. return H245_ERROR_INVALID_INST;
  2588. }
  2589. /* system should be in connected state */
  2590. if (pInstance->API.SystemState != APIST_Connected)
  2591. {
  2592. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  2593. InstanceUnlock(pInstance);
  2594. return H245_ERROR_NOT_CONNECTED;
  2595. }
  2596. /* must have performed Master Slave Negotiation at this point */
  2597. if (pInstance->Configuration == H245_CONF_H324 &&
  2598. pInstance->API.MasterSlave != APIMS_Master &&
  2599. pInstance->API.MasterSlave != APIMS_Slave)
  2600. {
  2601. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_INVALID_STATE));
  2602. InstanceUnlock(pInstance);
  2603. return H245_ERROR_INVALID_STATE;
  2604. }
  2605. pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
  2606. /* channel is currently in use */
  2607. if (pTracker)
  2608. {
  2609. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_CHANNEL_INUSE));
  2610. InstanceUnlock(pInstance);
  2611. return H245_ERROR_CHANNEL_INUSE;
  2612. }
  2613. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  2614. {
  2615. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
  2616. InstanceUnlock(pInstance);
  2617. return H245_ERROR_NOMEM;
  2618. }
  2619. memset(pPdu, 0, sizeof(*pPdu));
  2620. /* lock in the transmit side.. */
  2621. /* wait until OpenChannelConfResp to setup RxChannel */
  2622. lError = pdu_req_open_channel(pPdu,
  2623. wTxChannel,
  2624. dwTxPort, /* forward port */
  2625. pTxMode,
  2626. pTxMux,
  2627. pRxMode,
  2628. pRxMux,
  2629. pSeparateStack);
  2630. if (lError != H245_ERROR_OK)
  2631. {
  2632. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
  2633. free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
  2634. InstanceUnlock(pInstance);
  2635. return lError;
  2636. }
  2637. /* if allocation error */
  2638. if (!(pTracker = alloc_link_tracker (pInstance,
  2639. API_OPEN_CHANNEL_T,
  2640. dwTransId,
  2641. API_ST_WAIT_RMTACK,
  2642. API_CH_ALLOC_LCL,
  2643. (pRxMode?API_CH_TYPE_BI:API_CH_TYPE_UNI),
  2644. pTxMode->DataType,
  2645. wTxChannel, H245_INVALID_CHANNEL,
  2646. 0)))
  2647. {
  2648. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(H245_ERROR_NOMEM));
  2649. free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
  2650. InstanceUnlock(pInstance);
  2651. return H245_ERROR_NOMEM;
  2652. }
  2653. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  2654. free_pdu_req_open_channel(pPdu, pTxMode, pRxMode);
  2655. if (lError != H245_ERROR_OK)
  2656. {
  2657. unlink_dealloc_tracker (pInstance, pTracker);
  2658. H245TRACE (dwInst,1,"H245OpenChannel -> %s",map_api_error(lError));
  2659. }
  2660. else
  2661. H245TRACE (dwInst,4,"H245OpenChannel -> OK");
  2662. InstanceUnlock(pInstance);
  2663. return lError;
  2664. } // H245OpenChannel()
  2665. /*****************************************************************************
  2666. *
  2667. * TYPE: H245 API
  2668. *
  2669. * PROCEDURE: H245OpenChannelAccept
  2670. *
  2671. * DESCRIPTION
  2672. *
  2673. * RETURN:
  2674. *
  2675. *****************************************************************************/
  2676. H245DLL HRESULT
  2677. H245OpenChannelAccept (
  2678. H245_INST_T dwInst,
  2679. DWORD_PTR dwTransId,
  2680. H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
  2681. const H245_MUX_T * pRxMux, // optional H2250LogicalChannelAckParameters
  2682. H245_CHANNEL_T wTxChannel, // bi-dir only
  2683. const H245_MUX_T * pTxMux, // bi-dir only optional H2250LogicalChannelParameters
  2684. H245_PORT_T dwTxPort, // bi-dir only optional
  2685. const H245_ACCESS_T * pSeparateStack // optional
  2686. )
  2687. {
  2688. register struct InstanceStruct *pInstance;
  2689. Tracker_T * pTracker;
  2690. MltmdSystmCntrlMssg * pPdu;
  2691. HRESULT lError;
  2692. H245TRACE (dwInst,4,"H245OpenChannelAccept <- wRxChannel=%d wTxChannel=%d",
  2693. wRxChannel, wTxChannel);
  2694. /* check for valid instance handle */
  2695. pInstance = InstanceLock(dwInst);
  2696. if (pInstance == NULL)
  2697. {
  2698. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
  2699. return H245_ERROR_INVALID_INST;
  2700. }
  2701. /* system should be in connected state */
  2702. if (pInstance->API.SystemState != APIST_Connected)
  2703. {
  2704. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  2705. InstanceUnlock(pInstance);
  2706. return H245_ERROR_NOT_CONNECTED;
  2707. }
  2708. /* if channel not found in tracker list */
  2709. /* note that it looks for given channel given who alloced it */
  2710. pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
  2711. /* not locking tracker.. since no indication will come in until I issue the request */
  2712. if (!pTracker)
  2713. {
  2714. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
  2715. InstanceUnlock(pInstance);
  2716. return H245_ERROR_INVALID_OP;
  2717. }
  2718. /* if not open.. invalid op */
  2719. if (pTracker->TrackerType != API_OPEN_CHANNEL_T)
  2720. {
  2721. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_OP));
  2722. InstanceUnlock(pInstance);
  2723. return H245_ERROR_INVALID_OP;
  2724. }
  2725. /* if was uni open w/ TxChannel set.. error */
  2726. /* -or - */
  2727. /* if was bi open w/ !TxChannel set.. error */
  2728. /* AND it wasn't a reject */
  2729. if (pTracker->u.Channel.ChannelType == API_CH_TYPE_BI && wTxChannel == 0)
  2730. {
  2731. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_PARAM));
  2732. InstanceUnlock(pInstance);
  2733. return H245_ERROR_PARAM;
  2734. }
  2735. /* for debug */
  2736. ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
  2737. ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
  2738. /* check state.. must be returning.. */
  2739. if (pTracker->State != API_ST_WAIT_LCLACK)
  2740. {
  2741. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_INVALID_STATE));
  2742. InstanceUnlock(pInstance);
  2743. return H245_ERROR_INVALID_STATE;
  2744. }
  2745. /* setup tracker object for new transaction */
  2746. pTracker->TransId = dwTransId;
  2747. pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
  2748. if (pPdu == NULL)
  2749. {
  2750. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(H245_ERROR_NOMEM));
  2751. InstanceUnlock(pInstance);
  2752. return H245_ERROR_NOMEM;
  2753. }
  2754. memset(pPdu, 0, sizeof(*pPdu));
  2755. switch (pTracker->u.Channel.ChannelType)
  2756. {
  2757. case API_CH_TYPE_UNI:
  2758. pTracker->State = API_ST_IDLE;
  2759. pTracker->u.Channel.TxChannel = 0;
  2760. lError = pdu_rsp_open_logical_channel_ack(pPdu,
  2761. wRxChannel,
  2762. pRxMux,
  2763. 0,
  2764. NULL,
  2765. dwTxPort,
  2766. pSeparateStack);
  2767. if (lError != H245_ERROR_OK)
  2768. {
  2769. // If parameter error, we don't want to deallocate tracker
  2770. MemFree (pPdu);
  2771. InstanceUnlock(pInstance);
  2772. return lError;
  2773. }
  2774. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  2775. break;
  2776. case API_CH_TYPE_BI:
  2777. pTracker->State = API_ST_WAIT_CONF; /* waiting for confirmation */
  2778. pTracker->u.Channel.TxChannel = wTxChannel;
  2779. lError = pdu_rsp_open_logical_channel_ack(pPdu,
  2780. wRxChannel,
  2781. pRxMux,
  2782. wTxChannel,
  2783. pTxMux,
  2784. dwTxPort,
  2785. pSeparateStack);
  2786. if (lError != H245_ERROR_OK)
  2787. {
  2788. // If parameter error, we don't want to deallocate tracker
  2789. MemFree (pPdu);
  2790. InstanceUnlock(pInstance);
  2791. return lError;
  2792. }
  2793. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  2794. break;
  2795. default:
  2796. H245TRACE (dwInst,1,"H245OpenChannelAccept: Invalid Tracker Channel Type %d",
  2797. pTracker->u.Channel.ChannelType);
  2798. lError = H245_ERROR_FATAL;
  2799. } // switch
  2800. MemFree (pPdu);
  2801. switch (lError)
  2802. {
  2803. case H245_ERROR_OK:
  2804. H245TRACE (dwInst,4,"H245OpenChannelAccept -> OK");
  2805. break;
  2806. default:
  2807. // Deallocate tracker object for all errors except parameter error
  2808. unlink_dealloc_tracker (pInstance, pTracker);
  2809. // Fall-through to next case is intentional
  2810. case H245_ERROR_PARAM:
  2811. // If parameter error, we don't want to deallocate tracker
  2812. H245TRACE (dwInst,1,"H245OpenChannelAccept -> %s",map_api_error(lError));
  2813. } // switch
  2814. InstanceUnlock(pInstance);
  2815. return lError;
  2816. } // H245OpenChannelAccept()
  2817. /*****************************************************************************
  2818. *
  2819. * TYPE: H245 API
  2820. *
  2821. * PROCEDURE: H245OpenChannelReject
  2822. *
  2823. * DESCRIPTION
  2824. *
  2825. * RETURN:
  2826. *
  2827. *****************************************************************************/
  2828. H245DLL HRESULT
  2829. H245OpenChannelReject (
  2830. H245_INST_T dwInst,
  2831. H245_CHANNEL_T wRxChannel, // RxChannel from IND_OPEN
  2832. unsigned short wCause
  2833. )
  2834. {
  2835. register struct InstanceStruct *pInstance;
  2836. Tracker_T * pTracker;
  2837. MltmdSystmCntrlMssg * pPdu;
  2838. HRESULT lError;
  2839. H245TRACE (dwInst,4,"H245OpenChannelReject <- wRxChannel=%d", wRxChannel);
  2840. /* check for valid instance handle */
  2841. pInstance = InstanceLock(dwInst);
  2842. if (pInstance == NULL)
  2843. {
  2844. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
  2845. return H245_ERROR_INVALID_INST;
  2846. }
  2847. /* system should be in connected state */
  2848. if (pInstance->API.SystemState != APIST_Connected)
  2849. {
  2850. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  2851. InstanceUnlock(pInstance);
  2852. return H245_ERROR_NOT_CONNECTED;
  2853. }
  2854. /* if channel not found in tracker list */
  2855. /* note that it looks for given channel given who alloced it */
  2856. pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
  2857. /* not locking tracker.. since no indication will come in until I issue the request */
  2858. /* if not open.. invalid op */
  2859. if (pTracker == NULL || pTracker->TrackerType != API_OPEN_CHANNEL_T)
  2860. {
  2861. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_OP));
  2862. InstanceUnlock(pInstance);
  2863. return H245_ERROR_INVALID_OP;
  2864. }
  2865. /* for debug */
  2866. ASSERT (pTracker->u.Channel.RxChannel == wRxChannel);
  2867. ASSERT (pTracker->u.Channel.ChannelAlloc == API_CH_ALLOC_RMT);
  2868. /* check state.. must be returning.. */
  2869. if (pTracker->State != API_ST_WAIT_LCLACK)
  2870. {
  2871. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_INVALID_STATE));
  2872. InstanceUnlock(pInstance);
  2873. return H245_ERROR_INVALID_STATE;
  2874. }
  2875. pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(*pPdu));
  2876. if (pPdu == NULL)
  2877. {
  2878. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(H245_ERROR_NOMEM));
  2879. InstanceUnlock(pInstance);
  2880. return H245_ERROR_NOMEM;
  2881. }
  2882. memset(pPdu, 0, sizeof(*pPdu));
  2883. pdu_rsp_open_logical_channel_rej(pPdu, wRxChannel, wCause);
  2884. switch (pTracker->u.Channel.ChannelType)
  2885. {
  2886. case API_CH_TYPE_UNI:
  2887. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  2888. break;
  2889. case API_CH_TYPE_BI:
  2890. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  2891. break;
  2892. default:
  2893. H245TRACE (dwInst,1,"H245OpenChannelReject: Invalid Tracker Channel Type %d",
  2894. pTracker->u.Channel.ChannelType);
  2895. lError = H245_ERROR_FATAL;
  2896. } // switch
  2897. MemFree (pPdu);
  2898. unlink_dealloc_tracker (pInstance, pTracker);
  2899. if (lError != H245_ERROR_OK)
  2900. H245TRACE (dwInst,1,"H245OpenChannelReject -> %s",map_api_error(lError));
  2901. else
  2902. H245TRACE (dwInst,4,"H245OpenChannelReject -> OK");
  2903. InstanceUnlock(pInstance);
  2904. return lError;
  2905. } // H245OpenChannelReject()
  2906. /*****************************************************************************
  2907. *
  2908. * TYPE: H245 API
  2909. *
  2910. *****************************************************************************
  2911. *
  2912. * PROCEDURE: H245CloseChannel
  2913. *
  2914. * DESCRIPTION
  2915. *
  2916. * HRESULT H245CloseChannel (
  2917. * H245_INST_T dwInst,
  2918. * DWORD dwTransId,
  2919. * DWORD wTxChannel,
  2920. * )
  2921. * Description:
  2922. * Called to close a channel upon which the client previously
  2923. * issued an OpenChannel request.
  2924. *
  2925. * Input
  2926. * dwInst Instance handle returned by H245Init
  2927. * dwTransId User supplied object used to identify this
  2928. * request in the asynchronous confirm to this
  2929. * call.
  2930. * wChannel Logical Channel Number to close
  2931. *
  2932. * Call Type:
  2933. * Asynchronous
  2934. *
  2935. * Return Values:
  2936. * See Errors
  2937. *
  2938. * Callbacks:
  2939. * H245_CONF_CLOSE
  2940. * Errors:
  2941. * H245_ERROR_OK
  2942. * H245_ERROR_PARAM wChannel is not a locally opened
  2943. * channel
  2944. * H245_ERROR_INVALID_INST dwInst is not a valid intance handle
  2945. * H245_ERROR_NOT_CONNECTED
  2946. * H245_ERROR_INVALID_CHANNEL
  2947. * H245_ERROR_INVALID_OP Can not perform this operation on
  2948. * this channel.(See H245CloseChannelReq)
  2949. * See Also:
  2950. * H245OpenChannel
  2951. * H245OpenChannelIndResp
  2952. * H245OpenChannelConfResp
  2953. * H245CloseChannelReq
  2954. *
  2955. * callback
  2956. * H245_CONF_CLOSE
  2957. *
  2958. *
  2959. * RETURN:
  2960. *
  2961. *****************************************************************************/
  2962. H245DLL HRESULT
  2963. H245CloseChannel (
  2964. H245_INST_T dwInst,
  2965. DWORD_PTR dwTransId,
  2966. H245_CHANNEL_T wTxChannel
  2967. )
  2968. {
  2969. register struct InstanceStruct *pInstance;
  2970. Tracker_T *pTracker;
  2971. DWORD error;
  2972. MltmdSystmCntrlMssg *pPdu;
  2973. H245TRACE (dwInst,4,"H245CloseChannel <-");
  2974. /* check for valid instance handle */
  2975. pInstance = InstanceLock(dwInst);
  2976. if (pInstance == NULL)
  2977. {
  2978. H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_INST));
  2979. return H245_ERROR_INVALID_INST;
  2980. }
  2981. /* system should be in connected state */
  2982. if (pInstance->API.SystemState != APIST_Connected)
  2983. {
  2984. H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  2985. InstanceUnlock(pInstance);
  2986. return H245_ERROR_NOT_CONNECTED;
  2987. }
  2988. /* if channel not found in tracker list */
  2989. /* note that it looks for given channel given who alloced it */
  2990. pTracker = find_tracker_by_txchannel (pInstance, wTxChannel, API_CH_ALLOC_LCL);
  2991. /* not locking tracker.. since no indication will come in until I issue the request */
  2992. if (!pTracker)
  2993. {
  2994. H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
  2995. InstanceUnlock(pInstance);
  2996. return H245_ERROR_INVALID_CHANNEL;
  2997. }
  2998. /* setup new tracker state */
  2999. pTracker->State = API_ST_WAIT_RMTACK;
  3000. pTracker->TrackerType = API_CLOSE_CHANNEL_T;
  3001. pTracker->TransId = dwTransId;
  3002. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  3003. {
  3004. H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(H245_ERROR_NOMEM));
  3005. InstanceUnlock(pInstance);
  3006. return H245_ERROR_NOMEM;
  3007. }
  3008. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3009. /* ok.. get pdu */
  3010. pdu_req_close_logical_channel(pPdu, wTxChannel, 0/* user */);
  3011. error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  3012. MemFree (pPdu);
  3013. /* error.. so deallocate tracker structure */
  3014. if (error != H245_ERROR_OK)
  3015. {
  3016. unlink_dealloc_tracker (pInstance, pTracker);
  3017. H245TRACE (dwInst,1,"H245CloseChannel -> %s",map_api_error(error));
  3018. }
  3019. else
  3020. {
  3021. H245TRACE (dwInst,4,"H245CloseChannel -> OK");
  3022. }
  3023. InstanceUnlock(pInstance);
  3024. return H245_ERROR_OK;
  3025. } // H245CloseChannel()
  3026. /*****************************************************************************
  3027. *
  3028. * TYPE: H245 API
  3029. *
  3030. *****************************************************************************
  3031. *
  3032. * PROCEDURE: H245CloseChannelReq
  3033. *
  3034. * DESCRIPTION
  3035. *
  3036. * HRESULT H245CloseChannelReq (
  3037. * H245_INST_T dwInst,
  3038. * DWORD dwTransId,
  3039. * DWORD wChannel,
  3040. * )
  3041. * Description:
  3042. * Called to request the remote peer to close a logical channel
  3043. * it previously opened
  3044. *
  3045. * Input
  3046. * dwInst Instance handle returned by H245Init
  3047. * dwTransId User supplied object used to identify this
  3048. * request in the asynchronous confirm to this
  3049. * call
  3050. * wChannel Logical Channel Number to close
  3051. *
  3052. * Note: This is only asking permission. Even if the Close
  3053. * Request is accepted the channel still has to be closed from
  3054. * the remote side. (i.e. this does not close the channel it
  3055. * only asked the remote side it issue a close)
  3056. *
  3057. * Call Type:
  3058. * Asynchronous
  3059. *
  3060. * Return Values:
  3061. * See Errors
  3062. *
  3063. * Callbacks:
  3064. * H245_CONF_CLOSE
  3065. *
  3066. * Errors:
  3067. * H245_ERROR_OK
  3068. * H245_ERROR_PARAM wChannel is not a channel
  3069. * opened by remote peer
  3070. * H245_ERROR_INVALID_INST dwInst is not a valid instance
  3071. * handle
  3072. * H245_ERROR_NOT_CONNECTED
  3073. * H245_ERROR_INVALID_CHANNEL
  3074. * H245_ERROR_INVALID_OP Can not perform this operation
  3075. * on this channel
  3076. * (see H245CloseChannel)
  3077. * See Also:
  3078. * H245OpenChannel
  3079. * H245OpenChannelIndResp
  3080. * H245OpenChannelConfResp
  3081. * H245CloseChannel
  3082. *
  3083. * callback
  3084. *
  3085. * H245_CONF_CLOSE
  3086. *
  3087. * RETURN:
  3088. *
  3089. *****************************************************************************/
  3090. H245DLL HRESULT
  3091. H245CloseChannelReq (
  3092. H245_INST_T dwInst,
  3093. DWORD_PTR dwTransId,
  3094. H245_CHANNEL_T wRxChannel
  3095. )
  3096. {
  3097. register struct InstanceStruct *pInstance;
  3098. Tracker_T *pTracker;
  3099. DWORD error;
  3100. MltmdSystmCntrlMssg *pPdu;
  3101. H245TRACE (dwInst,4,"H245CloseChannelReq <-");
  3102. /* check for valid instance handle */
  3103. pInstance = InstanceLock(dwInst);
  3104. if (pInstance == NULL)
  3105. {
  3106. H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3107. return H245_ERROR_INVALID_INST;
  3108. }
  3109. /* system should be in connected state */
  3110. if (pInstance->API.SystemState != APIST_Connected)
  3111. {
  3112. H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  3113. InstanceUnlock(pInstance);
  3114. return H245_ERROR_NOT_CONNECTED;
  3115. }
  3116. /* if channel not found in tracker list */
  3117. /* note that it looks for given channel given who alloced it */
  3118. pTracker = find_tracker_by_rxchannel (pInstance, wRxChannel, API_CH_ALLOC_RMT);
  3119. /* not locking tracker.. since no indication will come in until I issue the request */
  3120. if (!pTracker)
  3121. {
  3122. H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_INVALID_OP));
  3123. InstanceUnlock(pInstance);
  3124. return H245_ERROR_INVALID_OP;
  3125. }
  3126. /* verify state of tracker */
  3127. pTracker->State = API_ST_WAIT_RMTACK;
  3128. pTracker->TrackerType = API_CLOSE_CHANNEL_T;
  3129. pTracker->TransId = dwTransId;
  3130. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  3131. {
  3132. H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(H245_ERROR_NOMEM));
  3133. InstanceUnlock(pInstance);
  3134. return H245_ERROR_NOMEM;
  3135. }
  3136. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3137. /* ok.. get pdu */
  3138. pdu_req_request_close_channel(pPdu, wRxChannel);
  3139. error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  3140. MemFree (pPdu);
  3141. if (error != H245_ERROR_OK)
  3142. {
  3143. unlink_dealloc_tracker (pInstance, pTracker);
  3144. H245TRACE (dwInst,1,"H245CloseChannelReq -> %s",map_api_error(error));
  3145. }
  3146. else
  3147. H245TRACE (dwInst,4,"H245CloseChannelReq -> OK");
  3148. InstanceUnlock(pInstance);
  3149. return error;
  3150. } // H245CloseChannelReq()
  3151. /*****************************************************************************
  3152. *
  3153. * TYPE: H245 API
  3154. *
  3155. *****************************************************************************
  3156. *
  3157. * PROCEDURE: H245CloseChannelReqResp
  3158. *
  3159. * DESCRIPTION
  3160. *
  3161. * HRESULT H245CloseChannelReqResp (
  3162. * H245_INST_T dwInst,
  3163. * H245_ACC_REJ_T AccRej,
  3164. * DWORD wChannel
  3165. * )
  3166. *
  3167. * Description:
  3168. * This routine is called to accept or reject a
  3169. * RequestChannelClose (H245_IND_REQ_CLOSE indication) from the
  3170. * remote peer. The channel must have been locally opened. The
  3171. * parameter AccRej is H245_ACC to accept or H245_REJ to reject
  3172. * the close. The local client should follow this response with
  3173. * a H245CloseChannel call.
  3174. *
  3175. * If there was a Release CloseChannelRequest event that
  3176. * occurred during this transaction there error code returned
  3177. * will be H245_ERROR_CANCELED. This indicates to the H.245
  3178. * client that no action should be taken.
  3179. *
  3180. * Input
  3181. * dwInst Instance handle returned by H245GetInstanceId
  3182. * AccRej this parameter contains either H245_ACC or
  3183. * H245_REJ. This indicates to H.245 which
  3184. * action to take.
  3185. * wChannel Logical Channel Number to close
  3186. *
  3187. * Call Type:
  3188. * Synchronous
  3189. *
  3190. * Return Values:
  3191. * See Errors
  3192. * Errors:
  3193. * H245_ERROR_OK
  3194. * H245_ERROR_PARAM
  3195. * H245_ERROR_NOMEM
  3196. * H245_ERROR_INVALID_CHANNEL
  3197. * H245_ERROR_INVALID_OP Can not perform this operation on this
  3198. * channel (see H245CloseChannel)
  3199. * H245_ERROR_INVALID_INST dwInst is not a valid instance handle
  3200. * H245_ERROR_CANCELED if release was received during the
  3201. * processing of this request..
  3202. * See Also:
  3203. * H245CloseChannel
  3204. *
  3205. * callback
  3206. *
  3207. * H245_IND_REQ_CLOSE
  3208. * H245_IND_CLOSE
  3209. *
  3210. *
  3211. * RETURN:
  3212. *
  3213. *****************************************************************************/
  3214. H245DLL HRESULT
  3215. H245CloseChannelReqResp (
  3216. H245_INST_T dwInst,
  3217. H245_ACC_REJ_T AccRej,
  3218. H245_CHANNEL_T wChannel
  3219. )
  3220. {
  3221. register struct InstanceStruct *pInstance;
  3222. Tracker_T *pTracker;
  3223. DWORD error;
  3224. MltmdSystmCntrlMssg *pPdu;
  3225. H245TRACE (dwInst,4,"H245CloseChannelReqResp <-");
  3226. /* check for valid instance handle */
  3227. pInstance = InstanceLock(dwInst);
  3228. if (pInstance == NULL)
  3229. {
  3230. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3231. return H245_ERROR_INVALID_INST;
  3232. }
  3233. /* system should be in connected state */
  3234. if (pInstance->API.SystemState != APIST_Connected)
  3235. {
  3236. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  3237. InstanceUnlock(pInstance);
  3238. return H245_ERROR_NOT_CONNECTED;
  3239. }
  3240. /* if channel not found in tracker list */
  3241. /* note that it looks for given channel given who alloced it */
  3242. pTracker = find_tracker_by_txchannel (pInstance, wChannel, API_CH_ALLOC_LCL);
  3243. /* not locking tracker.. since no indication will come in until I issue the request */
  3244. if (!pTracker)
  3245. {
  3246. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
  3247. InstanceUnlock(pInstance);
  3248. return H245_ERROR_INVALID_OP;
  3249. }
  3250. /* if the request was canceled.. tell useer */
  3251. if (pTracker->State == API_ST_WAIT_LCLACK_CANCEL)
  3252. {
  3253. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_CANCELED));
  3254. InstanceUnlock(pInstance);
  3255. return H245_ERROR_CANCELED;
  3256. }
  3257. /* verify state of tracker */
  3258. if ((pTracker->State != API_ST_WAIT_LCLACK) ||
  3259. (pTracker->TrackerType != API_CLOSE_CHANNEL_T))
  3260. {
  3261. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
  3262. InstanceUnlock(pInstance);
  3263. return H245_ERROR_INVALID_OP;
  3264. }
  3265. /* set the state to idle.. expect this side to close the channel next */
  3266. pTracker->State = API_ST_IDLE;
  3267. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  3268. {
  3269. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(H245_ERROR_NOMEM));
  3270. InstanceUnlock(pInstance);
  3271. return H245_ERROR_NOMEM;
  3272. }
  3273. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3274. /* ok.. get pdu */
  3275. if (AccRej == H245_ACC)
  3276. {
  3277. pTracker = NULL;
  3278. pdu_rsp_request_channel_close_ack(pPdu, wChannel);
  3279. }
  3280. else
  3281. {
  3282. pdu_rsp_request_channel_close_rej(pPdu, wChannel, AccRej);
  3283. }
  3284. error = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  3285. MemFree (pPdu);
  3286. if (error != H245_ERROR_OK)
  3287. H245TRACE (dwInst,1,"H245CloseChannelReqResp -> %s",map_api_error(error));
  3288. else
  3289. H245TRACE (dwInst,4,"H245CloseChannelReqResp ->");
  3290. InstanceUnlock(pInstance);
  3291. return error;
  3292. } // H245CloseChannelReqResp()
  3293. /*****************************************************************************
  3294. *
  3295. * TYPE: H245 API
  3296. *
  3297. *****************************************************************************
  3298. *
  3299. * PROCEDURE: H245SendLocalMuxTable
  3300. *
  3301. * DESCRIPTION
  3302. *
  3303. * HRESULT H245SendLocalMuxTable (
  3304. * H245_INST_T dwInst,
  3305. * DWORD dwTransId,
  3306. * H245_MUX_TABLE_T *pMuxTbl
  3307. * )
  3308. * Description:
  3309. * This routine is called to send a mux table to the remote
  3310. * side. The remote side can either reject or accept each mux
  3311. * table entry in a message. The confirm is sent back to the
  3312. * calling H.245 client based on the acceptance or non
  3313. * acceptance of each Mux table entry with H245_CONF_MUXTBL_SND.
  3314. *
  3315. * This is a fairly dangerous call, since the mux table
  3316. * structure is a linked lise of mux table entries. Invalid
  3317. * data structures could cause an access error. Example code is
  3318. * supplied in the appendix.
  3319. * Input
  3320. * dwInst Instance handle returned by H245Init
  3321. * dwTransId User supplied object used to identify
  3322. * this request in the asynchronous
  3323. * confirm to this call.
  3324. * pMuxTbl Mux table entry structure
  3325. *
  3326. * Call Type:
  3327. * Asynchronous
  3328. *
  3329. * Return Values:
  3330. * See Errors
  3331. *
  3332. * Callbacks:
  3333. * H245_CONF_MUXTBLSND
  3334. *
  3335. * Errors:
  3336. * H245_ERROR_OK
  3337. * H245_ERROR_INVALID_MUXTBLENTRY
  3338. * H245_ERROR_PARAM
  3339. * H245_ERROR_INVALID_INST
  3340. * H245_ERROR_NOT_CONNECTED
  3341. * H245_ERROR_NOMEM
  3342. *
  3343. * See Also:
  3344. * APPENDIX Examples
  3345. *
  3346. * callback
  3347. *
  3348. * H245_CONF_MUXTBL_SND
  3349. *
  3350. *
  3351. * RETURN:
  3352. *
  3353. *****************************************************************************/
  3354. H245DLL HRESULT
  3355. H245SendLocalMuxTable (
  3356. H245_INST_T dwInst,
  3357. DWORD_PTR dwTransId,
  3358. H245_MUX_TABLE_T *pMuxTable
  3359. )
  3360. {
  3361. register struct InstanceStruct *pInstance;
  3362. HRESULT lError;
  3363. Tracker_T *pTracker;
  3364. MltmdSystmCntrlMssg *pPdu;
  3365. H245TRACE (dwInst,4,"H245SendLocalMuxTable <-");
  3366. /* check for valid instance handle */
  3367. pInstance = InstanceLock(dwInst);
  3368. if (pInstance == NULL)
  3369. {
  3370. H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3371. return H245_ERROR_INVALID_INST;
  3372. }
  3373. /* system should be in connected state */
  3374. if (pInstance->API.SystemState != APIST_Connected)
  3375. {
  3376. H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  3377. InstanceUnlock(pInstance);
  3378. return H245_ERROR_NOT_CONNECTED;
  3379. }
  3380. /* make sure parameters ar ok.. */
  3381. if (!pMuxTable)
  3382. {
  3383. H245TRACE (dwInst,1,"H245endLocalMuxTable -> %s",map_api_error(H245_ERROR_PARAM));
  3384. InstanceUnlock(pInstance);
  3385. return H245_ERROR_PARAM;
  3386. }
  3387. /* allocate tracker for event */
  3388. pTracker = alloc_link_tracker (pInstance,
  3389. API_SEND_MUX_T,
  3390. dwTransId,
  3391. API_ST_WAIT_RMTACK,
  3392. API_CH_ALLOC_UNDEF,
  3393. API_CH_TYPE_UNDEF,
  3394. 0,
  3395. H245_INVALID_CHANNEL, H245_INVALID_CHANNEL,
  3396. 0);
  3397. if (pTracker == NULL)
  3398. {
  3399. H245TRACE(dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(H245_ERROR_NOMEM));
  3400. InstanceUnlock(pInstance);
  3401. return H245_ERROR_NOMEM;
  3402. }
  3403. // Allocate PDU buffer
  3404. pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
  3405. if (pPdu == NULL)
  3406. {
  3407. H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",H245_ERROR_NOMEM);
  3408. InstanceUnlock(pInstance);
  3409. return H245_ERROR_NOMEM;
  3410. }
  3411. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3412. lError = pdu_req_send_mux_table(pInstance,
  3413. pPdu,
  3414. pMuxTable,
  3415. 0,
  3416. &pTracker->u.MuxEntryCount);
  3417. if (lError == H245_ERROR_OK)
  3418. {
  3419. lError = FsmOutgoing(pInstance, pPdu, (DWORD_PTR)pTracker);
  3420. /* free the list just built */
  3421. free_mux_desc_list(pPdu->u.MltmdSystmCntrlMssg_rqst.u.multiplexEntrySend.multiplexEntryDescriptors);
  3422. }
  3423. /* free the pdu */
  3424. MemFree (pPdu);
  3425. if (lError != H245_ERROR_OK)
  3426. {
  3427. unlink_dealloc_tracker (pInstance, pTracker);
  3428. H245TRACE (dwInst,1,"H245SendLocalMuxTable -> %s",map_api_error(lError));
  3429. }
  3430. else
  3431. H245TRACE (dwInst,4,"H245SendLocalMuxTable -> OK");
  3432. InstanceUnlock(pInstance);
  3433. return lError;
  3434. } // H245SendLocalMuxTable()
  3435. /*****************************************************************************
  3436. *
  3437. * TYPE: H245 API
  3438. *
  3439. *****************************************************************************
  3440. *
  3441. * PROCEDURE: H245MuxTableIndResp
  3442. *
  3443. * DESCRIPTION
  3444. *
  3445. * HRESULT H245MuxTableIndResp (
  3446. * H45_INST_T dwInst,
  3447. * H245_ACC_REJ_MUX_T AccRejMux,
  3448. * DWORD Count
  3449. * )
  3450. * Description:
  3451. * This procedure is called to either accept or reject mux
  3452. * table entries sent up in the H245_IND_MUX_TBL indication.
  3453. *
  3454. * Input
  3455. * dwInst Instance handle returned by H245Init
  3456. * AccRejMux Accept Reject Mux structure
  3457. * Count number of entries in the structure
  3458. *
  3459. * Call Type:
  3460. * Asynchronous
  3461. *
  3462. * Return Values:
  3463. * See Errors
  3464. * Errors:
  3465. * H245_ERROR_OK
  3466. * H245_ERROR_INVALID_MUXTBLENTRY
  3467. * H245_ERROR_PARAM
  3468. * H245_ERROR_INVALID_INST
  3469. * H245_ERROR_INVALID_OP
  3470. * H245_ERROR_NOT_CONNECTED
  3471. * H245_ERROR_NOMEM
  3472. * See Also:
  3473. * H245SendLocalMuxTable
  3474. *
  3475. * callback
  3476. *
  3477. * H245_IND_MUX_TBL
  3478. *
  3479. *
  3480. * RETURN:
  3481. *
  3482. *****************************************************************************/
  3483. H245DLL HRESULT
  3484. H245MuxTableIndResp (
  3485. H245_INST_T dwInst,
  3486. H245_ACC_REJ_MUX_T AccRejMux,
  3487. unsigned long dwCount
  3488. )
  3489. {
  3490. register struct InstanceStruct *pInstance;
  3491. DWORD ii;
  3492. Tracker_T *pTracker;
  3493. MltmdSystmCntrlMssg *pPdu;
  3494. H245TRACE (dwInst,4,"H245MuxTableIndResp <-");
  3495. /* check for valid instance handle */
  3496. pInstance = InstanceLock(dwInst);
  3497. if (pInstance == NULL)
  3498. {
  3499. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3500. return H245_ERROR_INVALID_INST;
  3501. }
  3502. /* system should be in connected state */
  3503. if (pInstance->API.SystemState != APIST_Connected)
  3504. {
  3505. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  3506. InstanceUnlock(pInstance);
  3507. return H245_ERROR_NOT_CONNECTED;
  3508. }
  3509. /* look for tracker.. */
  3510. pTracker = NULL;
  3511. pTracker = find_tracker_by_type (pInstance, API_RECV_MUX_T, pTracker);
  3512. /* if tracker not found.. issue invalid op */
  3513. if (!pTracker)
  3514. {
  3515. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_INVALID_OP));
  3516. InstanceUnlock(pInstance);
  3517. return H245_ERROR_INVALID_OP;
  3518. }
  3519. ASSERT (pTracker->State == API_ST_WAIT_LCLACK);
  3520. /* can't ack or reject more than you got */
  3521. if ((dwCount > pTracker->u.MuxEntryCount) ||
  3522. (dwCount > 15))
  3523. {
  3524. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
  3525. InstanceUnlock(pInstance);
  3526. return H245_ERROR_PARAM;
  3527. }
  3528. /* verify the mux table entry id's */
  3529. for (ii=0;ii<dwCount;ii++)
  3530. {
  3531. if ((AccRejMux[ii].MuxEntryId > 15) ||
  3532. (AccRejMux[ii].MuxEntryId <= 0))
  3533. {
  3534. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_PARAM));
  3535. InstanceUnlock(pInstance);
  3536. return H245_ERROR_PARAM;
  3537. }
  3538. }
  3539. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  3540. {
  3541. H245TRACE (dwInst,1,"H245MuxTableIndResp -> %s",map_api_error(H245_ERROR_NOMEM));
  3542. InstanceUnlock(pInstance);
  3543. return H245_ERROR_NOMEM;
  3544. }
  3545. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3546. /* if there are any rejects in the list.. send reject */
  3547. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3548. if (pdu_rsp_mux_table_rej (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
  3549. FsmOutgoing(pInstance, pPdu, 0);
  3550. /* if there are any accepts in the list.. send accept */
  3551. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3552. if (pdu_rsp_mux_table_ack (pPdu,0,AccRejMux,dwCount) == H245_ERROR_OK)
  3553. FsmOutgoing(pInstance, pPdu, 0);
  3554. /* if we've acked all the entries */
  3555. if (!(pTracker->u.MuxEntryCount -= dwCount))
  3556. unlink_dealloc_tracker (pInstance, pTracker);
  3557. MemFree (pPdu);
  3558. H245TRACE (dwInst,4,"H245MuxTableIndResp -> %s",H245_ERROR_OK);
  3559. InstanceUnlock(pInstance);
  3560. return H245_ERROR_OK;
  3561. } // H245MuxTableIndResp()
  3562. #if 0
  3563. /*****************************************************************************
  3564. *
  3565. * TYPE: H245 API
  3566. *
  3567. *****************************************************************************
  3568. *
  3569. * PROCEDURE: H245MiscCommand
  3570. *
  3571. * DESCRIPTION
  3572. *
  3573. * HRESULT H245MiscCommand (
  3574. * H245_INST_T dwInst,
  3575. * DWORD wChannel,
  3576. * H245_MISC_T *pMisc
  3577. * )
  3578. * Description:
  3579. * Send a Misc. command to the remote side (see H245_MISC_T
  3580. * data Structure)
  3581. *
  3582. * Input
  3583. * dwInst Instance handle returned by H245Init
  3584. * wChannel Logical Channel Number
  3585. * pMisc pointer to a misc. command structure
  3586. *
  3587. * Call Type:
  3588. * Synchronous
  3589. *
  3590. * Return Values:
  3591. * See Errors
  3592. *
  3593. * Errors:
  3594. * H245_ERROR_OK
  3595. * H245_ERROR_NOT_CONNECTED
  3596. * H245_ERROR_INVALID_CHANNEL
  3597. * H245_ERROR_NOMEM
  3598. * H245_ERROR_PARAM
  3599. * H245_ERROR_INVALID_INST
  3600. *
  3601. * callback
  3602. *
  3603. * H245_IND_MISC
  3604. *
  3605. *
  3606. * RETURN:
  3607. *
  3608. *****************************************************************************/
  3609. H245DLL HRESULT H245MiscCommand (
  3610. H245_INST_T dwInst,
  3611. WORD wChannel,
  3612. H245_MISC_T *pMisc
  3613. )
  3614. {
  3615. register struct InstanceStruct *pInstance;
  3616. HRESULT lError;
  3617. MltmdSystmCntrlMssg *pPdu;
  3618. H245TRACE (dwInst,4,"H245MiscCommand <-");
  3619. /* check for valid instance handle */
  3620. pInstance = InstanceLock(dwInst);
  3621. if (pInstance == NULL)
  3622. {
  3623. H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3624. return H245_ERROR_INVALID_INST;
  3625. }
  3626. /* system should be in connected state */
  3627. if (pInstance->API.SystemState != APIST_Connected)
  3628. {
  3629. H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  3630. InstanceUnlock(pInstance);
  3631. return H245_ERROR_NOT_CONNECTED;
  3632. }
  3633. /* if the channel can not be found */
  3634. if (!find_tracker_by_txchannel(pInstance, wChannel, API_CH_ALLOC_LCL) &&
  3635. !find_tracker_by_rxchannel(pInstance, wChannel, API_CH_ALLOC_RMT))
  3636. {
  3637. H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_INVALID_CHANNEL));
  3638. InstanceUnlock(pInstance);
  3639. return H245_ERROR_INVALID_CHANNEL;
  3640. }
  3641. if (!(pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg))))
  3642. {
  3643. H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(H245_ERROR_NOMEM));
  3644. InstanceUnlock(pInstance);
  3645. return H245_ERROR_NOMEM;
  3646. }
  3647. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  3648. /* budld pdu for misc command */
  3649. pdu_cmd_misc (pPdu, pMisc, wChannel);
  3650. lError = FsmOutgoing(pInstance, pPdu, 0);
  3651. MemFree (pPdu);
  3652. if (lError != H245_ERROR_OK)
  3653. H245TRACE (dwInst,1,"H245MiscCommand -> %s",map_api_error(lError));
  3654. else
  3655. H245TRACE (dwInst,4,"H245MiscCommand -> OK");
  3656. InstanceUnlock(pInstance);
  3657. return lError;
  3658. } // H245MiscCommand()
  3659. #endif
  3660. /*****************************************************************************
  3661. *
  3662. * TYPE: H245 API
  3663. *
  3664. * PROCEDURE: H245RequestMultiplexEntry
  3665. *
  3666. * DESCRIPTION
  3667. *
  3668. * RETURN:
  3669. *
  3670. *****************************************************************************/
  3671. H245DLL HRESULT
  3672. H245RequestMultiplexEntry (
  3673. H245_INST_T dwInst,
  3674. DWORD_PTR dwTransId,
  3675. const unsigned short * pwMultiplexTableEntryNumbers,
  3676. unsigned long dwCount
  3677. )
  3678. {
  3679. register struct InstanceStruct *pInstance;
  3680. register PDU_T * pPdu;
  3681. HRESULT lError;
  3682. DWORD dwIndex;
  3683. H245TRACE (dwInst,4,"H245RequestMultiplexEntry <-");
  3684. if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
  3685. {
  3686. H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
  3687. return H245_ERROR_PARAM;
  3688. }
  3689. for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
  3690. {
  3691. if (pwMultiplexTableEntryNumbers[dwIndex] < 1 ||
  3692. pwMultiplexTableEntryNumbers[dwIndex] > 15)
  3693. {
  3694. H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_PARAM));
  3695. return H245_ERROR_PARAM;
  3696. }
  3697. }
  3698. pInstance = InstanceLock(dwInst);
  3699. if (pInstance == NULL)
  3700. {
  3701. H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3702. return H245_ERROR_INVALID_INST;
  3703. }
  3704. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  3705. if (pPdu == NULL)
  3706. {
  3707. lError = H245_ERROR_NOMEM;
  3708. }
  3709. else
  3710. {
  3711. memset(pPdu, 0, sizeof(*pPdu));
  3712. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  3713. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMultiplexEntry_chosen;
  3714. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.count = (WORD)dwCount;
  3715. for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
  3716. {
  3717. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMultiplexEntry.entryNumbers.value[dwIndex] =
  3718. (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
  3719. }
  3720. lError = FsmOutgoing(pInstance, pPdu, dwTransId);
  3721. MemFree(pPdu);
  3722. }
  3723. if (lError != H245_ERROR_OK)
  3724. H245TRACE (dwInst,1,"H245RequestMultiplexEntry -> %s",map_api_error(lError));
  3725. else
  3726. H245TRACE (dwInst,4,"H245RequestMultiplexEntry -> OK");
  3727. InstanceUnlock(pInstance);
  3728. return lError;
  3729. } // H245RequestMultiplexEntry()
  3730. /*****************************************************************************
  3731. *
  3732. * TYPE: H245 API
  3733. *
  3734. * PROCEDURE: H245RequestMultiplexEntryAck
  3735. *
  3736. * DESCRIPTION
  3737. *
  3738. * RETURN:
  3739. *
  3740. *****************************************************************************/
  3741. H245DLL HRESULT
  3742. H245RequestMultiplexEntryAck (
  3743. H245_INST_T dwInst,
  3744. const unsigned short * pwMultiplexTableEntryNumbers,
  3745. unsigned long dwCount
  3746. )
  3747. {
  3748. register struct InstanceStruct *pInstance;
  3749. register PDU_T * pPdu;
  3750. HRESULT lError;
  3751. DWORD dwIndex;
  3752. H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck <-");
  3753. if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
  3754. {
  3755. H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_PARAM));
  3756. return H245_ERROR_PARAM;
  3757. }
  3758. pInstance = InstanceLock(dwInst);
  3759. if (pInstance == NULL)
  3760. {
  3761. H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3762. return H245_ERROR_INVALID_INST;
  3763. }
  3764. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  3765. if (pPdu == NULL)
  3766. {
  3767. lError = H245_ERROR_NOMEM;
  3768. }
  3769. else
  3770. {
  3771. memset(pPdu, 0, sizeof(*pPdu));
  3772. pPdu->choice = MSCMg_rspns_chosen;
  3773. pPdu->u.MSCMg_rspns.choice = requestMultiplexEntryAck_chosen;
  3774. pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.count = (WORD)dwCount;
  3775. for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
  3776. {
  3777. pPdu->u.MSCMg_rspns.u.requestMultiplexEntryAck.entryNumbers.value[dwIndex] =
  3778. (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
  3779. }
  3780. lError = FsmOutgoing(pInstance, pPdu, 0);
  3781. MemFree(pPdu);
  3782. }
  3783. if (lError != H245_ERROR_OK)
  3784. H245TRACE (dwInst,1,"H245RequestMultiplexEntryAck -> %s",map_api_error(lError));
  3785. else
  3786. H245TRACE (dwInst,4,"H245RequestMultiplexEntryAck -> OK");
  3787. InstanceUnlock(pInstance);
  3788. return lError;
  3789. } // H245RequestMultiplexEntryAck()
  3790. /*****************************************************************************
  3791. *
  3792. * TYPE: H245 API
  3793. *
  3794. * PROCEDURE: H245RequestMultiplexEntryReject
  3795. *
  3796. * DESCRIPTION
  3797. *
  3798. * RETURN:
  3799. *
  3800. *****************************************************************************/
  3801. H245DLL HRESULT
  3802. H245RequestMultiplexEntryReject (
  3803. H245_INST_T dwInst,
  3804. const unsigned short * pwMultiplexTableEntryNumbers,
  3805. unsigned long dwCount
  3806. )
  3807. {
  3808. register struct InstanceStruct *pInstance;
  3809. register PDU_T * pPdu;
  3810. HRESULT lError;
  3811. DWORD dwIndex;
  3812. H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject <-");
  3813. if (pwMultiplexTableEntryNumbers == NULL || dwCount < 1 || dwCount > 15)
  3814. {
  3815. H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_PARAM));
  3816. return H245_ERROR_PARAM;
  3817. }
  3818. pInstance = InstanceLock(dwInst);
  3819. if (pInstance == NULL)
  3820. {
  3821. H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3822. return H245_ERROR_INVALID_INST;
  3823. }
  3824. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  3825. if (pPdu == NULL)
  3826. {
  3827. lError = H245_ERROR_NOMEM;
  3828. }
  3829. else
  3830. {
  3831. memset(pPdu, 0, sizeof(*pPdu));
  3832. pPdu->choice = MSCMg_rspns_chosen;
  3833. pPdu->u.MSCMg_rspns.choice = rqstMltplxEntryRjct_chosen;
  3834. pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.count = (WORD)dwCount;
  3835. for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
  3836. {
  3837. pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].multiplexTableEntryNumber =
  3838. (MultiplexTableEntryNumber) pwMultiplexTableEntryNumbers[dwIndex];
  3839. pPdu->u.MSCMg_rspns.u.rqstMltplxEntryRjct.rejectionDescriptions.value[dwIndex].cause.choice = RMERDs_cs_unspcfdCs_chosen;
  3840. }
  3841. lError = FsmOutgoing(pInstance, pPdu, 0);
  3842. MemFree(pPdu);
  3843. }
  3844. if (lError != H245_ERROR_OK)
  3845. H245TRACE (dwInst,1,"H245RequestMultiplexEntryReject -> %s",map_api_error(lError));
  3846. else
  3847. H245TRACE (dwInst,4,"H245RequestMultiplexEntryReject -> OK");
  3848. InstanceUnlock(pInstance);
  3849. return lError;
  3850. } // H245RequestMultiplexEntryReject()
  3851. /*****************************************************************************
  3852. *
  3853. * TYPE: H245 API
  3854. *
  3855. * PROCEDURE: H245RequestMode
  3856. *
  3857. * DESCRIPTION
  3858. *
  3859. * RETURN:
  3860. *
  3861. *****************************************************************************/
  3862. H245DLL HRESULT
  3863. H245RequestMode (
  3864. H245_INST_T dwInst,
  3865. DWORD_PTR dwTransId,
  3866. // const ModeElement * pModeElements,
  3867. //[email protected]
  3868. ModeDescription ModeDescriptions[],
  3869. //[email protected]
  3870. unsigned long dwCount
  3871. )
  3872. {
  3873. register struct InstanceStruct *pInstance;
  3874. register PDU_T * pPdu;
  3875. HRESULT lError;
  3876. RequestedModesLink pLink;
  3877. RequestedModesLink pLink_First;
  3878. DWORD dwIndex;
  3879. // [email protected]
  3880. ULONG ulPDUsize;
  3881. // [email protected]
  3882. H245TRACE (dwInst,4,"H245RequestMode <-");
  3883. //[email protected]
  3884. // if (pModeElements == NULL || dwCount == 0 || dwCount > 256)
  3885. if (ModeDescriptions == NULL || dwCount == 0 || dwCount > 256)
  3886. //[email protected]
  3887. {
  3888. H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_PARAM));
  3889. return H245_ERROR_PARAM;
  3890. }
  3891. pInstance = InstanceLock(dwInst);
  3892. if (pInstance == NULL)
  3893. {
  3894. H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3895. return H245_ERROR_INVALID_INST;
  3896. }
  3897. //[email protected]
  3898. // pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + sizeof(*pLink));
  3899. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
  3900. //[email protected]
  3901. if (pPdu == NULL)
  3902. {
  3903. lError = H245_ERROR_NOMEM;
  3904. }
  3905. else
  3906. {
  3907. USHORT usModeDescIndex =0;
  3908. memset(pPdu, 0, sizeof(*pPdu));
  3909. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  3910. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = requestMode_chosen;
  3911. //[email protected]
  3912. // pLink = (RequestedModesLink)(pPdu + 1);
  3913. pLink = (RequestedModesLink)(pPdu + usModeDescIndex+1);
  3914. //[email protected]
  3915. //[email protected]
  3916. // pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink;
  3917. //[email protected]
  3918. //[email protected]
  3919. pLink_First = pLink;
  3920. //[email protected]
  3921. // --> linked list of mode descriptions ... up to 1..256
  3922. //[email protected]
  3923. while(usModeDescIndex<=(dwCount-1))
  3924. {
  3925. //[email protected]
  3926. //[email protected]
  3927. // pLink->next = NULL;
  3928. //[email protected]
  3929. // --> number of actual mode-elements associated with this mode description
  3930. //[email protected]
  3931. // pLink->value.count = (WORD)dwCount;
  3932. pLink->value.count = (WORD)ModeDescriptions[usModeDescIndex].count;
  3933. //[email protected]
  3934. // for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
  3935. for (dwIndex = 0; dwIndex < ModeDescriptions[usModeDescIndex].count; ++dwIndex)
  3936. {
  3937. //[email protected]
  3938. // pLink->value.value[dwIndex] = pModeElements[dwIndex];
  3939. pLink->value.value[dwIndex] = ModeDescriptions[usModeDescIndex].value[dwIndex];
  3940. //[email protected]
  3941. }
  3942. //[email protected]
  3943. usModeDescIndex++;
  3944. if(usModeDescIndex<=(dwCount-1))
  3945. {
  3946. pLink->next = (RequestedModesLink)(pPdu + usModeDescIndex+1);
  3947. pLink = pLink->next;
  3948. pLink->next = NULL;
  3949. }
  3950. //[email protected]
  3951. //[email protected]
  3952. }
  3953. //[email protected]
  3954. //[email protected]
  3955. pPdu->u.MltmdSystmCntrlMssg_rqst.u.requestMode.requestedModes = pLink_First;
  3956. //[email protected]
  3957. //--
  3958. ulPDUsize = (sizeof(*pPdu) + (sizeof(*pLink)*(dwCount)));
  3959. //--
  3960. lError = FsmOutgoing(pInstance, pPdu, dwTransId);
  3961. MemFree(pPdu);
  3962. }
  3963. if (lError != H245_ERROR_OK)
  3964. H245TRACE (dwInst,1,"H245RequestMode -> %s",map_api_error(lError));
  3965. else
  3966. H245TRACE (dwInst,4,"H245RequestMode -> OK");
  3967. InstanceUnlock(pInstance);
  3968. return lError;
  3969. } // H245RequestMode()
  3970. /*****************************************************************************
  3971. *
  3972. * TYPE: H245 API
  3973. *
  3974. * PROCEDURE: H245RequestModeAck
  3975. *
  3976. * DESCRIPTION
  3977. *
  3978. * RETURN:
  3979. *
  3980. *****************************************************************************/
  3981. H245DLL HRESULT
  3982. H245RequestModeAck (
  3983. H245_INST_T dwInst,
  3984. unsigned short wResponse
  3985. )
  3986. {
  3987. register struct InstanceStruct *pInstance;
  3988. register PDU_T * pPdu;
  3989. HRESULT lError;
  3990. H245TRACE (dwInst,4,"H245RequestModeAck <-");
  3991. pInstance = InstanceLock(dwInst);
  3992. if (pInstance == NULL)
  3993. {
  3994. H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(H245_ERROR_INVALID_INST));
  3995. return H245_ERROR_INVALID_INST;
  3996. }
  3997. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  3998. if (pPdu == NULL)
  3999. {
  4000. lError = H245_ERROR_NOMEM;
  4001. }
  4002. else
  4003. {
  4004. memset(pPdu, 0, sizeof(*pPdu));
  4005. pPdu->choice = MSCMg_rspns_chosen;
  4006. pPdu->u.MSCMg_rspns.choice = requestModeAck_chosen;
  4007. pPdu->u.MSCMg_rspns.u.requestModeAck.response.choice = wResponse;
  4008. lError = FsmOutgoing(pInstance, pPdu, 0);
  4009. MemFree(pPdu);
  4010. }
  4011. if (lError != H245_ERROR_OK)
  4012. H245TRACE (dwInst,1,"H245RequestModeAck -> %s",map_api_error(lError));
  4013. else
  4014. H245TRACE (dwInst,4,"H245RequestModeAck -> OK");
  4015. InstanceUnlock(pInstance);
  4016. return lError;
  4017. } // H245RequestModeAck()
  4018. /*****************************************************************************
  4019. *
  4020. * TYPE: H245 API
  4021. *
  4022. * PROCEDURE: H245RequestModeReject
  4023. *
  4024. * DESCRIPTION
  4025. *
  4026. * RETURN:
  4027. *
  4028. *****************************************************************************/
  4029. H245DLL HRESULT
  4030. H245RequestModeReject (
  4031. H245_INST_T dwInst,
  4032. unsigned short wCause
  4033. )
  4034. {
  4035. register struct InstanceStruct *pInstance;
  4036. register PDU_T * pPdu;
  4037. HRESULT lError;
  4038. H245TRACE (dwInst,4,"H245RequestModeReject <-");
  4039. pInstance = InstanceLock(dwInst);
  4040. if (pInstance == NULL)
  4041. {
  4042. H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4043. return H245_ERROR_INVALID_INST;
  4044. }
  4045. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4046. if (pPdu == NULL)
  4047. {
  4048. lError = H245_ERROR_NOMEM;
  4049. }
  4050. else
  4051. {
  4052. memset(pPdu, 0, sizeof(*pPdu));
  4053. pPdu->choice = MSCMg_rspns_chosen;
  4054. pPdu->u.MSCMg_rspns.choice = requestModeReject_chosen;
  4055. pPdu->u.MSCMg_rspns.u.requestModeReject.cause.choice = wCause;
  4056. lError = FsmOutgoing(pInstance, pPdu, 0);
  4057. MemFree(pPdu);
  4058. }
  4059. if (lError != H245_ERROR_OK)
  4060. H245TRACE (dwInst,1,"H245RequestModeReject -> %s",map_api_error(lError));
  4061. else
  4062. H245TRACE (dwInst,4,"H245RequestModeReject -> OK");
  4063. InstanceUnlock(pInstance);
  4064. return lError;
  4065. } // H245RequestModeReject()
  4066. /*****************************************************************************
  4067. *
  4068. * TYPE: H245 API
  4069. *
  4070. * PROCEDURE: H245RoundTripDelayRequest
  4071. *
  4072. * DESCRIPTION
  4073. *
  4074. * RETURN:
  4075. *
  4076. *****************************************************************************/
  4077. H245DLL HRESULT
  4078. H245RoundTripDelayRequest (
  4079. H245_INST_T dwInst,
  4080. DWORD_PTR dwTransId
  4081. )
  4082. {
  4083. register struct InstanceStruct *pInstance;
  4084. register PDU_T * pPdu;
  4085. HRESULT lError;
  4086. H245TRACE (dwInst,4,"H245RoundTripDelayRequest <-");
  4087. pInstance = InstanceLock(dwInst);
  4088. if (pInstance == NULL)
  4089. {
  4090. H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4091. return H245_ERROR_INVALID_INST;
  4092. }
  4093. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4094. if (pPdu == NULL)
  4095. {
  4096. lError = H245_ERROR_NOMEM;
  4097. }
  4098. else
  4099. {
  4100. memset(pPdu, 0, sizeof(*pPdu));
  4101. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4102. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = roundTripDelayRequest_chosen;
  4103. lError = FsmOutgoing(pInstance, pPdu, dwTransId);
  4104. MemFree(pPdu);
  4105. }
  4106. if (lError != H245_ERROR_OK)
  4107. H245TRACE (dwInst,1,"H245RoundTripDelayRequest -> %s",map_api_error(lError));
  4108. else
  4109. H245TRACE (dwInst,4,"H245RoundTripDelayRequest -> OK");
  4110. InstanceUnlock(pInstance);
  4111. return lError;
  4112. } // H245RoundTripDelayRequest()
  4113. /*****************************************************************************
  4114. *
  4115. * TYPE: H245 API
  4116. *
  4117. * PROCEDURE: H245MaintenanceLoop
  4118. *
  4119. * DESCRIPTION
  4120. *
  4121. * RETURN:
  4122. *
  4123. *****************************************************************************/
  4124. H245DLL HRESULT
  4125. H245MaintenanceLoop (
  4126. H245_INST_T dwInst,
  4127. DWORD_PTR dwTransId,
  4128. H245_LOOP_TYPE_T dwLoopType,
  4129. H245_CHANNEL_T wChannel
  4130. )
  4131. {
  4132. register struct InstanceStruct *pInstance;
  4133. register PDU_T * pPdu;
  4134. HRESULT lError;
  4135. H245TRACE (dwInst,4,"H245MaintenanceLoop <-");
  4136. if (dwLoopType < systemLoop_chosen ||
  4137. dwLoopType > logicalChannelLoop_chosen ||
  4138. (dwLoopType != systemLoop_chosen && wChannel == 0))
  4139. {
  4140. H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_PARAM));
  4141. return H245_ERROR_PARAM;
  4142. }
  4143. pInstance = InstanceLock(dwInst);
  4144. if (pInstance == NULL)
  4145. {
  4146. H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4147. return H245_ERROR_INVALID_INST;
  4148. }
  4149. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4150. if (pPdu == NULL)
  4151. {
  4152. lError = H245_ERROR_NOMEM;
  4153. }
  4154. else
  4155. {
  4156. memset(pPdu, 0, sizeof(*pPdu));
  4157. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4158. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = maintenanceLoopRequest_chosen;
  4159. pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.choice = (WORD)dwLoopType;
  4160. pPdu->u.MltmdSystmCntrlMssg_rqst.u.maintenanceLoopRequest.type.u.mediaLoop = wChannel;
  4161. lError = FsmOutgoing(pInstance, pPdu, dwTransId);
  4162. MemFree(pPdu);
  4163. }
  4164. if (lError != H245_ERROR_OK)
  4165. H245TRACE (dwInst,1,"H245MaintenanceLoop -> %s",map_api_error(lError));
  4166. else
  4167. H245TRACE (dwInst,4,"H245MaintenanceLoop -> OK");
  4168. InstanceUnlock(pInstance);
  4169. return lError;
  4170. } // H245MaintenanceLoop()
  4171. /*****************************************************************************
  4172. *
  4173. * TYPE: H245 API
  4174. *
  4175. * PROCEDURE: H245MaintenanceLoopRelease
  4176. *
  4177. * DESCRIPTION
  4178. *
  4179. * RETURN:
  4180. *
  4181. *****************************************************************************/
  4182. H245DLL HRESULT
  4183. H245MaintenanceLoopRelease (H245_INST_T dwInst)
  4184. {
  4185. register struct InstanceStruct *pInstance;
  4186. register PDU_T * pPdu;
  4187. HRESULT lError;
  4188. H245TRACE (dwInst,4,"H245MaintenanceLoopRelease <-");
  4189. pInstance = InstanceLock(dwInst);
  4190. if (pInstance == NULL)
  4191. {
  4192. H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4193. return H245_ERROR_INVALID_INST;
  4194. }
  4195. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4196. if (pPdu == NULL)
  4197. {
  4198. lError = H245_ERROR_NOMEM;
  4199. }
  4200. else
  4201. {
  4202. memset(pPdu, 0, sizeof(*pPdu));
  4203. pPdu->choice = MSCMg_cmmnd_chosen;
  4204. pPdu->u.MSCMg_cmmnd.choice = mntnncLpOffCmmnd_chosen;
  4205. lError = FsmOutgoing(pInstance, pPdu, 0);
  4206. MemFree(pPdu);
  4207. }
  4208. if (lError != H245_ERROR_OK)
  4209. H245TRACE (dwInst,1,"H245MaintenanceLoopRelease -> %s",map_api_error(lError));
  4210. else
  4211. H245TRACE (dwInst,4,"H245MaintenanceLoopRelease -> OK");
  4212. InstanceUnlock(pInstance);
  4213. return lError;
  4214. } // H245MaintenanceLoopRelease()
  4215. /*****************************************************************************
  4216. *
  4217. * TYPE: H245 API
  4218. *
  4219. * PROCEDURE: H245MaintenanceLoopAccept
  4220. *
  4221. * DESCRIPTION
  4222. *
  4223. * RETURN:
  4224. *
  4225. *****************************************************************************/
  4226. H245DLL HRESULT
  4227. H245MaintenanceLoopAccept (
  4228. H245_INST_T dwInst,
  4229. H245_CHANNEL_T wChannel
  4230. )
  4231. {
  4232. register struct InstanceStruct *pInstance;
  4233. register PDU_T * pPdu;
  4234. HRESULT lError;
  4235. H245TRACE (dwInst,4,"H245MaintenanceLoopAccept <-");
  4236. pInstance = InstanceLock(dwInst);
  4237. if (pInstance == NULL)
  4238. {
  4239. H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4240. return H245_ERROR_INVALID_INST;
  4241. }
  4242. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4243. if (pPdu == NULL)
  4244. {
  4245. lError = H245_ERROR_NOMEM;
  4246. }
  4247. else
  4248. {
  4249. memset(pPdu, 0, sizeof(*pPdu));
  4250. pPdu->choice = MSCMg_rspns_chosen;
  4251. pPdu->u.MSCMg_rspns.choice = maintenanceLoopAck_chosen;
  4252. pPdu->u.MSCMg_rspns.u.maintenanceLoopAck.type.u.mediaLoop = wChannel;
  4253. lError = FsmOutgoing(pInstance, pPdu, 0);
  4254. MemFree(pPdu);
  4255. }
  4256. if (lError != H245_ERROR_OK)
  4257. H245TRACE (dwInst,1,"H245MaintenanceLoopAccept -> %s",map_api_error(lError));
  4258. else
  4259. H245TRACE (dwInst,4,"H245MaintenanceLoopAccept -> OK");
  4260. InstanceUnlock(pInstance);
  4261. return lError;
  4262. } // H245MaintenanceLoopAccept()
  4263. /*****************************************************************************
  4264. *
  4265. * TYPE: H245 API
  4266. *
  4267. * PROCEDURE: H245MaintenanceLoopReject
  4268. *
  4269. * DESCRIPTION
  4270. *
  4271. * RETURN:
  4272. *
  4273. *****************************************************************************/
  4274. H245DLL HRESULT
  4275. H245MaintenanceLoopReject (
  4276. H245_INST_T dwInst,
  4277. H245_CHANNEL_T wChannel,
  4278. unsigned short wCause
  4279. )
  4280. {
  4281. register struct InstanceStruct *pInstance;
  4282. register PDU_T * pPdu;
  4283. HRESULT lError;
  4284. H245TRACE (dwInst,4,"H245MaintenanceLoopReject <-");
  4285. pInstance = InstanceLock(dwInst);
  4286. if (pInstance == NULL)
  4287. {
  4288. H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4289. return H245_ERROR_INVALID_INST;
  4290. }
  4291. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4292. if (pPdu == NULL)
  4293. {
  4294. lError = H245_ERROR_NOMEM;
  4295. }
  4296. else
  4297. {
  4298. memset(pPdu, 0, sizeof(*pPdu));
  4299. pPdu->choice = MSCMg_rspns_chosen;
  4300. pPdu->u.MSCMg_rspns.choice = maintenanceLoopReject_chosen;
  4301. pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.type.u.mediaLoop = wChannel;
  4302. pPdu->u.MSCMg_rspns.u.maintenanceLoopReject.cause.choice = wCause;
  4303. lError = FsmOutgoing(pInstance, pPdu, 0);
  4304. MemFree(pPdu);
  4305. }
  4306. if (lError != H245_ERROR_OK)
  4307. H245TRACE (dwInst,1,"H245MaintenanceLoopReject -> %s",map_api_error(lError));
  4308. else
  4309. H245TRACE (dwInst,4,"H245MaintenanceLoopReject -> OK");
  4310. InstanceUnlock(pInstance);
  4311. return lError;
  4312. } // H245MaintenanceLoopReject()
  4313. /*****************************************************************************
  4314. *
  4315. * TYPE: H245 API
  4316. *
  4317. * PROCEDURE: H245NonStandardObject
  4318. *
  4319. * DESCRIPTION
  4320. *
  4321. * RETURN:
  4322. *
  4323. *****************************************************************************/
  4324. H245DLL HRESULT
  4325. H245NonStandardObject (
  4326. H245_INST_T dwInst,
  4327. H245_MESSAGE_TYPE_T MessageType,
  4328. const unsigned char * pData,
  4329. unsigned long dwDataLength,
  4330. const unsigned short * pwObjectId,
  4331. unsigned long dwObjectIdLength
  4332. )
  4333. {
  4334. register struct InstanceStruct *pInstance;
  4335. register PDU_T * pPdu;
  4336. HRESULT lError;
  4337. POBJECTID pObject;
  4338. H245TRACE (dwInst,4,"H245NonStandardObject <-");
  4339. if (pData == NULL || dwDataLength == 0 || pwObjectId == NULL || dwObjectIdLength == 0)
  4340. {
  4341. H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
  4342. return H245_ERROR_PARAM;
  4343. }
  4344. pInstance = InstanceLock(dwInst);
  4345. if (pInstance == NULL)
  4346. {
  4347. H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4348. return H245_ERROR_INVALID_INST;
  4349. }
  4350. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + dwObjectIdLength * sizeof(*pObject));
  4351. if (pPdu == NULL)
  4352. {
  4353. lError = H245_ERROR_NOMEM;
  4354. }
  4355. else
  4356. {
  4357. memset(pPdu, 0, sizeof(*pPdu));
  4358. switch (MessageType)
  4359. {
  4360. case H245_MESSAGE_REQUEST:
  4361. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4362. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
  4363. break;
  4364. case H245_MESSAGE_RESPONSE:
  4365. pPdu->choice = MSCMg_rspns_chosen;
  4366. pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
  4367. break;
  4368. case H245_MESSAGE_COMMAND:
  4369. pPdu->choice = MSCMg_cmmnd_chosen;
  4370. pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
  4371. break;
  4372. case H245_MESSAGE_INDICATION:
  4373. pPdu->choice = indication_chosen;
  4374. pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
  4375. break;
  4376. default:
  4377. H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(H245_ERROR_PARAM));
  4378. InstanceUnlock(pInstance);
  4379. return H245_ERROR_PARAM;
  4380. } // switch
  4381. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
  4382. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
  4383. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = object_chosen;
  4384. // Copy the object identifier
  4385. pObject = (POBJECTID) (pPdu + 1);
  4386. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.object = pObject;
  4387. do
  4388. {
  4389. pObject->next = pObject + 1;
  4390. pObject->value = *pwObjectId++;
  4391. ++pObject;
  4392. } while (--dwObjectIdLength);
  4393. // Null terminate the linked list
  4394. --pObject;
  4395. pObject->next = NULL;
  4396. lError = FsmOutgoing(pInstance, pPdu, 0);
  4397. MemFree(pPdu);
  4398. }
  4399. if (lError != H245_ERROR_OK)
  4400. H245TRACE (dwInst,1,"H245NonStandardObject -> %s",map_api_error(lError));
  4401. else
  4402. H245TRACE (dwInst,4,"H245NonStandardObject -> OK");
  4403. InstanceUnlock(pInstance);
  4404. return lError;
  4405. } // H245NonStandardObject()
  4406. /*****************************************************************************
  4407. *
  4408. * TYPE: H245 API
  4409. *
  4410. * PROCEDURE: H245NonStandardH221
  4411. *
  4412. * DESCRIPTION
  4413. *
  4414. * RETURN:
  4415. *
  4416. *****************************************************************************/
  4417. H245DLL HRESULT
  4418. H245NonStandardH221 (
  4419. H245_INST_T dwInst,
  4420. H245_MESSAGE_TYPE_T MessageType,
  4421. const unsigned char * pData,
  4422. unsigned long dwDataLength,
  4423. unsigned char byCountryCode,
  4424. unsigned char byExtension,
  4425. unsigned short wManufacturerCode
  4426. )
  4427. {
  4428. register struct InstanceStruct *pInstance;
  4429. register PDU_T * pPdu;
  4430. HRESULT lError;
  4431. H245TRACE (dwInst,4,"H245NonStandard221 <-");
  4432. pInstance = InstanceLock(dwInst);
  4433. if (pInstance == NULL)
  4434. {
  4435. H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4436. return H245_ERROR_INVALID_INST;
  4437. }
  4438. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4439. if (pPdu == NULL)
  4440. {
  4441. lError = H245_ERROR_NOMEM;
  4442. }
  4443. else
  4444. {
  4445. memset(pPdu, 0, sizeof(*pPdu));
  4446. switch (MessageType)
  4447. {
  4448. case H245_MESSAGE_REQUEST:
  4449. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4450. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = RqstMssg_nonStandard_chosen;
  4451. break;
  4452. case H245_MESSAGE_RESPONSE:
  4453. pPdu->choice = MSCMg_rspns_chosen;
  4454. pPdu->u.MSCMg_rspns.choice = RspnsMssg_nonStandard_chosen;
  4455. break;
  4456. case H245_MESSAGE_COMMAND:
  4457. pPdu->choice = MSCMg_cmmnd_chosen;
  4458. pPdu->u.MSCMg_cmmnd.choice = CmmndMssg_nonStandard_chosen;
  4459. break;
  4460. case H245_MESSAGE_INDICATION:
  4461. pPdu->choice = indication_chosen;
  4462. pPdu->u.indication.choice = IndctnMssg_nonStandard_chosen;
  4463. break;
  4464. default:
  4465. H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(H245_ERROR_PARAM));
  4466. InstanceUnlock(pInstance);
  4467. return H245_ERROR_PARAM;
  4468. } // switch
  4469. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.length = (WORD)dwDataLength;
  4470. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.data.value = (unsigned char *)pData;
  4471. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.choice = h221NonStandard_chosen;
  4472. // Fill in the H.221 identifier
  4473. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode = byCountryCode;
  4474. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension = byExtension;
  4475. pPdu->u.indication.u.IndctnMssg_nonStandard.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode = wManufacturerCode;
  4476. lError = FsmOutgoing(pInstance, pPdu, 0);
  4477. MemFree(pPdu);
  4478. }
  4479. if (lError != H245_ERROR_OK)
  4480. H245TRACE (dwInst,1,"H245NonStandardH221 -> %s",map_api_error(lError));
  4481. else
  4482. H245TRACE (dwInst,4,"H245NonStandardH221 -> OK");
  4483. InstanceUnlock(pInstance);
  4484. return lError;
  4485. } // H245NonStandardH221
  4486. /*****************************************************************************
  4487. *
  4488. * TYPE: H245 API
  4489. *
  4490. * PROCEDURE: H245CommunicationModeRequest
  4491. *
  4492. * DESCRIPTION
  4493. *
  4494. * RETURN:
  4495. *
  4496. *****************************************************************************/
  4497. H245DLL HRESULT
  4498. H245CommunicationModeRequest(H245_INST_T dwInst)
  4499. {
  4500. register struct InstanceStruct *pInstance;
  4501. register PDU_T * pPdu;
  4502. HRESULT lError;
  4503. H245TRACE (dwInst,4,"H245CommunicationModeRequest <-");
  4504. pInstance = InstanceLock(dwInst);
  4505. if (pInstance == NULL)
  4506. {
  4507. H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4508. return H245_ERROR_INVALID_INST;
  4509. }
  4510. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4511. if (pPdu == NULL)
  4512. {
  4513. lError = H245_ERROR_NOMEM;
  4514. }
  4515. else
  4516. {
  4517. memset(pPdu, 0, sizeof(*pPdu));
  4518. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4519. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = communicationModeRequest_chosen;
  4520. lError = FsmOutgoing(pInstance, pPdu, 0);
  4521. MemFree(pPdu);
  4522. }
  4523. if (lError != H245_ERROR_OK)
  4524. H245TRACE (dwInst,1,"H245CommunicationModeRequest -> %s",map_api_error(lError));
  4525. else
  4526. H245TRACE (dwInst,4,"H245CommunicationModeRequest -> OK");
  4527. InstanceUnlock(pInstance);
  4528. return lError;
  4529. } // H245CommunicationModeRequest
  4530. /*****************************************************************************
  4531. *
  4532. * TYPE: H245 API
  4533. *
  4534. * PROCEDURE: H245CommunicationModeResponse
  4535. *
  4536. * DESCRIPTION
  4537. *
  4538. * RETURN:
  4539. *
  4540. *****************************************************************************/
  4541. H245DLL HRESULT
  4542. H245CommunicationModeResponse(
  4543. H245_INST_T dwInst,
  4544. const H245_COMM_MODE_ENTRY_T *pTable,
  4545. unsigned char byTableCount
  4546. )
  4547. {
  4548. register struct InstanceStruct *pInstance;
  4549. register PDU_T * pPdu;
  4550. HRESULT lError = H245_ERROR_OK;
  4551. CommunicationModeTableLink pLink;
  4552. unsigned int uIndex;
  4553. H245TRACE (dwInst,4,"H245CommunicationModeResponse <-");
  4554. pInstance = InstanceLock(dwInst);
  4555. if (pInstance == NULL)
  4556. {
  4557. H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4558. return H245_ERROR_INVALID_INST;
  4559. }
  4560. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
  4561. if (pPdu == NULL)
  4562. {
  4563. lError = H245_ERROR_NOMEM;
  4564. }
  4565. else
  4566. {
  4567. memset(pPdu, 0, sizeof(*pPdu));
  4568. pPdu->choice = MSCMg_rspns_chosen;
  4569. pPdu->u.MSCMg_rspns.choice = cmmnctnMdRspns_chosen;
  4570. pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.choice = communicationModeTable_chosen;
  4571. pLink = (CommunicationModeTableLink)(pPdu + 1);
  4572. pPdu->u.MSCMg_rspns.u.cmmnctnMdRspns.u.communicationModeTable = pLink;
  4573. for (uIndex = 0; uIndex < byTableCount; ++uIndex)
  4574. {
  4575. pLink[uIndex].next = &pLink[uIndex + 1];
  4576. lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
  4577. if (lError != H245_ERROR_OK)
  4578. break;
  4579. }
  4580. pLink[byTableCount - 1].next = NULL;
  4581. if (lError == H245_ERROR_OK)
  4582. {
  4583. lError = FsmOutgoing(pInstance, pPdu, 0);
  4584. }
  4585. MemFree(pPdu);
  4586. }
  4587. if (lError != H245_ERROR_OK)
  4588. H245TRACE (dwInst,1,"H245CommunicationModeResponse -> %s",map_api_error(lError));
  4589. else
  4590. H245TRACE (dwInst,4,"H245CommunicationModeResponse -> OK");
  4591. InstanceUnlock(pInstance);
  4592. return lError;
  4593. } // H245CommunicationModeResponse()
  4594. /*****************************************************************************
  4595. *
  4596. * TYPE: H245 API
  4597. *
  4598. * PROCEDURE: H245CommunicationModeCommand
  4599. *
  4600. * DESCRIPTION
  4601. *
  4602. * RETURN:
  4603. *
  4604. *****************************************************************************/
  4605. H245DLL HRESULT
  4606. H245CommunicationModeCommand(
  4607. H245_INST_T dwInst,
  4608. const H245_COMM_MODE_ENTRY_T *pTable,
  4609. unsigned char byTableCount
  4610. )
  4611. {
  4612. register struct InstanceStruct *pInstance;
  4613. register PDU_T * pPdu;
  4614. HRESULT lError = H245_ERROR_OK;
  4615. CommunicationModeCommandLink pLink;
  4616. unsigned int uIndex;
  4617. H245TRACE (dwInst,4,"H245CommunicationModeCommand <-");
  4618. pInstance = InstanceLock(dwInst);
  4619. if (pInstance == NULL)
  4620. {
  4621. H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4622. return H245_ERROR_INVALID_INST;
  4623. }
  4624. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu) + byTableCount * sizeof(*pLink));
  4625. if (pPdu == NULL)
  4626. {
  4627. lError = H245_ERROR_NOMEM;
  4628. }
  4629. else
  4630. {
  4631. memset(pPdu, 0, sizeof(*pPdu));
  4632. pPdu->choice = MSCMg_cmmnd_chosen;
  4633. pPdu->u.MSCMg_cmmnd.choice = communicationModeCommand_chosen;
  4634. pLink = (CommunicationModeCommandLink)(pPdu + 1);
  4635. pPdu->u.MSCMg_cmmnd.u.communicationModeCommand.communicationModeTable = pLink;
  4636. for (uIndex = 0; uIndex < byTableCount; ++uIndex)
  4637. {
  4638. pLink[uIndex].next = &pLink[uIndex + 1];
  4639. lError = SetupCommModeEntry(&pLink[uIndex].value, &pTable[uIndex]);
  4640. if (lError != H245_ERROR_OK)
  4641. break;
  4642. }
  4643. pLink[byTableCount - 1].next = NULL;
  4644. if (lError == H245_ERROR_OK)
  4645. {
  4646. lError = FsmOutgoing(pInstance, pPdu, 0);
  4647. }
  4648. MemFree(pPdu);
  4649. }
  4650. if (lError != H245_ERROR_OK)
  4651. H245TRACE (dwInst,1,"H245CommunicationModeCommand -> %s",map_api_error(lError));
  4652. else
  4653. H245TRACE (dwInst,4,"H245CommunicationModeCommand -> OK");
  4654. InstanceUnlock(pInstance);
  4655. return lError;
  4656. } // H245CommunicationModeCommand()
  4657. /*****************************************************************************
  4658. *
  4659. * TYPE: H245 API
  4660. *
  4661. * PROCEDURE: H245ConferenceRequest
  4662. *
  4663. * DESCRIPTION
  4664. *
  4665. * RETURN:
  4666. *
  4667. *****************************************************************************/
  4668. H245DLL HRESULT
  4669. H245ConferenceRequest (
  4670. H245_INST_T dwInst,
  4671. H245_CONFER_REQ_ENUM_T RequestType,
  4672. unsigned char byMcuNumber,
  4673. unsigned char byTerminalNumber
  4674. )
  4675. {
  4676. register struct InstanceStruct *pInstance;
  4677. register PDU_T * pPdu;
  4678. HRESULT lError;
  4679. H245TRACE (dwInst,4,"H245ConferenceRequest <-");
  4680. pInstance = InstanceLock(dwInst);
  4681. if (pInstance == NULL)
  4682. {
  4683. H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4684. return H245_ERROR_INVALID_INST;
  4685. }
  4686. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4687. if (pPdu == NULL)
  4688. {
  4689. lError = H245_ERROR_NOMEM;
  4690. }
  4691. else
  4692. {
  4693. memset(pPdu, 0, sizeof(*pPdu));
  4694. pPdu->choice = MltmdSystmCntrlMssg_rqst_chosen;
  4695. pPdu->u.MltmdSystmCntrlMssg_rqst.choice = conferenceRequest_chosen;
  4696. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.choice = (WORD)RequestType;
  4697. switch (RequestType)
  4698. {
  4699. case dropTerminal_chosen:
  4700. case requestTerminalID_chosen:
  4701. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.mcuNumber = byMcuNumber;
  4702. pPdu->u.MltmdSystmCntrlMssg_rqst.u.conferenceRequest.u.dropTerminal.terminalNumber = byTerminalNumber;
  4703. // Fall-through to next case is intentional
  4704. case terminalListRequest_chosen:
  4705. case makeMeChair_chosen:
  4706. case cancelMakeMeChair_chosen:
  4707. case enterH243Password_chosen:
  4708. case enterH243TerminalID_chosen:
  4709. case enterH243ConferenceID_chosen:
  4710. lError = FsmOutgoing(pInstance, pPdu, 0);
  4711. break;
  4712. default:
  4713. lError = H245_ERROR_PARAM;
  4714. } // switch
  4715. MemFree(pPdu);
  4716. }
  4717. if (lError != H245_ERROR_OK)
  4718. H245TRACE (dwInst,1,"H245ConferenceRequest -> %s",map_api_error(lError));
  4719. else
  4720. H245TRACE (dwInst,4,"H245ConferenceRequest -> OK");
  4721. InstanceUnlock(pInstance);
  4722. return lError;
  4723. } // H245ConferenceRequest()
  4724. /*****************************************************************************
  4725. *
  4726. * TYPE: H245 API
  4727. *
  4728. * PROCEDURE: H245ConferenceResponse
  4729. *
  4730. * DESCRIPTION
  4731. *
  4732. * RETURN:
  4733. *
  4734. *****************************************************************************/
  4735. H245DLL HRESULT
  4736. H245ConferenceResponse (
  4737. H245_INST_T dwInst,
  4738. H245_CONFER_RSP_ENUM_T ResponseType,
  4739. unsigned char byMcuNumber,
  4740. unsigned char byTerminalNumber,
  4741. const unsigned char *pOctetString,
  4742. unsigned char byOctetStringLength,
  4743. const TerminalLabel *pTerminalList,
  4744. unsigned short wTerminalListCount
  4745. )
  4746. {
  4747. register struct InstanceStruct *pInstance;
  4748. register PDU_T * pPdu;
  4749. HRESULT lError;
  4750. unsigned uIndex;
  4751. H245TRACE (dwInst,4,"H245ConferenceResponse <-");
  4752. pInstance = InstanceLock(dwInst);
  4753. if (pInstance == NULL)
  4754. {
  4755. H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4756. return H245_ERROR_INVALID_INST;
  4757. }
  4758. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4759. if (pPdu == NULL)
  4760. {
  4761. lError = H245_ERROR_NOMEM;
  4762. }
  4763. else
  4764. {
  4765. memset(pPdu, 0, sizeof(*pPdu));
  4766. pPdu->choice = MSCMg_rspns_chosen;
  4767. pPdu->u.MSCMg_rspns.choice = conferenceResponse_chosen;
  4768. pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = (WORD)ResponseType;
  4769. switch (ResponseType)
  4770. {
  4771. case mCTerminalIDResponse_chosen:
  4772. case terminalIDResponse_chosen:
  4773. case conferenceIDResponse_chosen:
  4774. case passwordResponse_chosen:
  4775. if (pOctetString == NULL ||
  4776. byOctetStringLength == 0 ||
  4777. byOctetStringLength > 128)
  4778. {
  4779. H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
  4780. return H245_ERROR_PARAM;
  4781. }
  4782. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.mcuNumber = byMcuNumber;
  4783. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalLabel.terminalNumber = byTerminalNumber;
  4784. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.length = byOctetStringLength;
  4785. memcpy(pPdu->u.MSCMg_rspns.u.conferenceResponse.u.mCTerminalIDResponse.terminalID.value,
  4786. pOctetString,
  4787. byOctetStringLength);
  4788. // Fall-through to next case is intentional
  4789. case videoCommandReject_chosen:
  4790. case terminalDropReject_chosen:
  4791. lError = FsmOutgoing(pInstance, pPdu, 0);
  4792. break;
  4793. case terminalListResponse_chosen:
  4794. if (pTerminalList == NULL ||
  4795. wTerminalListCount == 0 ||
  4796. wTerminalListCount > 256)
  4797. {
  4798. H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(H245_ERROR_PARAM));
  4799. return H245_ERROR_PARAM;
  4800. }
  4801. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.count = wTerminalListCount;
  4802. for (uIndex = 0; uIndex < wTerminalListCount; ++uIndex)
  4803. {
  4804. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.terminalListResponse.value[uIndex] =
  4805. pTerminalList[uIndex];
  4806. }
  4807. lError = FsmOutgoing(pInstance, pPdu, 0);
  4808. break;
  4809. case H245_RSP_DENIED_CHAIR_TOKEN:
  4810. pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
  4811. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = deniedChairToken_chosen;
  4812. lError = FsmOutgoing(pInstance, pPdu, 0);
  4813. break;
  4814. case H245_RSP_GRANTED_CHAIR_TOKEN:
  4815. pPdu->u.MSCMg_rspns.u.conferenceResponse.choice = makeMeChairResponse_chosen;
  4816. pPdu->u.MSCMg_rspns.u.conferenceResponse.u.makeMeChairResponse.choice = grantedChairToken_chosen;
  4817. lError = FsmOutgoing(pInstance, pPdu, 0);
  4818. break;
  4819. default:
  4820. lError = H245_ERROR_PARAM;
  4821. } // switch
  4822. MemFree(pPdu);
  4823. }
  4824. if (lError != H245_ERROR_OK)
  4825. H245TRACE (dwInst,1,"H245ConferenceResponse -> %s",map_api_error(lError));
  4826. else
  4827. H245TRACE (dwInst,4,"H245ConferenceResponse -> OK");
  4828. InstanceUnlock(pInstance);
  4829. return lError;
  4830. } // H245ConferenceResponse()
  4831. /*****************************************************************************
  4832. *
  4833. * TYPE: H245 API
  4834. *
  4835. * PROCEDURE: H245ConferenceCommand
  4836. *
  4837. * DESCRIPTION
  4838. *
  4839. * RETURN:
  4840. *
  4841. *****************************************************************************/
  4842. H245DLL HRESULT
  4843. H245ConferenceCommand (
  4844. H245_INST_T dwInst,
  4845. H245_CONFER_CMD_ENUM_T CommandType,
  4846. H245_CHANNEL_T Channel,
  4847. unsigned char byMcuNumber,
  4848. unsigned char byTerminalNumber
  4849. )
  4850. {
  4851. register struct InstanceStruct *pInstance;
  4852. register PDU_T * pPdu;
  4853. HRESULT lError;
  4854. H245TRACE (dwInst,4,"H245ConferenceCommand <-");
  4855. pInstance = InstanceLock(dwInst);
  4856. if (pInstance == NULL)
  4857. {
  4858. H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4859. return H245_ERROR_INVALID_INST;
  4860. }
  4861. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4862. if (pPdu == NULL)
  4863. {
  4864. lError = H245_ERROR_NOMEM;
  4865. }
  4866. else
  4867. {
  4868. memset(pPdu, 0, sizeof(*pPdu));
  4869. pPdu->choice = MSCMg_cmmnd_chosen;
  4870. pPdu->u.MSCMg_cmmnd.choice = conferenceCommand_chosen;
  4871. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.choice = (WORD)CommandType;
  4872. switch (CommandType)
  4873. {
  4874. case brdcstMyLgclChnnl_chosen:
  4875. case cnclBrdcstMyLgclChnnl_chosen:
  4876. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.brdcstMyLgclChnnl = Channel;
  4877. lError = FsmOutgoing(pInstance, pPdu, 0);
  4878. break;
  4879. case ConferenceCommand_makeTerminalBroadcaster_chosen:
  4880. case ConferenceCommand_sendThisSource_chosen:
  4881. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.mcuNumber = byMcuNumber;
  4882. pPdu->u.MSCMg_cmmnd.u.conferenceCommand.u.makeTerminalBroadcaster.terminalNumber = byTerminalNumber;
  4883. // Fall-through to next case is intentional
  4884. case cnclMkTrmnlBrdcstr_chosen:
  4885. case cancelSendThisSource_chosen:
  4886. case dropConference_chosen:
  4887. lError = FsmOutgoing(pInstance, pPdu, 0);
  4888. break;
  4889. default:
  4890. lError = H245_ERROR_PARAM;
  4891. } // switch
  4892. MemFree(pPdu);
  4893. }
  4894. if (lError != H245_ERROR_OK)
  4895. H245TRACE (dwInst,1,"H245ConferenceCommand -> %s",map_api_error(lError));
  4896. else
  4897. H245TRACE (dwInst,4,"H245ConferenceCommand -> OK");
  4898. InstanceUnlock(pInstance);
  4899. return lError;
  4900. } // H245ConferenceCommand()
  4901. /*****************************************************************************
  4902. *
  4903. * TYPE: H245 API
  4904. *
  4905. * PROCEDURE: H245ConferenceIndication
  4906. *
  4907. * DESCRIPTION
  4908. *
  4909. * RETURN:
  4910. *
  4911. *****************************************************************************/
  4912. H245DLL HRESULT
  4913. H245ConferenceIndication(
  4914. H245_INST_T dwInst,
  4915. H245_CONFER_IND_ENUM_T IndicationType,
  4916. unsigned char bySbeNumber,
  4917. unsigned char byMcuNumber,
  4918. unsigned char byTerminalNumber
  4919. )
  4920. {
  4921. register struct InstanceStruct *pInstance;
  4922. register PDU_T * pPdu;
  4923. HRESULT lError;
  4924. H245TRACE (dwInst,4,"H245ConferenceIndication <-");
  4925. pInstance = InstanceLock(dwInst);
  4926. if (pInstance == NULL)
  4927. {
  4928. H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
  4929. return H245_ERROR_INVALID_INST;
  4930. }
  4931. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  4932. if (pPdu == NULL)
  4933. {
  4934. lError = H245_ERROR_NOMEM;
  4935. }
  4936. else
  4937. {
  4938. memset(pPdu, 0, sizeof(*pPdu));
  4939. pPdu->choice = indication_chosen;
  4940. pPdu->u.indication.choice = conferenceIndication_chosen;
  4941. pPdu->u.indication.u.conferenceIndication.choice = (WORD)IndicationType;
  4942. switch (IndicationType)
  4943. {
  4944. case sbeNumber_chosen:
  4945. pPdu->u.indication.u.conferenceIndication.u.sbeNumber = bySbeNumber;
  4946. lError = FsmOutgoing(pInstance, pPdu, 0);
  4947. break;
  4948. case terminalNumberAssign_chosen:
  4949. case terminalJoinedConference_chosen:
  4950. case terminalLeftConference_chosen:
  4951. case terminalYouAreSeeing_chosen:
  4952. pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.mcuNumber = byMcuNumber;
  4953. pPdu->u.indication.u.conferenceIndication.u.terminalNumberAssign.terminalNumber = byTerminalNumber;
  4954. // Fall-through to next case is intentional
  4955. case seenByAtLeastOneOther_chosen:
  4956. case cnclSnByAtLstOnOthr_chosen:
  4957. case seenByAll_chosen:
  4958. case cancelSeenByAll_chosen:
  4959. case requestForFloor_chosen:
  4960. lError = FsmOutgoing(pInstance, pPdu, 0);
  4961. break;
  4962. default:
  4963. lError = H245_ERROR_PARAM;
  4964. } // switch
  4965. MemFree(pPdu);
  4966. }
  4967. if (lError != H245_ERROR_OK)
  4968. H245TRACE (dwInst,1,"H245ConferenceIndication -> %s",map_api_error(lError));
  4969. else
  4970. H245TRACE (dwInst,4,"H245ConferenceIndication -> OK");
  4971. InstanceUnlock(pInstance);
  4972. return lError;
  4973. } // H245ConferenceIndication()
  4974. /*****************************************************************************
  4975. *
  4976. * TYPE: H245 API
  4977. *
  4978. *****************************************************************************
  4979. *
  4980. * PROCEDURE: H245UserInput
  4981. *
  4982. * DESCRIPTION
  4983. *
  4984. * HRESULT H245UserInput (
  4985. * H245_INST_T dwInst,
  4986. * char *pGenString,
  4987. * H245_NONSTANDARD_PARAMETER_T *pNonStd
  4988. * )
  4989. * Description:
  4990. *
  4991. * Send a User Input indiation to the remote side. One of the
  4992. * two parameters must be set (pGenString, pNonStd). The client
  4993. * can either send a string or a NonStandard parameter set to the
  4994. * remote client. Only one of the two parameters can contain a
  4995. * value. The other is required to be NULL.
  4996. *
  4997. * Input
  4998. * dwInst Instance handle returned by H245Init
  4999. * pGenString choice: String to be sent to remote
  5000. * side in accordance with T.51 specification.
  5001. * pNonStd choice: NonStandard Parameter
  5002. *
  5003. * Call Type:
  5004. * Synchronous
  5005. *
  5006. * Return Values:
  5007. * See Errors
  5008. *
  5009. * Errors:
  5010. * H245_ERROR_OK
  5011. * H245_ERROR_NOT_CONNECTED
  5012. * H245_ERROR_NOMEM
  5013. * H245_ERROR_PARAM
  5014. *
  5015. * callback
  5016. * H245_IND_USERINPUT
  5017. *
  5018. *
  5019. * RETURN:
  5020. *
  5021. *****************************************************************************/
  5022. H245DLL HRESULT
  5023. H245UserInput (
  5024. H245_INST_T dwInst,
  5025. const WCHAR * pGenString,
  5026. const H245_NONSTANDARD_PARAMETER_T * pNonStd
  5027. )
  5028. {
  5029. register struct InstanceStruct *pInstance;
  5030. HRESULT lError;
  5031. MltmdSystmCntrlMssg *pPdu;
  5032. #if 1
  5033. int nLength;
  5034. char * pszGeneral = NULL;
  5035. #endif
  5036. H245TRACE (dwInst,4,"H245UserInput <-");
  5037. /* check for valid instance handle */
  5038. pInstance = InstanceLock(dwInst);
  5039. if (pInstance == NULL)
  5040. {
  5041. H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5042. return H245_ERROR_INVALID_INST;
  5043. }
  5044. /* system should be in connected state */
  5045. if (pInstance->API.SystemState != APIST_Connected)
  5046. {
  5047. H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOT_CONNECTED));
  5048. InstanceUnlock(pInstance);
  5049. return H245_ERROR_NOT_CONNECTED;
  5050. }
  5051. pPdu = (MltmdSystmCntrlMssg *)MemAlloc(sizeof(MltmdSystmCntrlMssg));
  5052. if (pPdu == NULL)
  5053. {
  5054. H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
  5055. InstanceUnlock(pInstance);
  5056. return H245_ERROR_NOMEM;
  5057. }
  5058. memset(pPdu, 0, sizeof(MltmdSystmCntrlMssg));
  5059. /* build PDU */
  5060. #if 1
  5061. if (pGenString)
  5062. {
  5063. nLength = WideCharToMultiByte(CP_ACP, // code page
  5064. 0, // dwFlags
  5065. pGenString, // Unicode string
  5066. -1, // Unicode string length (bytes)
  5067. NULL, // ASCII string
  5068. 0, // max ASCII string length
  5069. NULL, // default character
  5070. NULL); // default character used
  5071. pszGeneral = MemAlloc(nLength);
  5072. if (pszGeneral == NULL)
  5073. {
  5074. H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(H245_ERROR_NOMEM));
  5075. InstanceUnlock(pInstance);
  5076. return H245_ERROR_NOMEM;
  5077. }
  5078. nLength = WideCharToMultiByte(CP_ACP, // code page
  5079. 0, // dwFlags
  5080. pGenString, // Unicode string
  5081. -1, // Unicode string length (bytes)
  5082. pszGeneral, // ASCII string
  5083. nLength, // max ASCII string length
  5084. NULL, // default character
  5085. NULL); // default character used
  5086. lError = pdu_ind_usrinpt (pPdu, NULL, pszGeneral);
  5087. }
  5088. else
  5089. {
  5090. lError = pdu_ind_usrinpt (pPdu, pNonStd, NULL);
  5091. }
  5092. #else
  5093. lError = pdu_ind_usrinpt (pPdu, pNonStd, pGenString);
  5094. #endif
  5095. if (lError == H245_ERROR_OK)
  5096. lError = FsmOutgoing(pInstance, pPdu, 0);
  5097. #if 1
  5098. if (pszGeneral)
  5099. MemFree(pszGeneral);
  5100. #endif
  5101. MemFree (pPdu);
  5102. if (lError != H245_ERROR_OK)
  5103. H245TRACE (dwInst,1,"H245UserInput -> %s",map_api_error(lError));
  5104. else
  5105. H245TRACE (dwInst,4,"H245UserInput -> OK");
  5106. InstanceUnlock(pInstance);
  5107. return lError;
  5108. } // H245UserInput()
  5109. /*****************************************************************************
  5110. *
  5111. * TYPE: H245 API
  5112. *
  5113. * PROCEDURE: H245FlowControl
  5114. *
  5115. * DESCRIPTION
  5116. *
  5117. * RETURN:
  5118. *
  5119. *****************************************************************************/
  5120. H245DLL HRESULT
  5121. H245FlowControl (
  5122. H245_INST_T dwInst,
  5123. H245_SCOPE_T Scope,
  5124. H245_CHANNEL_T Channel, // only used if Scope is H245_SCOPE_CHANNEL_NUMBER
  5125. unsigned short wResourceID, // only used if Scope is H245_SCOPE_RESOURCE_ID
  5126. unsigned long dwRestriction // H245_NO_RESTRICTION if no restriction
  5127. )
  5128. {
  5129. register struct InstanceStruct *pInstance;
  5130. register PDU_T * pPdu;
  5131. HRESULT lError;
  5132. H245TRACE (dwInst,4,"H245FlowControl <-");
  5133. pInstance = InstanceLock(dwInst);
  5134. if (pInstance == NULL)
  5135. {
  5136. H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5137. return H245_ERROR_INVALID_INST;
  5138. }
  5139. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  5140. if (pPdu == NULL)
  5141. {
  5142. lError = H245_ERROR_NOMEM;
  5143. }
  5144. else
  5145. {
  5146. memset(pPdu, 0, sizeof(*pPdu));
  5147. pPdu->choice = MSCMg_cmmnd_chosen;
  5148. pPdu->u.MSCMg_cmmnd.choice = flowControlCommand_chosen;
  5149. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.choice = (WORD)Scope;
  5150. if (dwRestriction == H245_NO_RESTRICTION)
  5151. {
  5152. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = noRestriction_chosen;
  5153. }
  5154. else
  5155. {
  5156. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.choice = maximumBitRate_chosen;
  5157. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.restriction.u.maximumBitRate = dwRestriction;
  5158. }
  5159. switch (Scope)
  5160. {
  5161. case FCCd_scp_lgclChnnlNmbr_chosen:
  5162. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FCCd_scp_lgclChnnlNmbr = Channel;
  5163. lError = FsmOutgoing(pInstance, pPdu, 0);
  5164. break;
  5165. case FlwCntrlCmmnd_scp_rsrcID_chosen:
  5166. pPdu->u.MSCMg_cmmnd.u.flowControlCommand.scope.u.FlwCntrlCmmnd_scp_rsrcID = wResourceID;
  5167. // Fall-through to next case
  5168. case FCCd_scp_whlMltplx_chosen:
  5169. lError = FsmOutgoing(pInstance, pPdu, 0);
  5170. break;
  5171. default:
  5172. lError = H245_ERROR_PARAM;
  5173. } // switch
  5174. MemFree(pPdu);
  5175. }
  5176. if (lError != H245_ERROR_OK)
  5177. H245TRACE (dwInst,1,"H245FlowControl -> %s",map_api_error(lError));
  5178. else
  5179. H245TRACE (dwInst,4,"H245FlowControl -> OK");
  5180. InstanceUnlock(pInstance);
  5181. return lError;
  5182. } // H245FlowControl()
  5183. /*****************************************************************************
  5184. *
  5185. * TYPE: H245 API
  5186. *
  5187. * PROCEDURE: H245H223SkewIndication
  5188. *
  5189. * DESCRIPTION
  5190. *
  5191. * RETURN:
  5192. *
  5193. *****************************************************************************/
  5194. H245DLL HRESULT
  5195. H245H223SkewIndication (
  5196. H245_INST_T dwInst,
  5197. H245_CHANNEL_T wLogicalChannelNumber1,
  5198. H245_CHANNEL_T wLogicalChannelNumber2,
  5199. unsigned short wSkew
  5200. )
  5201. {
  5202. register struct InstanceStruct *pInstance;
  5203. register PDU_T * pPdu;
  5204. HRESULT lError;
  5205. H245TRACE (dwInst,4,"H245H223SkewIndication <-");
  5206. pInstance = InstanceLock(dwInst);
  5207. if (pInstance == NULL)
  5208. {
  5209. H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5210. return H245_ERROR_INVALID_INST;
  5211. }
  5212. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  5213. if (pPdu == NULL)
  5214. {
  5215. lError = H245_ERROR_NOMEM;
  5216. }
  5217. else
  5218. {
  5219. memset(pPdu, 0, sizeof(*pPdu));
  5220. pPdu->choice = indication_chosen;
  5221. pPdu->u.indication.choice = h223SkewIndication_chosen;
  5222. pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber1 = wLogicalChannelNumber1;
  5223. pPdu->u.indication.u.h223SkewIndication.logicalChannelNumber2 = wLogicalChannelNumber2;
  5224. pPdu->u.indication.u.h223SkewIndication.skew = wSkew;
  5225. lError = FsmOutgoing(pInstance, pPdu, 0);
  5226. MemFree(pPdu);
  5227. }
  5228. if (lError != H245_ERROR_OK)
  5229. H245TRACE (dwInst,1,"H245H223SkewIndication -> %s",map_api_error(lError));
  5230. else
  5231. H245TRACE (dwInst,4,"H245H223SkewIndication -> OK");
  5232. InstanceUnlock(pInstance);
  5233. return lError;
  5234. } // H245H223SkewIndication()
  5235. /*****************************************************************************
  5236. *
  5237. * TYPE: H245 API
  5238. *
  5239. * PROCEDURE: H245H2250MaximumSkewIndication
  5240. *
  5241. * DESCRIPTION
  5242. *
  5243. * RETURN:
  5244. *
  5245. *****************************************************************************/
  5246. H245DLL HRESULT
  5247. H245H2250MaximumSkewIndication(
  5248. H245_INST_T dwInst,
  5249. H245_CHANNEL_T wLogicalChannelNumber1,
  5250. H245_CHANNEL_T wLogicalChannelNumber2,
  5251. unsigned short wMaximumSkew
  5252. )
  5253. {
  5254. register struct InstanceStruct *pInstance;
  5255. register PDU_T * pPdu;
  5256. HRESULT lError;
  5257. H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication <-");
  5258. pInstance = InstanceLock(dwInst);
  5259. if (pInstance == NULL)
  5260. {
  5261. H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5262. return H245_ERROR_INVALID_INST;
  5263. }
  5264. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  5265. if (pPdu == NULL)
  5266. {
  5267. lError = H245_ERROR_NOMEM;
  5268. }
  5269. else
  5270. {
  5271. memset(pPdu, 0, sizeof(*pPdu));
  5272. pPdu->choice = indication_chosen;
  5273. pPdu->u.indication.choice = h2250MxmmSkwIndctn_chosen;
  5274. pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber1 = wLogicalChannelNumber1;
  5275. pPdu->u.indication.u.h2250MxmmSkwIndctn.logicalChannelNumber2 = wLogicalChannelNumber2;
  5276. pPdu->u.indication.u.h2250MxmmSkwIndctn.maximumSkew = wMaximumSkew;
  5277. lError = FsmOutgoing(pInstance, pPdu, 0);
  5278. MemFree(pPdu);
  5279. }
  5280. if (lError != H245_ERROR_OK)
  5281. H245TRACE (dwInst,1,"H245H2250MaximumSkewIndication -> %s",map_api_error(lError));
  5282. else
  5283. H245TRACE (dwInst,4,"H245H2250MaximumSkewIndication -> OK");
  5284. InstanceUnlock(pInstance);
  5285. return lError;
  5286. } // H245H2250MaximumSkewIndication()
  5287. /*****************************************************************************
  5288. *
  5289. * TYPE: H245 API
  5290. *
  5291. * PROCEDURE: H245MCLocationIndication
  5292. *
  5293. * DESCRIPTION
  5294. *
  5295. * RETURN:
  5296. *
  5297. *****************************************************************************/
  5298. H245DLL HRESULT
  5299. H245MCLocationIndication(
  5300. H245_INST_T dwInst,
  5301. const H245_TRANSPORT_ADDRESS_T * pSignalAddress
  5302. )
  5303. {
  5304. register struct InstanceStruct *pInstance;
  5305. register PDU_T * pPdu;
  5306. HRESULT lError;
  5307. H245TRACE (dwInst,4,"H245MCLocationIndication <-");
  5308. pInstance = InstanceLock(dwInst);
  5309. if (pInstance == NULL)
  5310. {
  5311. H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5312. return H245_ERROR_INVALID_INST;
  5313. }
  5314. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  5315. if (pPdu == NULL)
  5316. {
  5317. lError = H245_ERROR_NOMEM;
  5318. }
  5319. else
  5320. {
  5321. memset(pPdu, 0, sizeof(*pPdu));
  5322. pPdu->choice = indication_chosen;
  5323. pPdu->u.indication.choice = mcLocationIndication_chosen;
  5324. lError = SetupTransportAddress(&pPdu->u.indication.u.mcLocationIndication.signalAddress,
  5325. pSignalAddress);
  5326. if (lError == H245_ERROR_OK)
  5327. {
  5328. lError = FsmOutgoing(pInstance, pPdu, 0);
  5329. }
  5330. MemFree(pPdu);
  5331. }
  5332. if (lError != H245_ERROR_OK)
  5333. H245TRACE (dwInst,1,"H245MCLocationIndication -> %s",map_api_error(lError));
  5334. else
  5335. H245TRACE (dwInst,4,"H245MCLocationIndication -> OK");
  5336. InstanceUnlock(pInstance);
  5337. return lError;
  5338. } // H245MCLocationIndication()
  5339. /*****************************************************************************
  5340. *
  5341. * TYPE: H245 API
  5342. *
  5343. * PROCEDURE: H245VendorIdentification
  5344. *
  5345. * DESCRIPTION
  5346. *
  5347. * RETURN:
  5348. *
  5349. *****************************************************************************/
  5350. H245DLL HRESULT
  5351. H245VendorIdentification(
  5352. H245_INST_T dwInst,
  5353. const H245_NONSTANDID_T *pIdentifier,
  5354. const unsigned char *pProductNumber,
  5355. unsigned char byProductNumberLength,
  5356. const unsigned char *pVersionNumber,
  5357. unsigned char byVersionNumberLength
  5358. )
  5359. {
  5360. register struct InstanceStruct *pInstance;
  5361. register PDU_T * pPdu;
  5362. HRESULT lError;
  5363. H245TRACE (dwInst,4,"H245VendorIdentification <-");
  5364. pInstance = InstanceLock(dwInst);
  5365. if (pInstance == NULL)
  5366. {
  5367. H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5368. return H245_ERROR_INVALID_INST;
  5369. }
  5370. pPdu = (PDU_T *)MemAlloc(sizeof(*pPdu));
  5371. if (pPdu == NULL)
  5372. {
  5373. lError = H245_ERROR_NOMEM;
  5374. }
  5375. else
  5376. {
  5377. memset(pPdu, 0, sizeof(*pPdu));
  5378. pPdu->choice = indication_chosen;
  5379. pPdu->u.indication.choice = vendorIdentification_chosen;
  5380. pPdu->u.indication.u.vendorIdentification.bit_mask = 0;
  5381. pPdu->u.indication.u.vendorIdentification.vendor = *pIdentifier;
  5382. if (pProductNumber != NULL && byProductNumberLength != 0)
  5383. {
  5384. pPdu->u.indication.u.vendorIdentification.bit_mask |= productNumber_present;
  5385. pPdu->u.indication.u.vendorIdentification.productNumber.length = byProductNumberLength;
  5386. memcpy(pPdu->u.indication.u.vendorIdentification.productNumber.value,
  5387. pProductNumber,
  5388. byProductNumberLength);
  5389. }
  5390. if (pVersionNumber != NULL && byVersionNumberLength != 0)
  5391. {
  5392. pPdu->u.indication.u.vendorIdentification.bit_mask |= versionNumber_present;
  5393. pPdu->u.indication.u.vendorIdentification.versionNumber.length = byVersionNumberLength;
  5394. memcpy(pPdu->u.indication.u.vendorIdentification.versionNumber.value,
  5395. pVersionNumber,
  5396. byVersionNumberLength);
  5397. }
  5398. lError = FsmOutgoing(pInstance, pPdu, 0);
  5399. MemFree(pPdu);
  5400. }
  5401. if (lError != H245_ERROR_OK)
  5402. H245TRACE (dwInst,1,"H245VendorIdentification -> %s",map_api_error(lError));
  5403. else
  5404. H245TRACE (dwInst,4,"H245VendorIdentification -> OK");
  5405. InstanceUnlock(pInstance);
  5406. return lError;
  5407. } // H245VendorIdentification()
  5408. /*****************************************************************************
  5409. *
  5410. * TYPE: H245 API
  5411. *
  5412. * PROCEDURE: H245SendPDU
  5413. *
  5414. * DESCRIPTION
  5415. *
  5416. * RETURN:
  5417. *
  5418. *****************************************************************************/
  5419. H245DLL HRESULT
  5420. H245SendPDU (
  5421. H245_INST_T dwInst,
  5422. PDU_T * pPdu
  5423. )
  5424. {
  5425. register struct InstanceStruct *pInstance;
  5426. HRESULT lError;
  5427. H245TRACE (dwInst,4,"H245SendPDU <-");
  5428. // Check for valid instance handle
  5429. pInstance = InstanceLock(dwInst);
  5430. if (pInstance == NULL)
  5431. {
  5432. H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(H245_ERROR_INVALID_INST));
  5433. return H245_ERROR_INVALID_INST;
  5434. }
  5435. lError = FsmOutgoing(pInstance, pPdu, 0);
  5436. if (lError != H245_ERROR_OK)
  5437. H245TRACE (dwInst,1,"H245SendPDU -> %s",map_api_error(lError));
  5438. else
  5439. H245TRACE (dwInst,4,"H245SendPDU -> OK");
  5440. InstanceUnlock(pInstance);
  5441. return lError;
  5442. } // H245SendPDU()
  5443. /*****************************************************************************
  5444. *
  5445. * TYPE: H245 API
  5446. *
  5447. *****************************************************************************
  5448. *
  5449. * PROCEDURE: H245SystemControl
  5450. *
  5451. * DESCRIPTION
  5452. *
  5453. * HRESULT H245SystemControl
  5454. * ( H245_INST_T dwInst,
  5455. * DWORD Request ,
  5456. * VOID *pData
  5457. * )
  5458. *
  5459. * Description:
  5460. * This function should not be used by clients who
  5461. * normally interface to the H.245 subsystem. It is
  5462. * defined here to help during development and debug
  5463. * of the H.245 subsystem.
  5464. *
  5465. * This is a roll your own.. and can do what
  5466. * ever the user needs.. It's a hook to allow
  5467. * IOCTL (unix) calls that can either be
  5468. * passed to lower stack elements (AT&T Streams IOCTL
  5469. * would be an example - :) or simply to get or put
  5470. * information to the H245 SubSytem.
  5471. *
  5472. * Input
  5473. * dwInst Instance handle returned by H245Init
  5474. * Request Requested system control
  5475. * pData In the case of sending information
  5476. * down to H.245 this is an input
  5477. * parameter, and it's data format
  5478. * is determined by the Request.
  5479. * output
  5480. * pData In the case of retrieving information
  5481. * from H.245 this can be an output
  5482. * parameter, and it's data format is
  5483. * determined by the Request. It may not
  5484. * have valid data if the request is a
  5485. * synchronous request. (See Request Options).
  5486. * Call Type:
  5487. *
  5488. * Synchronous
  5489. *
  5490. * Request Options:
  5491. *
  5492. * H245_SYSCON_GET_STATS Retrieves Statistics
  5493. * from H.245 subsystem
  5494. * parameter pData = &H245_SYSCON_STAT_T
  5495. * H245_ SYSCON_RESET_STATS Resets the statistics
  5496. * pData = NULL
  5497. * H245_SYS_TRACE Set Trace Level
  5498. * pData = &DWORD (Trace Level)
  5499. *
  5500. * Return Values:
  5501. * See Request Options
  5502. *
  5503. * Errors:
  5504. * H245_ERROR_OK
  5505. *
  5506. * RETURN:
  5507. *
  5508. *****************************************************************************/
  5509. H245DLL HRESULT
  5510. H245SystemControl (
  5511. H245_INST_T dwInst,
  5512. unsigned long dwRequest,
  5513. void * pData
  5514. )
  5515. {
  5516. HRESULT lError;
  5517. DWORD dwTemp;
  5518. H245TRACE(dwInst,4,"H245SystemControl <-");
  5519. if (dwRequest == H245_SYSCON_DUMP_TRACKER)
  5520. {
  5521. register struct InstanceStruct *pInstance = InstanceLock(dwInst);
  5522. if (pInstance == NULL)
  5523. {
  5524. lError = H245_ERROR_INVALID_INST;
  5525. }
  5526. else
  5527. {
  5528. dump_tracker(pInstance);
  5529. InstanceUnlock(pInstance);
  5530. lError = H245_ERROR_OK;
  5531. }
  5532. }
  5533. else if (pData == NULL)
  5534. {
  5535. lError = H245_ERROR_PARAM;
  5536. }
  5537. else
  5538. {
  5539. lError = H245_ERROR_OK;
  5540. switch (dwRequest)
  5541. {
  5542. case H245_SYSCON_GET_FSM_N100:
  5543. *((DWORD *)pData) = (DWORD) uN100;
  5544. H245TRACE(dwInst,20,"H245SystemControl: Get N100 = %d",*((DWORD *)pData));
  5545. break;
  5546. case H245_SYSCON_GET_FSM_T101:
  5547. *((DWORD *)pData) = (DWORD) uT101;
  5548. H245TRACE(dwInst,20,"H245SystemControl: Get T101 = %d",*((DWORD *)pData));
  5549. break;
  5550. case H245_SYSCON_GET_FSM_T102:
  5551. *((DWORD *)pData) = (DWORD) uT102;
  5552. H245TRACE(dwInst,20,"H245SystemControl: Get T102 = %d",*((DWORD *)pData));
  5553. break;
  5554. case H245_SYSCON_GET_FSM_T103:
  5555. *((DWORD *)pData) = (DWORD) uT103;
  5556. H245TRACE(dwInst,20,"H245SystemControl: Get T103 = %d",*((DWORD *)pData));
  5557. break;
  5558. case H245_SYSCON_GET_FSM_T104:
  5559. *((DWORD *)pData) = (DWORD) uT104;
  5560. H245TRACE(dwInst,20,"H245SystemControl: Get T104 = %d",*((DWORD *)pData));
  5561. break;
  5562. case H245_SYSCON_GET_FSM_T105:
  5563. *((DWORD *)pData) = (DWORD) uT105;
  5564. H245TRACE(dwInst,20,"H245SystemControl: Get T105 = %d",*((DWORD *)pData));
  5565. break;
  5566. case H245_SYSCON_GET_FSM_T106:
  5567. *((DWORD *)pData) = (DWORD) uT106;
  5568. H245TRACE(dwInst,20,"H245SystemControl: Get T106 = %d",*((DWORD *)pData));
  5569. break;
  5570. case H245_SYSCON_GET_FSM_T107:
  5571. *((DWORD *)pData) = (DWORD) uT107;
  5572. H245TRACE(dwInst,20,"H245SystemControl: Get T107 = %d",*((DWORD *)pData));
  5573. break;
  5574. case H245_SYSCON_GET_FSM_T108:
  5575. *((DWORD *)pData) = (DWORD) uT108;
  5576. H245TRACE(dwInst,20,"H245SystemControl: Get T108 = %d",*((DWORD *)pData));
  5577. break;
  5578. case H245_SYSCON_GET_FSM_T109:
  5579. *((DWORD *)pData) = (DWORD) uT109;
  5580. H245TRACE(dwInst,20,"H245SystemControl: Get T109 = %d",*((DWORD *)pData));
  5581. break;
  5582. case H245_SYSCON_SET_FSM_N100:
  5583. dwTemp = (DWORD) uN100;
  5584. uN100 = (unsigned int) *((DWORD *)pData);
  5585. H245TRACE(dwInst,20,"H245SystemControl: Set N100 = %d",uN100);
  5586. *((DWORD *)pData) = dwTemp;
  5587. break;
  5588. case H245_SYSCON_SET_FSM_T101:
  5589. dwTemp = (DWORD) uT101;
  5590. uT101 = (unsigned int) *((DWORD *)pData);
  5591. H245TRACE(dwInst,20,"H245SystemControl: Set T101 = %d",uT101);
  5592. *((DWORD *)pData) = dwTemp;
  5593. break;
  5594. case H245_SYSCON_SET_FSM_T102:
  5595. dwTemp = (DWORD) uT102;
  5596. uT102 = (unsigned int) *((DWORD *)pData);
  5597. H245TRACE(dwInst,20,"H245SystemControl: Set T102 = %d",uT102);
  5598. *((DWORD *)pData) = dwTemp;
  5599. break;
  5600. case H245_SYSCON_SET_FSM_T103:
  5601. dwTemp = (DWORD) uT103;
  5602. uT103 = (unsigned int) *((DWORD *)pData);
  5603. H245TRACE(dwInst,20,"H245SystemControl: Set T103 = %d",uT103);
  5604. *((DWORD *)pData) = dwTemp;
  5605. break;
  5606. case H245_SYSCON_SET_FSM_T104:
  5607. dwTemp = (DWORD) uT104;
  5608. uT104 = (unsigned int) *((DWORD *)pData);
  5609. H245TRACE(dwInst,20,"H245SystemControl: Set T104 = %d",uT104);
  5610. *((DWORD *)pData) = dwTemp;
  5611. break;
  5612. case H245_SYSCON_SET_FSM_T105:
  5613. dwTemp = (DWORD) uT105;
  5614. uT105 = (unsigned int) *((DWORD *)pData);
  5615. H245TRACE(dwInst,20,"H245SystemControl: Set T105 = %d",uT105);
  5616. *((DWORD *)pData) = dwTemp;
  5617. break;
  5618. case H245_SYSCON_SET_FSM_T106:
  5619. dwTemp = (DWORD) uT106;
  5620. uT106 = (unsigned int) *((DWORD *)pData);
  5621. H245TRACE(dwInst,20,"H245SystemControl: Set T106 = %d",uT106);
  5622. *((DWORD *)pData) = dwTemp;
  5623. break;
  5624. case H245_SYSCON_SET_FSM_T107:
  5625. dwTemp = (DWORD) uT107;
  5626. uT107 = (unsigned int) *((DWORD *)pData);
  5627. H245TRACE(dwInst,20,"H245SystemControl: Set T107 = %d",uT107);
  5628. *((DWORD *)pData) = dwTemp;
  5629. break;
  5630. case H245_SYSCON_SET_FSM_T108:
  5631. dwTemp = (DWORD) uT108;
  5632. uT108 = (unsigned int) *((DWORD *)pData);
  5633. H245TRACE(dwInst,20,"H245SystemControl: Set T108 = %d",uT108);
  5634. *((DWORD *)pData) = dwTemp;
  5635. break;
  5636. case H245_SYSCON_SET_FSM_T109:
  5637. dwTemp = (DWORD) uT109;
  5638. uT109 = (unsigned int) *((DWORD *)pData);
  5639. H245TRACE(dwInst,20,"H245SystemControl: Set T109 = %d",uT109);
  5640. *((DWORD *)pData) = dwTemp;
  5641. break;
  5642. case H245_SYSCON_TRACE_LVL:
  5643. dwTemp = TraceLevel;
  5644. TraceLevel = *(DWORD *)pData;
  5645. H245TRACE(dwInst,20,"H245SystemControl: Set TraceLevel = %d",TraceLevel);
  5646. *((DWORD *)pData) = dwTemp;
  5647. break;
  5648. default:
  5649. lError = H245_ERROR_NOTIMP;
  5650. } // switch
  5651. } // else
  5652. if (lError != H245_ERROR_OK)
  5653. H245TRACE(dwInst,1,"H245SystemControl -> %s",map_api_error(lError));
  5654. else
  5655. H245TRACE(dwInst,4,"H245SystemControl -> OK");
  5656. return lError;
  5657. } // H245SystemControl()
  5658.