Source code of Windows XP (NT5)
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.

3944 lines
97 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. call.c
  5. Abstract:
  6. TAPI Service Provider functions related to manipulating calls.
  7. TSPI_lineAnswer
  8. TSPI_lineCloseCall
  9. TSPI_lineDrop
  10. TSPI_lineGetCallAddressID
  11. TSPI_lineGetCallInfo
  12. TSPI_lineGetCallStatus
  13. TSPI_lineMakeCallMSP
  14. Environment:
  15. User Mode - Win32
  16. --*/
  17. ///////////////////////////////////////////////////////////////////////////////
  18. // //
  19. // Include files //
  20. // //
  21. ///////////////////////////////////////////////////////////////////////////////
  22. #include "globals.h"
  23. #include "provider.h"
  24. #include "registry.h"
  25. #include "termcaps.h"
  26. #include "callback.h"
  27. #include "line.h"
  28. #include <h323tsp.h>
  29. #include <h323pdu.h>
  30. #include <iphlpapi.h>
  31. WCHAR g_strAlias[MAX_ALIAS_LENGTH+1];
  32. DWORD g_dwAliasLength = 0;
  33. ///////////////////////////////////////////////////////////////////////////////
  34. // //
  35. // Private procedures //
  36. // //
  37. ///////////////////////////////////////////////////////////////////////////////
  38. BOOL
  39. H323CloseCallCommand(
  40. PH323_CALL pCall
  41. )
  42. /*++
  43. Routine Description:
  44. Sends CLOSE_CALL_COMMAND from TSP to MSP.
  45. Arguments:
  46. pCall - Specifies a pointer to the associated call object.
  47. Return Values:
  48. Returns true if successful.
  49. --*/
  50. {
  51. H323TSP_MESSAGE Message;
  52. // set the appropriate message type
  53. Message.Type = H323TSP_CLOSE_CALL_COMMAND;
  54. // send msp message
  55. (*g_pfnLineEventProc)(
  56. pCall->pLine->htLine,
  57. pCall->htCall,
  58. LINE_SENDMSPDATA,
  59. MSP_HANDLE_UNKNOWN,
  60. (DWORD_PTR)&Message,
  61. sizeof(Message)
  62. );
  63. // success
  64. return TRUE;
  65. }
  66. BOOL
  67. H323AddU2U(
  68. PLIST_ENTRY pListHead,
  69. DWORD dwDataSize,
  70. PBYTE pData
  71. )
  72. /*++
  73. Routine Description:
  74. Create user user structure and adds to list.
  75. Arguments:
  76. pListHead - Pointer to list in which to add user user info.
  77. dwDataSize - Size of buffer pointed to by pData.
  78. pData - Pointer to user user info.
  79. Return Values:
  80. Returns true if successful.
  81. --*/
  82. {
  83. PH323_U2ULE pU2ULE;
  84. // validate data buffer pointer and size
  85. if ((pData != NULL) && (dwDataSize > 0)) {
  86. // allocate memory for user user info
  87. pU2ULE = H323HeapAlloc(dwDataSize + sizeof(H323_U2ULE));
  88. // validate pointer
  89. if (pU2ULE == NULL) {
  90. H323DBG((
  91. DEBUG_LEVEL_ERROR,
  92. "could not allocate user user info.\n"
  93. ));
  94. // failure
  95. return FALSE;
  96. }
  97. // aim pointer at the end of the buffer by default
  98. pU2ULE->pU2U = (LPBYTE)pU2ULE + sizeof(H323_U2ULE);
  99. pU2ULE->dwU2USize = dwDataSize;
  100. // transfer user user info into list entry
  101. memcpy(pU2ULE->pU2U, pData, pU2ULE->dwU2USize);
  102. // add list entry to back of list
  103. InsertTailList(pListHead, &pU2ULE->Link);
  104. H323DBG((
  105. DEBUG_LEVEL_VERBOSE,
  106. "added user user info 0x%08lx (%d bytes).\n",
  107. pU2ULE->pU2U,
  108. pU2ULE->dwU2USize
  109. ));
  110. }
  111. // success
  112. return TRUE;
  113. }
  114. BOOL
  115. H323RemoveU2U(
  116. PLIST_ENTRY pListHead,
  117. PH323_U2ULE * ppU2ULE
  118. )
  119. /*++
  120. Routine Description:
  121. Removes user user info structure from list.
  122. Arguments:
  123. pListHead - Pointer to list in which to remove user user info.
  124. ppU2ULE - Pointer to pointer to list entry.
  125. Return Values:
  126. Returns true if successful.
  127. --*/
  128. {
  129. PLIST_ENTRY pLE;
  130. // process list until empty
  131. if (!IsListEmpty(pListHead)) {
  132. // retrieve first entry
  133. pLE = RemoveHeadList(pListHead);
  134. // convert list entry to structure pointer
  135. *ppU2ULE = CONTAINING_RECORD(pLE, H323_U2ULE, Link);
  136. H323DBG((
  137. DEBUG_LEVEL_VERBOSE,
  138. "removed user user info 0x%08lx (%d bytes).\n",
  139. (*ppU2ULE)->pU2U,
  140. (*ppU2ULE)->dwU2USize
  141. ));
  142. // success
  143. return TRUE;
  144. }
  145. // failure
  146. return FALSE;
  147. }
  148. BOOL
  149. H323FreeU2U(
  150. PLIST_ENTRY pListHead
  151. )
  152. /*++
  153. Routine Description:
  154. Releases memory for user user list.
  155. Arguments:
  156. pListHead - Pointer to list in which to free user user info.
  157. Return Values:
  158. Returns true if successful.
  159. --*/
  160. {
  161. PLIST_ENTRY pLE;
  162. PH323_U2ULE pU2ULE;
  163. // process list until empty
  164. while (!IsListEmpty(pListHead)) {
  165. // retrieve first entry
  166. pLE = RemoveHeadList(pListHead);
  167. // convert list entry to structure pointer
  168. pU2ULE = CONTAINING_RECORD(pLE, H323_U2ULE, Link);
  169. // release memory
  170. H323HeapFree(pU2ULE);
  171. }
  172. // success
  173. return TRUE;
  174. }
  175. BOOL
  176. H323ResetCall(
  177. PH323_CALL pCall
  178. )
  179. /*++
  180. Routine Description:
  181. Resets call object to original state for re-use.
  182. Arguments:
  183. pCall - Specifies a pointer to the call object to be reset.
  184. Return Values:
  185. Returns true if successful.
  186. --*/
  187. {
  188. // reset state of call object
  189. pCall->nState = H323_CALLSTATE_ALLOCATED;
  190. // reset tapi info
  191. pCall->dwCallState = LINECALLSTATE_UNKNOWN;
  192. pCall->dwCallStateMode = 0;
  193. pCall->dwOrigin = LINECALLORIGIN_UNKNOWN;
  194. pCall->dwAddressType = 0;
  195. pCall->dwIncomingModes = 0;
  196. pCall->dwOutgoingModes = 0;
  197. pCall->dwRequestedModes = 0;
  198. pCall->fMonitoringDigits = FALSE;
  199. pCall->dwAppSpecific = 0;
  200. // reset tapi handles
  201. pCall->hdCall = (HDRVCALL)NULL;
  202. pCall->htCall = (HTAPICALL)NULL;
  203. // reset intelcc handles
  204. pCall->hccCall = UNINITIALIZED;
  205. pCall->hccConf = UNINITIALIZED;
  206. // reset link speeds
  207. pCall->dwLinkSpeed = UNINITIALIZED;
  208. // reset addresses
  209. memset(&pCall->ccCalleeAddr,0,sizeof(CC_ADDR));
  210. memset(&pCall->ccCallerAddr,0,sizeof(CC_ADDR));
  211. // release alias strings
  212. H323HeapFree(pCall->ccCalleeAlias.pData);
  213. H323HeapFree(pCall->ccCallerAlias.pData);
  214. // reset aliases
  215. memset(&pCall->ccCalleeAlias,0,sizeof(CC_ALIASITEM));
  216. memset(&pCall->ccCallerAlias,0,sizeof(CC_ALIASITEM));
  217. // reset remote caps
  218. memset(&pCall->ccRemoteAudioCaps,0,sizeof(CC_TERMCAP));
  219. memset(&pCall->ccRemoteVideoCaps,0,sizeof(CC_TERMCAP));
  220. // release user user information
  221. H323FreeU2U(&pCall->IncomingU2U);
  222. H323FreeU2U(&pCall->OutgoingU2U);
  223. // success
  224. return TRUE;
  225. }
  226. BOOL
  227. H323AllocCall(
  228. PH323_CALL * ppCall
  229. )
  230. /*++
  231. Routine Description:
  232. Allocates call object and channel table.
  233. Arguments:
  234. ppCall - Specifies a pointer to a DWORD-sized value which the service
  235. provider fills in with the newly allocated call object.
  236. Return Values:
  237. Returns true if successful.
  238. --*/
  239. {
  240. HRESULT hr;
  241. PH323_CALL pCall;
  242. // allocate call from heap
  243. pCall = H323HeapAlloc(sizeof(H323_CALL));
  244. // validate pointer
  245. if (pCall == NULL) {
  246. H323DBG((
  247. DEBUG_LEVEL_ERROR,
  248. "could not allocate call object.\n"
  249. ));
  250. // failure
  251. return FALSE;
  252. }
  253. // allocate default channel objects
  254. if (!H323AllocChannelTable(&pCall->pChannelTable)) {
  255. // release call
  256. H323HeapFree(pCall);
  257. // failure
  258. return FALSE;
  259. }
  260. H323DBG((
  261. DEBUG_LEVEL_VERBOSE,
  262. "call 0x%08lx allocated.\n",
  263. pCall
  264. ));
  265. // initialize user user information
  266. InitializeListHead(&pCall->IncomingU2U);
  267. InitializeListHead(&pCall->OutgoingU2U);
  268. // reset call object
  269. H323ResetCall(pCall);
  270. // transfer
  271. *ppCall = pCall;
  272. // success
  273. return TRUE;
  274. }
  275. BOOL
  276. H323FreeCall(
  277. PH323_CALL pCall
  278. )
  279. /*++
  280. Routine Description:
  281. Deallocates call object and channel table.
  282. Arguments:
  283. pCall - Specifies a pointer to the call object to release.
  284. Return Values:
  285. Returns true if successful.
  286. --*/
  287. {
  288. // validate pointer
  289. if (pCall != NULL) {
  290. // release memory for channel table
  291. H323FreeChannelTable(pCall->pChannelTable);
  292. // reset call
  293. H323ResetCall(pCall);
  294. // release call
  295. H323HeapFree(pCall);
  296. }
  297. H323DBG((
  298. DEBUG_LEVEL_VERBOSE,
  299. "call 0x%08lx released.\n",
  300. pCall
  301. ));
  302. // success
  303. return TRUE;
  304. }
  305. DWORD
  306. H323DetermineLinkSpeed(
  307. DWORD dwHostAddr
  308. )
  309. /*++
  310. Routine Description:
  311. Determines speed of specified link.
  312. Arguments:
  313. dwHostAddr - interface address given in host order.
  314. Return Values:
  315. Returns link speed (defaults to 28.8kbps).
  316. --*/
  317. {
  318. #define DEFAULT_IPADDRROW 10
  319. #define DEFAULT_LINKSPEED (MAXIMUM_BITRATE_28800 * 100)
  320. DWORD dwSize;
  321. DWORD dwIndex;
  322. DWORD dwStatus;
  323. DWORD dwIPAddr;
  324. DWORD dwIfIndex = UNINITIALIZED;
  325. PMIB_IPADDRTABLE pIPAddrTable = NULL;
  326. MIB_IFROW IfRow;
  327. // convert to network order
  328. dwIPAddr = htonl(dwHostAddr);
  329. H323DBG((
  330. DEBUG_LEVEL_VERBOSE,
  331. "determining link speed for %s\n",
  332. H323AddrToString(dwIPAddr)
  333. ));
  334. // default to reasonable size
  335. dwSize = sizeof(MIB_IPADDRTABLE) +
  336. sizeof(MIB_IPADDRROW) * DEFAULT_IPADDRROW
  337. ;
  338. do {
  339. H323DBG((
  340. DEBUG_LEVEL_VERBOSE,
  341. "allocating IP address table (%d bytes)\n",
  342. dwSize
  343. ));
  344. // release buffer
  345. H323HeapFree(pIPAddrTable);
  346. // allocate default table
  347. pIPAddrTable = H323HeapAlloc(dwSize);
  348. // validate pointer
  349. if (pIPAddrTable == NULL) {
  350. H323DBG((
  351. DEBUG_LEVEL_ERROR,
  352. "could not allocate IP address table\n"
  353. ));
  354. // failure
  355. return DEFAULT_LINKSPEED;
  356. }
  357. // attempt to get table
  358. dwStatus = GetIpAddrTable(
  359. pIPAddrTable,
  360. &dwSize,
  361. FALSE // sort table
  362. );
  363. } while (dwStatus == ERROR_INSUFFICIENT_BUFFER);
  364. // validate status
  365. if (dwStatus != NOERROR) {
  366. H323DBG((
  367. DEBUG_LEVEL_ERROR,
  368. "error 0x%08lx calling GetIpAddrTable\n",
  369. dwStatus
  370. ));
  371. // release buffer
  372. H323HeapFree(pIPAddrTable);
  373. // failure
  374. return DEFAULT_LINKSPEED;
  375. }
  376. // find the correct row in the table
  377. for (dwIndex = 0; dwIndex < pIPAddrTable->dwNumEntries; dwIndex++) {
  378. // compare given address to interface address
  379. if (dwIPAddr == pIPAddrTable->table[dwIndex].dwAddr) {
  380. // save index into interface table
  381. dwIfIndex = pIPAddrTable->table[dwIndex].dwIndex;
  382. H323DBG((
  383. DEBUG_LEVEL_TRACE,
  384. "address %s maps to interface %d\n",
  385. H323AddrToString(dwIPAddr),
  386. dwIfIndex
  387. ));
  388. // done
  389. break;
  390. }
  391. }
  392. // release buffer
  393. H323HeapFree(pIPAddrTable);
  394. // validate row pointer
  395. if (dwIfIndex == UNINITIALIZED) {
  396. H323DBG((
  397. DEBUG_LEVEL_ERROR,
  398. "could not locate %s in IP address table\n",
  399. H323AddrToString(dwIPAddr)
  400. ));
  401. // failure
  402. return DEFAULT_LINKSPEED;
  403. }
  404. // initialize structure
  405. memset(&IfRow,0,sizeof(IfRow));
  406. // set interface index
  407. IfRow.dwIndex = dwIfIndex;
  408. // retrieve interface info
  409. dwStatus = GetIfEntry(&IfRow);
  410. // validate status
  411. if (dwStatus != NOERROR) {
  412. H323DBG((
  413. DEBUG_LEVEL_ERROR,
  414. "error 0x%08lx calling GetIfEntry(%d)\n",
  415. dwStatus,
  416. dwIfIndex
  417. ));
  418. // failure
  419. return DEFAULT_LINKSPEED;
  420. }
  421. H323DBG((
  422. DEBUG_LEVEL_TRACE,
  423. "interface %d has link speed of %d bps\n",
  424. dwIfIndex,
  425. IfRow.dwSpeed
  426. ));
  427. // return link speed
  428. return IfRow.dwSpeed;
  429. }
  430. BOOL
  431. H323ResolveCallerAddress(
  432. PH323_CALL pCall
  433. )
  434. /*++
  435. Routine Description:
  436. Resolves caller address from callee address.
  437. Arguments:
  438. pCall - Specifies a pointer to the call object of interest.
  439. Return Values:
  440. Returns true if successful.
  441. --*/
  442. {
  443. INT nStatus;
  444. SOCKET hCtrlSocket;
  445. SOCKADDR CalleeSockAddr;
  446. SOCKADDR CallerSockAddr;
  447. DWORD dwNumBytesReturned = 0;
  448. // allocate control socket
  449. hCtrlSocket = WSASocket(
  450. AF_INET, // af
  451. SOCK_DGRAM, // type
  452. IPPROTO_IP, // protocol
  453. NULL, // lpProtocolInfo
  454. 0, // g
  455. WSA_FLAG_OVERLAPPED // dwFlags
  456. );
  457. // validate control socket
  458. if (hCtrlSocket == INVALID_SOCKET) {
  459. H323DBG((
  460. DEBUG_LEVEL_ERROR,
  461. "error %d creating control socket.\n",
  462. WSAGetLastError()
  463. ));
  464. // failure
  465. return FALSE;
  466. }
  467. // initialize ioctl parameters
  468. memset(&CalleeSockAddr,0,sizeof(SOCKADDR));
  469. memset(&CallerSockAddr,0,sizeof(SOCKADDR));
  470. // initialize address family
  471. CalleeSockAddr.sa_family = AF_INET;
  472. // transfer callee information
  473. ((SOCKADDR_IN*)&CalleeSockAddr)->sin_addr.s_addr =
  474. htonl(pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr);
  475. // query stack
  476. nStatus = WSAIoctl(
  477. hCtrlSocket,
  478. SIO_ROUTING_INTERFACE_QUERY,
  479. &CalleeSockAddr,
  480. sizeof(SOCKADDR),
  481. &CallerSockAddr,
  482. sizeof(SOCKADDR),
  483. &dwNumBytesReturned,
  484. NULL,
  485. NULL
  486. );
  487. // release handle
  488. closesocket(hCtrlSocket);
  489. // validate return code
  490. if (nStatus == SOCKET_ERROR) {
  491. H323DBG((
  492. DEBUG_LEVEL_ERROR,
  493. "error 0x%08lx calling SIO_ROUTING_INTERFACE_QUERY.\n",
  494. WSAGetLastError()
  495. ));
  496. // failure
  497. return FALSE;
  498. }
  499. // save interface address of best route
  500. pCall->ccCallerAddr.nAddrType = CC_IP_BINARY;
  501. pCall->ccCallerAddr.Addr.IP_Binary.dwAddr =
  502. ntohl(((SOCKADDR_IN*)&CallerSockAddr)->sin_addr.s_addr);
  503. pCall->ccCallerAddr.Addr.IP_Binary.wPort =
  504. LOWORD(g_RegistrySettings.dwQ931CallSignallingPort);
  505. pCall->ccCallerAddr.bMulticast =
  506. IN_MULTICAST(pCall->ccCallerAddr.Addr.IP_Binary.dwAddr);
  507. H323DBG((
  508. DEBUG_LEVEL_TRACE,
  509. "caller address resolved to %s.\n",
  510. H323AddrToString(((SOCKADDR_IN*)&CallerSockAddr)->sin_addr.s_addr)
  511. ));
  512. // determine link speed for local interface
  513. pCall->dwLinkSpeed = H323DetermineLinkSpeed(
  514. pCall->ccCallerAddr.Addr.IP_Binary.dwAddr
  515. );
  516. // success
  517. return TRUE;
  518. }
  519. BOOL
  520. H323ResolveE164Address(
  521. PH323_CALL pCall,
  522. LPCWSTR pwszDialableAddr
  523. )
  524. /*++
  525. Routine Description:
  526. Resolves E.164 address ("4259367111").
  527. Arguments:
  528. pCall - Specifies a pointer to the call object of interest.
  529. pwszDialableAddr - Specifies a pointer to the dialable address specified
  530. by the TAPI application.
  531. Return Values:
  532. Returns true if successful.
  533. --*/
  534. {
  535. WCHAR * pwszValidE164Chars;
  536. WCHAR wszAddr[H323_MAXDESTNAMELEN+1];
  537. DWORD dwE164AddrSize = 0;
  538. WCHAR wszValidE164Chars[] = { CC_ALIAS_H323_PHONE_CHARS L"\0" };
  539. // make sure pstn gateway has been specified
  540. if ((g_RegistrySettings.fIsGatewayEnabled == FALSE) ||
  541. (g_RegistrySettings.ccGatewayAddr.nAddrType == 0)) {
  542. H323DBG((
  543. DEBUG_LEVEL_ERROR,
  544. "pstn gateway not specified.\n"
  545. ));
  546. // failure
  547. return FALSE;
  548. }
  549. // save gateway address as callee address
  550. pCall->ccCalleeAddr = g_RegistrySettings.ccGatewayAddr;
  551. // process until termination char
  552. while (*pwszDialableAddr != L'\0') {
  553. // reset pointer to valid characters
  554. pwszValidE164Chars = wszValidE164Chars;
  555. // process until termination char
  556. while (*pwszValidE164Chars != L'\0') {
  557. // see if valid E.164 character specified
  558. if (*pwszDialableAddr == *pwszValidE164Chars) {
  559. // save valid character in temp buffer
  560. wszAddr[dwE164AddrSize++] = *pwszDialableAddr;
  561. break;
  562. }
  563. // next valid char
  564. ++pwszValidE164Chars;
  565. }
  566. // next input char
  567. ++pwszDialableAddr;
  568. }
  569. // validate string
  570. if (dwE164AddrSize == 0) {
  571. H323DBG((
  572. DEBUG_LEVEL_ERROR,
  573. "no valid E.164 characters in string.\n"
  574. ));
  575. // failure
  576. return FALSE;
  577. }
  578. // terminate string
  579. wszAddr[dwE164AddrSize++] = '\0';
  580. // allocate callee alias from e164 address
  581. pCall->ccCalleeAlias.pData = H323HeapAlloc(
  582. dwE164AddrSize * sizeof(WCHAR)
  583. );
  584. // validate pointer
  585. if (pCall->ccCalleeAlias.pData == NULL) {
  586. H323DBG((
  587. DEBUG_LEVEL_ERROR,
  588. "could not allocate E.164 number.\n"
  589. ));
  590. // failure
  591. return FALSE;
  592. }
  593. // transfer callee alias
  594. memcpy(pCall->ccCalleeAlias.pData,
  595. wszAddr,
  596. dwE164AddrSize * sizeof(WCHAR)
  597. );
  598. // complete alias
  599. pCall->ccCalleeAlias.wType = CC_ALIAS_H323_PHONE;
  600. pCall->ccCalleeAlias.wPrefixLength = 0;
  601. pCall->ccCalleeAlias.pPrefix = NULL;
  602. pCall->ccCalleeAlias.wDataLength = LOWORD(dwE164AddrSize - 1);
  603. H323DBG((
  604. DEBUG_LEVEL_TRACE,
  605. "callee alias resolved to E.164 number %S.\n",
  606. pCall->ccCalleeAlias.pData
  607. ));
  608. // determine caller address
  609. return H323ResolveCallerAddress(pCall);
  610. }
  611. BOOL
  612. H323ResolveIPAddress(
  613. PH323_CALL pCall,
  614. LPSTR pszDialableAddr
  615. )
  616. /*++
  617. Routine Description:
  618. Resolves IP address ("172.31.255.231") or DNS entry ("DONRYAN1").
  619. Arguments:
  620. pCall - Specifies a pointer to the call object of interest.
  621. pszDialableAddr - Specifies a pointer to the dialable address specified
  622. by the TAPI application.
  623. Return Values:
  624. Returns true if successful.
  625. --*/
  626. {
  627. DWORD dwIPAddr;
  628. struct hostent * pHost;
  629. // attempt to convert ip address
  630. dwIPAddr = inet_addr(pszDialableAddr);
  631. // see if address converted
  632. if (dwIPAddr == UNINITIALIZED) {
  633. // attempt to lookup hostname
  634. pHost = gethostbyname(pszDialableAddr);
  635. // validate pointer
  636. if (pHost != NULL) {
  637. // retrieve host address from structure
  638. dwIPAddr = *(unsigned long *)pHost->h_addr;
  639. }
  640. }
  641. // see if address converted
  642. if (dwIPAddr == UNINITIALIZED) {
  643. H323DBG((
  644. DEBUG_LEVEL_ERROR,
  645. "error 0x%08lx resolving IP address.\n",
  646. WSAGetLastError()
  647. ));
  648. // failure
  649. return FALSE;
  650. }
  651. // save converted address
  652. pCall->ccCalleeAddr.nAddrType = CC_IP_BINARY;
  653. pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr = ntohl(dwIPAddr);
  654. pCall->ccCalleeAddr.Addr.IP_Binary.wPort =
  655. LOWORD(g_RegistrySettings.dwQ931CallSignallingPort);
  656. pCall->ccCalleeAddr.bMulticast =
  657. IN_MULTICAST(pCall->ccCalleeAddr.Addr.IP_Binary.dwAddr);
  658. H323DBG((
  659. DEBUG_LEVEL_TRACE,
  660. "callee address resolved to %s:%d.\n",
  661. H323AddrToString(dwIPAddr),
  662. pCall->ccCalleeAddr.Addr.IP_Binary.wPort
  663. ));
  664. // determine caller address
  665. return H323ResolveCallerAddress(pCall);
  666. }
  667. BOOL
  668. H323ResolveEmailAddress(
  669. PH323_CALL pCall,
  670. LPCWSTR pwszDialableAddr,
  671. LPSTR pszUser,
  672. LPSTR pszDomain
  673. )
  674. /*++
  675. Routine Description:
  676. Resolves e-mail address ("[email protected]").
  677. Arguments:
  678. pCall - Specifies a pointer to the call object of interest.
  679. pwszDialableAddr - Specifies a pointer to the dialable address specified
  680. by the TAPI application.
  681. pszUser - Specifies a pointer to the user component of e-mail name.
  682. pszDomain - Specified a pointer to the domain component of e-mail name.
  683. Return Values:
  684. Returns true if successful.
  685. --*/
  686. {
  687. DWORD dwAddrSize;
  688. // attempt to resolve domain locally
  689. if (H323ResolveIPAddress(pCall, pszDomain)) {
  690. // success
  691. return TRUE;
  692. }
  693. // make sure proxy has been specified
  694. if ((g_RegistrySettings.fIsProxyEnabled == FALSE) ||
  695. (g_RegistrySettings.ccProxyAddr.nAddrType == 0)) {
  696. H323DBG((
  697. DEBUG_LEVEL_ERROR,
  698. "proxy not specified.\n"
  699. ));
  700. // failure
  701. return FALSE;
  702. }
  703. // save proxy address as callee address
  704. pCall->ccCalleeAddr = g_RegistrySettings.ccProxyAddr;
  705. // size destination address string
  706. dwAddrSize = wcslen(pwszDialableAddr) + 1;
  707. // allocate callee alias from e164 address
  708. pCall->ccCalleeAlias.pData = H323HeapAlloc(
  709. dwAddrSize * sizeof(WCHAR)
  710. );
  711. // validate pointer
  712. if (pCall->ccCalleeAlias.pData == NULL) {
  713. H323DBG((
  714. DEBUG_LEVEL_ERROR,
  715. "could not allocate H.323 alias.\n"
  716. ));
  717. // failure
  718. return FALSE;
  719. }
  720. // transfer callee alias
  721. memcpy(pCall->ccCalleeAlias.pData,
  722. pwszDialableAddr,
  723. dwAddrSize * sizeof(WCHAR)
  724. );
  725. // complete alias
  726. pCall->ccCalleeAlias.wType = CC_ALIAS_H323_ID;
  727. pCall->ccCalleeAlias.wPrefixLength = 0;
  728. pCall->ccCalleeAlias.pPrefix = NULL;
  729. pCall->ccCalleeAlias.wDataLength = LOWORD(dwAddrSize - 1);
  730. H323DBG((
  731. DEBUG_LEVEL_TRACE,
  732. "callee alias resolved to H.323 alias %S.\n",
  733. pCall->ccCalleeAlias.pData
  734. ));
  735. // determine caller address
  736. return H323ResolveCallerAddress(pCall);
  737. }
  738. BOOL
  739. H323ResolveAddress(
  740. PH323_CALL pCall,
  741. LPCWSTR pwszDialableAddr
  742. )
  743. /*++
  744. Routine Description:
  745. Resolves remote address and determines the correct local address
  746. to use in order to reach remote address.
  747. Arguments:
  748. pCall - Specifies a pointer to the call object of interest.
  749. pwszDialableAddr - Specifies a pointer to the dialable address specified
  750. by the TAPI application.
  751. Return Values:
  752. Returns true if successful.
  753. --*/
  754. {
  755. DWORD dwIPAddr;
  756. CHAR szDelimiters[] = "@ \t\n";
  757. CHAR szAddr[H323_MAXDESTNAMELEN+1];
  758. LPSTR pszUser = NULL;
  759. LPSTR pszDomain = NULL;
  760. // validate pointerr
  761. if (pwszDialableAddr == NULL) {
  762. H323DBG((
  763. DEBUG_LEVEL_ERROR,
  764. "null destination address.\n"
  765. ));
  766. // failure
  767. return FALSE;
  768. }
  769. H323DBG((
  770. DEBUG_LEVEL_TRACE,
  771. "resolving %s %S.\n",
  772. H323AddressTypeToString(pCall->dwAddressType),
  773. pwszDialableAddr
  774. ));
  775. // check whether phone number has been specified
  776. if (pCall->dwAddressType == LINEADDRESSTYPE_PHONENUMBER) {
  777. // need to direct call to pstn gateway
  778. return H323ResolveE164Address(pCall, pwszDialableAddr);
  779. }
  780. // convert address from unicode
  781. if (WideCharToMultiByte(
  782. CP_ACP,
  783. 0,
  784. pwszDialableAddr,
  785. -1,
  786. szAddr,
  787. sizeof(szAddr),
  788. NULL,
  789. NULL
  790. ) == 0) {
  791. H323DBG((
  792. DEBUG_LEVEL_ERROR,
  793. "could not convert address from unicode.\n"
  794. ));
  795. // failure
  796. return FALSE;
  797. }
  798. // parse user name
  799. pszUser = strtok(szAddr, szDelimiters);
  800. // parse domain name
  801. pszDomain = strtok(NULL, szDelimiters);
  802. // validate pointer
  803. if (pszUser == NULL) {
  804. H323DBG((
  805. DEBUG_LEVEL_ERROR,
  806. "could not parse destination address.\n"
  807. ));
  808. // failure
  809. return FALSE;
  810. }
  811. // validate pointer
  812. if (pszDomain == NULL) {
  813. // switch pointers
  814. pszDomain = pszUser;
  815. // re-initialize
  816. pszUser = NULL;
  817. }
  818. H323DBG((
  819. DEBUG_LEVEL_VERBOSE,
  820. "resolving user %s domain %s.\n",
  821. pszUser,
  822. pszDomain
  823. ));
  824. // process e-mail and domain names
  825. return H323ResolveEmailAddress(
  826. pCall,
  827. pwszDialableAddr,
  828. pszUser,
  829. pszDomain
  830. );
  831. }
  832. BOOL
  833. H323ValidateCallParams(
  834. PH323_CALL pCall,
  835. LPLINECALLPARAMS pCallParams,
  836. LPCWSTR pwszDialableAddr,
  837. PDWORD pdwStatus
  838. )
  839. /*++
  840. Routine Description:
  841. Validate optional call parameters specified by user.
  842. Arguments:
  843. pCall - Pointer to call object of interest.
  844. pCallParams - Pointer to specified call parameters to be
  845. validated.
  846. pwszDialableAddr - Pointer to the dialable address specified
  847. by the TAPI application.
  848. pdwStatus - Pointer to DWORD containing error code if this
  849. routine fails for any reason.
  850. Return Values:
  851. Returns true if successful.
  852. --*/
  853. {
  854. DWORD dwMediaModes = H323_LINE_DEFMEDIAMODES;
  855. // validate pointer
  856. if (pCallParams != NULL) {
  857. // retrieve media modes specified
  858. dwMediaModes = pCallParams->dwMediaMode;
  859. // retrieve address type specified
  860. pCall->dwAddressType = pCallParams->dwAddressType;
  861. // see if we support call parameters
  862. if (pCallParams->dwCallParamFlags != 0) {
  863. H323DBG((
  864. DEBUG_LEVEL_ERROR,
  865. "do not support call parameters 0x%08lx.\n",
  866. pCallParams->dwCallParamFlags
  867. ));
  868. // do not support param flags
  869. *pdwStatus = LINEERR_INVALCALLPARAMS;
  870. // failure
  871. return FALSE;
  872. }
  873. // see if unknown bit is specified
  874. if (dwMediaModes & LINEMEDIAMODE_UNKNOWN) {
  875. H323DBG((
  876. DEBUG_LEVEL_VERBOSE,
  877. "clearing unknown media mode.\n"
  878. ));
  879. // clear unknown bit from modes
  880. dwMediaModes &= ~LINEMEDIAMODE_UNKNOWN;
  881. }
  882. // see if both audio bits are specified
  883. if ((dwMediaModes & LINEMEDIAMODE_AUTOMATEDVOICE) &&
  884. (dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE)) {
  885. H323DBG((
  886. DEBUG_LEVEL_VERBOSE,
  887. "clearing automated voice media mode.\n"
  888. ));
  889. // clear extra audio bit from modes
  890. dwMediaModes &= ~LINEMEDIAMODE_INTERACTIVEVOICE;
  891. }
  892. // see if we support media modes specified
  893. if (dwMediaModes & ~H323_LINE_MEDIAMODES) {
  894. H323DBG((
  895. DEBUG_LEVEL_ERROR,
  896. "do not support media modes 0x%08lx.\n",
  897. pCallParams->dwMediaMode
  898. ));
  899. // do not support media mode
  900. *pdwStatus = LINEERR_INVALMEDIAMODE;
  901. // failure
  902. return FALSE;
  903. }
  904. // see if we support bearer modes
  905. if (pCallParams->dwBearerMode & ~H323_LINE_BEARERMODES) {
  906. H323DBG((
  907. DEBUG_LEVEL_ERROR,
  908. "do not support bearer mode 0x%08lx.\n",
  909. pCallParams->dwBearerMode
  910. ));
  911. // do not support bearer mode
  912. *pdwStatus = LINEERR_INVALBEARERMODE;
  913. // failure
  914. return FALSE;
  915. }
  916. // see if we support address modes
  917. if (pCallParams->dwAddressMode & ~H323_LINE_ADDRESSMODES) {
  918. H323DBG((
  919. DEBUG_LEVEL_ERROR,
  920. "do not support address mode 0x%08lx.\n",
  921. pCallParams->dwAddressMode
  922. ));
  923. // do not support address mode
  924. *pdwStatus = LINEERR_INVALADDRESSMODE;
  925. // failure
  926. return FALSE;
  927. }
  928. // validate address id specified
  929. if (!H323IsValidAddressID(pCallParams->dwAddressID)) {
  930. H323DBG((
  931. DEBUG_LEVEL_ERROR,
  932. "address id 0x%08lx invalid.\n",
  933. pCallParams->dwAddressID
  934. ));
  935. // invalid address id
  936. *pdwStatus = LINEERR_INVALADDRESSID;
  937. // failure
  938. return FALSE;
  939. }
  940. // validate destination address type specified
  941. if (pCall->dwAddressType & ~H323_LINE_ADDRESSTYPES) {
  942. H323DBG((
  943. DEBUG_LEVEL_ERROR,
  944. "address type 0x%08lx invalid.\n",
  945. pCallParams->dwAddressType
  946. ));
  947. // invalid address type
  948. *pdwStatus = LINEERR_INVALADDRESSTYPE;
  949. // failure
  950. return FALSE;
  951. }
  952. // see if callee alias specified
  953. if ((pCallParams->dwCalledPartySize > 0) &&
  954. (pCall->dwAddressType != LINEADDRESSTYPE_PHONENUMBER)) {
  955. // allocate memory for callee string
  956. pCall->ccCalleeAlias.pData = H323HeapAlloc(
  957. pCallParams->dwCalledPartySize
  958. );
  959. // validate pointer
  960. if (pCall->ccCalleeAlias.pData == NULL) {
  961. H323DBG((
  962. DEBUG_LEVEL_ERROR,
  963. "could not allocate callee name.\n"
  964. ));
  965. // no memory available
  966. *pdwStatus = LINEERR_NOMEM;
  967. // failure
  968. return FALSE;
  969. }
  970. // transfer memory
  971. memcpy(pCall->ccCalleeAlias.pData,
  972. (LPBYTE)pCallParams +
  973. pCallParams->dwCalledPartyOffset,
  974. pCallParams->dwCalledPartySize
  975. );
  976. // complete alias
  977. pCall->ccCalleeAlias.wType = CC_ALIAS_H323_ID;
  978. pCall->ccCalleeAlias.wPrefixLength = 0;
  979. pCall->ccCalleeAlias.pPrefix = NULL;
  980. pCall->ccCalleeAlias.wDataLength =
  981. (WORD)wcslen(pCall->ccCalleeAlias.pData);
  982. }
  983. // see if caller name specified
  984. if (pCallParams->dwCallingPartyIDSize > 0) {
  985. // allocate memory for callee string
  986. pCall->ccCallerAlias.pData = H323HeapAlloc(
  987. pCallParams->dwCallingPartyIDSize
  988. );
  989. // validate pointer
  990. if (pCall->ccCallerAlias.pData == NULL) {
  991. H323DBG((
  992. DEBUG_LEVEL_ERROR,
  993. "could not allocate caller name.\n"
  994. ));
  995. // no memory available
  996. *pdwStatus = LINEERR_NOMEM;
  997. // failure
  998. return FALSE;
  999. }
  1000. // transfer memory
  1001. memcpy(pCall->ccCallerAlias.pData,
  1002. (LPBYTE)pCallParams +
  1003. pCallParams->dwCallingPartyIDOffset,
  1004. pCallParams->dwCallingPartyIDSize
  1005. );
  1006. // complete alias
  1007. pCall->ccCallerAlias.wType = CC_ALIAS_H323_ID;
  1008. pCall->ccCallerAlias.wPrefixLength = 0;
  1009. pCall->ccCallerAlias.pPrefix = NULL;
  1010. pCall->ccCallerAlias.wDataLength =
  1011. (WORD)wcslen(pCall->ccCallerAlias.pData);
  1012. }
  1013. // check for user user information
  1014. if (pCallParams->dwUserUserInfoSize > 0) {
  1015. // save user user info
  1016. if (!H323AddU2U(
  1017. &pCall->OutgoingU2U,
  1018. pCallParams->dwUserUserInfoSize,
  1019. (LPBYTE)pCallParams +
  1020. pCallParams->dwUserUserInfoOffset
  1021. )) {
  1022. // invalid address id
  1023. *pdwStatus = LINEERR_NOMEM;
  1024. // failure
  1025. return FALSE;
  1026. }
  1027. }
  1028. }
  1029. // clear incoming modes
  1030. pCall->dwIncomingModes = 0;
  1031. // outgoing modes will be finalized during H.245 stage
  1032. pCall->dwOutgoingModes = dwMediaModes | LINEMEDIAMODE_UNKNOWN;
  1033. // save media modes specified
  1034. pCall->dwRequestedModes = dwMediaModes;
  1035. // resolve dialable into local and remote address
  1036. if (!H323ResolveAddress(pCall, pwszDialableAddr)) {
  1037. // invalid destination addr
  1038. *pdwStatus = LINEERR_INVALADDRESS;
  1039. // failure
  1040. return FALSE;
  1041. }
  1042. // success
  1043. return TRUE;
  1044. }
  1045. ///////////////////////////////////////////////////////////////////////////////
  1046. // //
  1047. // Public procedures //
  1048. // //
  1049. ///////////////////////////////////////////////////////////////////////////////
  1050. BOOL
  1051. H323BindCall(
  1052. PH323_CALL pCall,
  1053. PCC_CONFERENCEID pConferenceID
  1054. )
  1055. /*++
  1056. Routine Description:
  1057. Associates call object with the specified conference id.
  1058. Arguments:
  1059. pCall - Specifies a pointer to the call object to bind.
  1060. pConferenceID - Pointer to conference id to be associated with call object.
  1061. Return Values:
  1062. Returns true if successful.
  1063. --*/
  1064. {
  1065. HRESULT hr;
  1066. CC_TERMCAPLIST TermCapList;
  1067. CC_TERMCAPDESCRIPTORS TermCapDescriptors;
  1068. // determine term caps from link speed
  1069. H323GetTermCapList(pCall,&TermCapList,&TermCapDescriptors);
  1070. // create conference
  1071. hr = CC_CreateConference(
  1072. &pCall->hccConf, // phConference
  1073. pConferenceID, // pConferenceID
  1074. 0, // dwConferenceConfiguration
  1075. &TermCapList, // pTermCapList
  1076. &TermCapDescriptors, // pTermCapDescriptors
  1077. &g_VendorInfo, // pVendorInfo
  1078. NULL, // pTerminalID
  1079. PtrToUlong(pCall->hdCall), // dwConferenceToken
  1080. NULL, // TermCapConstructor
  1081. NULL, // SessionTableConstructor
  1082. H323ConferenceCallback // ConferenceCallback
  1083. );
  1084. // validate
  1085. if (hr != S_OK) {
  1086. H323DBG((
  1087. DEBUG_LEVEL_ERROR,
  1088. "error %s (0x%08lx) binding call 0x%08lx.\n",
  1089. H323StatusToString(hr), hr,
  1090. pCall
  1091. ));
  1092. // failure
  1093. return FALSE;
  1094. }
  1095. H323DBG((
  1096. DEBUG_LEVEL_VERBOSE,
  1097. "call 0x%08lx bound to conference 0x%08lx.\n",
  1098. pCall,
  1099. pCall->hccConf
  1100. ));
  1101. // success
  1102. return TRUE;
  1103. }
  1104. BOOL
  1105. H323UnbindCall(
  1106. PH323_CALL pCall
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Removes association between call object and conference object.
  1111. Arguments:
  1112. pCall - Specifies a pointer to the call object to unbind.
  1113. Return Values:
  1114. Returns true if successful.
  1115. --*/
  1116. {
  1117. HRESULT hr;
  1118. // validate conference handle
  1119. if (pCall->hccConf != UNINITIALIZED) {
  1120. // destroy conference object used for call
  1121. hr = CC_DestroyConference(pCall->hccConf, FALSE);
  1122. // validate
  1123. if (hr != S_OK) {
  1124. H323DBG((
  1125. DEBUG_LEVEL_ERROR,
  1126. "error 0x%08lx destroying conference 0x%08lx.\n",
  1127. hr,
  1128. pCall->hccConf
  1129. ));
  1130. // failure
  1131. return FALSE;
  1132. }
  1133. H323DBG((
  1134. DEBUG_LEVEL_VERBOSE,
  1135. "call 0x%08lx unbound from conference 0x%08lx.\n",
  1136. pCall,
  1137. pCall->hccConf
  1138. ));
  1139. // invalidate conference handle
  1140. pCall->hccConf = UNINITIALIZED;
  1141. }
  1142. // success
  1143. return TRUE;
  1144. }
  1145. BOOL
  1146. H323PlaceCall(
  1147. PH323_CALL pCall
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. Initiates outbound call to specified destination.
  1152. Arguments:
  1153. pCall - Specifies the pointer to the call object.
  1154. Return Values:
  1155. Returns true if successful.
  1156. --*/
  1157. {
  1158. HRESULT hr;
  1159. CC_ALIASITEM LocalAlias;
  1160. CC_ALIASITEM CalleeAlias;
  1161. CC_ALIASNAMES LocalAliasNames;
  1162. CC_ALIASNAMES CalleeAliasNames;
  1163. PCC_ALIASNAMES pLocalAliasNames = NULL;
  1164. PCC_ALIASNAMES pCalleeAliasNames = NULL;
  1165. CC_NONSTANDARDDATA NonStandardData;
  1166. PCC_NONSTANDARDDATA pNonStandardData = NULL;
  1167. PH323_U2ULE pU2ULE = NULL;
  1168. PWSTR pwszDisplay = NULL;
  1169. // see if user user information specified
  1170. if (H323RemoveU2U(&pCall->OutgoingU2U,&pU2ULE)) {
  1171. // transfer header information
  1172. NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
  1173. NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
  1174. NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
  1175. // initialize octet string containing data
  1176. NonStandardData.sData.wOctetStringLength = LOWORD(pU2ULE->dwU2USize);
  1177. NonStandardData.sData.pOctetString = pU2ULE->pU2U;
  1178. // point to stack based structure
  1179. pNonStandardData = &NonStandardData;
  1180. }
  1181. // see if caller alias specified
  1182. if (g_dwAliasLength > 0)
  1183. {
  1184. // send caller name as display
  1185. pwszDisplay = g_strAlias;
  1186. }
  1187. else if ((pCall->ccCallerAlias.wType == CC_ALIAS_H323_ID) ||
  1188. (pCall->ccCallerAlias.wType == CC_ALIAS_H323_PHONE)) {
  1189. // fill in local alias list
  1190. LocalAliasNames.wCount = 1;
  1191. LocalAliasNames.pItems = &pCall->ccCallerAlias;
  1192. // initialize pointer
  1193. pLocalAliasNames = &LocalAliasNames;
  1194. // send caller name as display
  1195. pwszDisplay = pCall->ccCallerAlias.pData;
  1196. }
  1197. // see if callee alias specified
  1198. if ((pCall->ccCalleeAlias.wType == CC_ALIAS_H323_ID) ||
  1199. (pCall->ccCalleeAlias.wType == CC_ALIAS_H323_PHONE)) {
  1200. // fill in callee alias list
  1201. CalleeAliasNames.wCount = 1;
  1202. CalleeAliasNames.pItems = &pCall->ccCalleeAlias;
  1203. // initialize pointer
  1204. pCalleeAliasNames = &CalleeAliasNames;
  1205. }
  1206. // place call
  1207. hr = CC_PlaceCall(
  1208. pCall->hccConf, // hConference
  1209. &pCall->hccCall, // phCall
  1210. pLocalAliasNames, // pLocalAliasNames
  1211. pCalleeAliasNames, // pCalleeAliasNames
  1212. NULL, // pExtraCalleeAliasNames
  1213. NULL, // pCalleeExtension
  1214. pNonStandardData, // pNonStandardData
  1215. pwszDisplay, // pwszDisplay
  1216. &pCall->ccCalleeAddr, // pDestinationAddr
  1217. NULL, // pConnectAddr
  1218. 0, // dwBandwidth
  1219. PtrToUlong(pCall->hdCall) // dwUserToken
  1220. );
  1221. // validate
  1222. if (hr == S_OK) {
  1223. H323DBG((
  1224. DEBUG_LEVEL_VERBOSE,
  1225. "call 0x%08lx placed.\n",
  1226. pCall
  1227. ));
  1228. } else {
  1229. H323DBG((
  1230. DEBUG_LEVEL_ERROR,
  1231. "error 0x%08lx calling CC_PlaceCall.\n", hr
  1232. ));
  1233. }
  1234. // release memory
  1235. H323HeapFree(pU2ULE);
  1236. // return status
  1237. return (hr == S_OK);
  1238. }
  1239. BOOL
  1240. H323DropCall(
  1241. PH323_CALL pCall,
  1242. DWORD dwDisconnectMode
  1243. )
  1244. /*++
  1245. Routine Description:
  1246. Hangs up call (if necessary) and changes state to idle.
  1247. Arguments:
  1248. pCall - Specifies a pointer to the call object to drop.
  1249. dwDisconnectMode - Status code for disconnect.
  1250. Return Values:
  1251. Returns true if successful.
  1252. --*/
  1253. {
  1254. HRESULT hr;
  1255. PH323_U2ULE pU2ULE = NULL;
  1256. CC_NONSTANDARDDATA NonStandardData;
  1257. PCC_NONSTANDARDDATA pNonStandardData = NULL;
  1258. // determine call state
  1259. switch (pCall->dwCallState) {
  1260. case LINECALLSTATE_CONNECTED:
  1261. // hangup call (this will invoke async indication)
  1262. hr = CC_Hangup(pCall->hccConf, FALSE, PtrToUlong(pCall->hdCall));
  1263. // validate
  1264. if (hr == CC_OK) {
  1265. H323DBG((
  1266. DEBUG_LEVEL_VERBOSE,
  1267. "call 0x%08lx hung up.\n",
  1268. pCall
  1269. ));
  1270. } else {
  1271. H323DBG((
  1272. DEBUG_LEVEL_ERROR,
  1273. "error %s (0x%08lx) hanging up call 0x%08lx.\n",
  1274. H323StatusToString((DWORD)hr), hr,
  1275. pCall
  1276. ));
  1277. }
  1278. // change call state to disconnected
  1279. H323ChangeCallState(pCall, LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
  1280. break;
  1281. case LINECALLSTATE_OFFERING:
  1282. // see if user user information specified
  1283. if (H323RemoveU2U(&pCall->OutgoingU2U,&pU2ULE)) {
  1284. // transfer header information
  1285. NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
  1286. NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
  1287. NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
  1288. // initialize octet string containing data
  1289. NonStandardData.sData.wOctetStringLength = LOWORD(pU2ULE->dwU2USize);
  1290. NonStandardData.sData.pOctetString = pU2ULE->pU2U;
  1291. // point to stack based structure
  1292. pNonStandardData = &NonStandardData;
  1293. }
  1294. // reject call
  1295. hr = CC_RejectCall(
  1296. CC_REJECT_DESTINATION_REJECTION,
  1297. pNonStandardData,
  1298. pCall->hccCall
  1299. );
  1300. // validate
  1301. if (hr == CC_OK) {
  1302. H323DBG((
  1303. DEBUG_LEVEL_VERBOSE,
  1304. "call 0x%08lx rejected.\n",
  1305. pCall
  1306. ));
  1307. } else {
  1308. H323DBG((
  1309. DEBUG_LEVEL_ERROR,
  1310. "error %s (0x%08lx) reject call 0x%08lx.\n",
  1311. H323StatusToString((DWORD)hr), hr,
  1312. pCall
  1313. ));
  1314. }
  1315. // release memory
  1316. H323HeapFree(pU2ULE);
  1317. // change call state to disconnected
  1318. H323ChangeCallState(pCall, LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
  1319. break;
  1320. case LINECALLSTATE_DIALING:
  1321. case LINECALLSTATE_RINGBACK:
  1322. case LINECALLSTATE_ACCEPTED:
  1323. // cancel outbound call
  1324. hr = CC_CancelCall(pCall->hccCall);
  1325. // validate
  1326. if (hr == CC_OK) {
  1327. H323DBG((
  1328. DEBUG_LEVEL_VERBOSE,
  1329. "call 0x%08lx cancelled.\n",
  1330. pCall
  1331. ));
  1332. } else {
  1333. H323DBG((
  1334. DEBUG_LEVEL_ERROR,
  1335. "error %s (0x%08lx) cancelling call 0x%08lx.\n",
  1336. H323StatusToString((DWORD)hr), hr,
  1337. pCall
  1338. ));
  1339. }
  1340. // change call state to disconnected
  1341. H323ChangeCallState(pCall, LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
  1342. break;
  1343. case LINECALLSTATE_DISCONNECTED:
  1344. //
  1345. // disconnected but still need to clean up
  1346. //
  1347. break;
  1348. case LINECALLSTATE_IDLE:
  1349. //
  1350. // call object already idle
  1351. //
  1352. return TRUE;
  1353. }
  1354. // Tell the MSP to stop streaming.
  1355. H323CloseCallCommand(pCall);
  1356. // close logical channels
  1357. H323CloseChannelTable(pCall->pChannelTable);
  1358. // change call state to idle
  1359. H323ChangeCallState(pCall, LINECALLSTATE_IDLE, 0);
  1360. H323DBG((
  1361. DEBUG_LEVEL_VERBOSE,
  1362. "call 0x%08lx dropped.\n",
  1363. pCall
  1364. ));
  1365. // success
  1366. return TRUE;
  1367. }
  1368. BOOL
  1369. H323CloseCall(
  1370. PH323_CALL pCall
  1371. )
  1372. /*++
  1373. Routine Description:
  1374. Hangs up call (if necessary) and closes call object.
  1375. Arguments:
  1376. pCall - Specifies a pointer to the call object to release.
  1377. Return Values:
  1378. Returns true if successful.
  1379. --*/
  1380. {
  1381. // drop call using normal disconnect code
  1382. H323DropCall(pCall,LINEDISCONNECTMODE_NORMAL);
  1383. // unbind conference
  1384. H323UnbindCall(pCall);
  1385. // mark entry as allocated
  1386. H323FreeCallFromTable(pCall,pCall->pLine->pCallTable);
  1387. H323DBG((
  1388. DEBUG_LEVEL_VERBOSE,
  1389. "call 0x%08lx closed.\n",
  1390. pCall
  1391. ));
  1392. // success
  1393. return TRUE;
  1394. }
  1395. BOOL
  1396. H323GetCallAndLock(
  1397. PH323_CALL * ppCall,
  1398. HDRVCALL hdCall
  1399. )
  1400. /*++
  1401. Routine Description:
  1402. Retrieves pointer to call object given call handle.
  1403. Arguments:
  1404. ppCall - Specifies a pointer to a DWORD-sized memory location
  1405. into which the service provider must write the call object pointer
  1406. associated with the given call handle.
  1407. hdCall - Specifies the Service Provider's opaque handle to the call.
  1408. Return Values:
  1409. Returns true if successful.
  1410. --*/
  1411. {
  1412. DWORD i;
  1413. HDRVLINE hdLine;
  1414. PH323_LINE pLine = NULL;
  1415. PH323_CALL pCall = NULL;
  1416. // retrieve line handle from call
  1417. hdLine = H323GetLineHandle(PtrToUlong(hdCall));
  1418. // retrieve line pointer
  1419. if (!H323GetLineAndLock(&pLine, hdLine)) {
  1420. H323DBG((
  1421. DEBUG_LEVEL_ERROR,
  1422. "call handle 0x%08lx invalid line.\n",
  1423. PtrToUlong(hdCall)
  1424. ));
  1425. // unlock line device
  1426. H323UnlockLine(pLine);
  1427. // failure
  1428. return FALSE;
  1429. }
  1430. // retrieve call table index
  1431. i = H323GetCallTableIndex(PtrToUlong(hdCall));
  1432. // validate call table index
  1433. if (i >= pLine->pCallTable->dwNumSlots) {
  1434. H323DBG((
  1435. DEBUG_LEVEL_ERROR,
  1436. "call handle 0x%08lx invalid index.\n",
  1437. PtrToUlong(hdCall)
  1438. ));
  1439. // unlock line device
  1440. H323UnlockLine(pLine);
  1441. // failure
  1442. return FALSE;
  1443. }
  1444. // retrieve call pointer from table
  1445. pCall = pLine->pCallTable->pCalls[i];
  1446. // validate call information
  1447. if (!H323IsCallEqual(pCall,hdCall)) {
  1448. H323DBG((
  1449. DEBUG_LEVEL_ERROR,
  1450. "call handle 0x%08lx mismatch.\n",
  1451. PtrToUlong(hdCall)
  1452. ));
  1453. // unlock line device
  1454. H323UnlockLine(pLine);
  1455. // failure
  1456. return FALSE;
  1457. }
  1458. // transfer
  1459. *ppCall = pCall;
  1460. // success
  1461. return TRUE;
  1462. }
  1463. BOOL
  1464. H323GetCallByHCall(
  1465. PH323_CALL * ppCall,
  1466. struct _H323_LINE * pLine,
  1467. CC_HCALL hccCall
  1468. )
  1469. /*++
  1470. Routine Description:
  1471. Retrieves pointer to call object given callcont call handle.
  1472. Arguments:
  1473. ppCall - Specifies a pointer to a DWORD-sized memory location
  1474. into which the service provider must write the call object pointer
  1475. associated with the given call handle.
  1476. pLine - Specifies a pointer to associated line object.
  1477. hccCall - Specifies the call control module handle to the call.
  1478. Return Values:
  1479. Returns true if successful.
  1480. --*/
  1481. {
  1482. DWORD i;
  1483. PH323_CALL_TABLE pCallTable = pLine->pCallTable;
  1484. // loop through each object in table
  1485. for (i = 0; i < pCallTable->dwNumSlots; i++) {
  1486. // validate object has been allocated
  1487. if (H323IsCallInUse(pCallTable->pCalls[i])) {
  1488. // check for given call control handle
  1489. if (pCallTable->pCalls[i]->hccCall == hccCall) {
  1490. // transfer pointer
  1491. *ppCall = pCallTable->pCalls[i];
  1492. // success
  1493. return TRUE;
  1494. }
  1495. }
  1496. }
  1497. // failure
  1498. return FALSE;
  1499. }
  1500. BOOL
  1501. H323ChangeCallState(
  1502. PH323_CALL pCall,
  1503. DWORD dwCallState,
  1504. DWORD dwCallStateMode
  1505. )
  1506. /*++
  1507. Routine Description:
  1508. Reports call state of specified call object.
  1509. Arguments:
  1510. pCall - Specifies a pointer to call object.
  1511. dwCallState - Specifies new state of call object.
  1512. dwCallStateMode - Specifies new state mode of call object.
  1513. Return Values:
  1514. Returns true if successful.
  1515. --*/
  1516. {
  1517. H323DBG((
  1518. DEBUG_LEVEL_VERBOSE,
  1519. "call 0x%08lx %s. state mode: 0x%08lx\n",
  1520. pCall,
  1521. H323CallStateToString(dwCallState),
  1522. dwCallStateMode
  1523. ));
  1524. // save new call state
  1525. pCall->dwCallState = dwCallState;
  1526. pCall->dwCallStateMode = dwCallStateMode;
  1527. // report call status
  1528. (*g_pfnLineEventProc)(
  1529. pCall->pLine->htLine,
  1530. pCall->htCall,
  1531. LINE_CALLSTATE,
  1532. pCall->dwCallState,
  1533. pCall->dwCallStateMode,
  1534. pCall->dwIncomingModes | pCall->dwOutgoingModes
  1535. );
  1536. // success
  1537. return TRUE;
  1538. }
  1539. BOOL
  1540. H323AllocCallTable(
  1541. PH323_CALL_TABLE * ppCallTable
  1542. )
  1543. /*++
  1544. Routine Description:
  1545. Allocates table of call objects.
  1546. Arguments:
  1547. ppCallTable - Pointer to DWORD-sized value which service
  1548. provider must fill in with newly allocated table.
  1549. Return Values:
  1550. Returns true if successful.
  1551. --*/
  1552. {
  1553. PH323_CALL_TABLE pCallTable;
  1554. // allocate table from heap
  1555. pCallTable = H323HeapAlloc(
  1556. sizeof(H323_CALL_TABLE) +
  1557. sizeof(PH323_CALL) * H323_DEFCALLSPERLINE
  1558. );
  1559. // validate table pointer
  1560. if (pCallTable == NULL) {
  1561. H323DBG((
  1562. DEBUG_LEVEL_ERROR,
  1563. "could not allocate call table.\n"
  1564. ));
  1565. // failure
  1566. return FALSE;
  1567. }
  1568. // initialize number of entries in table
  1569. pCallTable->dwNumSlots = H323_DEFCALLSPERLINE;
  1570. // transfer pointer to caller
  1571. *ppCallTable = pCallTable;
  1572. // success
  1573. return TRUE;
  1574. }
  1575. BOOL
  1576. H323FreeCallTable(
  1577. PH323_CALL_TABLE pCallTable
  1578. )
  1579. /*++
  1580. Routine Description:
  1581. Deallocates table of call objects.
  1582. Arguments:
  1583. pCallTable - Pointer to call table to release.
  1584. Return Values:
  1585. Returns true if successful.
  1586. --*/
  1587. {
  1588. DWORD i;
  1589. // loop through each object in table
  1590. for (i = 0; i < pCallTable->dwNumSlots; i++) {
  1591. // validate object has been allocated
  1592. if (H323IsCallAllocated(pCallTable->pCalls[i])) {
  1593. // release memory for object
  1594. H323FreeCall(pCallTable->pCalls[i]);
  1595. }
  1596. }
  1597. // release memory for table
  1598. H323HeapFree(pCallTable);
  1599. // success
  1600. return TRUE;
  1601. }
  1602. BOOL
  1603. H323CloseCallTable(
  1604. PH323_CALL_TABLE pCallTable
  1605. )
  1606. /*++
  1607. Routine Description:
  1608. Closes table of call objects.
  1609. Arguments:
  1610. pCallTable - Pointer to table to close.
  1611. Return Values:
  1612. Returns true if successful.
  1613. --*/
  1614. {
  1615. DWORD i;
  1616. // loop through each objectin table
  1617. for (i = 0; i < pCallTable->dwNumSlots; i++) {
  1618. // validate object is in use
  1619. if (H323IsCallInUse(pCallTable->pCalls[i])) {
  1620. // close previously opened object
  1621. H323PostCloseCallMessage(pCallTable->pCalls[i]->hdCall);
  1622. }
  1623. }
  1624. // success
  1625. return TRUE;
  1626. }
  1627. BOOL
  1628. H323AllocCallFromTable(
  1629. PH323_CALL * ppCall,
  1630. PH323_CALL_TABLE * ppCallTable,
  1631. PH323_LINE pLine
  1632. )
  1633. /*++
  1634. Routine Description:
  1635. Allocates call object in table.
  1636. Arguments:
  1637. ppCall - Specifies a pointer to a DWORD-sized value in which the
  1638. service provider must write the allocated call object.
  1639. ppCallTable - Pointer to pointer to call table in which to
  1640. allocate call from (expands table if necessary).
  1641. pLine - Pointer to containing line object.
  1642. Return Values:
  1643. Returns true if successful.
  1644. --*/
  1645. {
  1646. DWORD i;
  1647. PH323_CALL pCall = NULL;
  1648. PH323_CALL_TABLE pCallTable = *ppCallTable;
  1649. // retrieve index to next entry
  1650. i = pCallTable->dwNextAvailable;
  1651. // see if previously allocated entries available
  1652. if (pCallTable->dwNumAllocated > pCallTable->dwNumInUse) {
  1653. // search table looking for available entry
  1654. while (H323IsCallInUse(pCallTable->pCalls[i]) ||
  1655. !H323IsCallAllocated(pCallTable->pCalls[i])) {
  1656. // increment index and adjust to wrap
  1657. i = H323GetNextIndex(i, pCallTable->dwNumSlots);
  1658. }
  1659. // retrieve pointer to object
  1660. pCall = pCallTable->pCalls[i];
  1661. // mark entry as being in use
  1662. pCall->nState = H323_CALLSTATE_IN_USE;
  1663. // initialize call handle with index
  1664. pCall->hdCall = H323CreateCallHandle(PtrToUlong(pLine->hdLine),i);
  1665. // increment number in use
  1666. pCallTable->dwNumInUse++;
  1667. // adjust next available index
  1668. pCallTable->dwNextAvailable =
  1669. H323GetNextIndex(i, pCallTable->dwNumSlots);
  1670. // transfer pointer
  1671. *ppCall = pCall;
  1672. // success
  1673. return TRUE;
  1674. }
  1675. // see if table is full and more slots need to be allocated
  1676. if (pCallTable->dwNumAllocated == pCallTable->dwNumSlots) {
  1677. // attempt to double table
  1678. pCallTable = H323HeapReAlloc(
  1679. pCallTable,
  1680. sizeof(H323_CALL_TABLE) +
  1681. pCallTable->dwNumSlots * 2 * sizeof(PH323_CALL)
  1682. );
  1683. // validate pointer
  1684. if (pCallTable == NULL) {
  1685. H323DBG((
  1686. DEBUG_LEVEL_ERROR,
  1687. "could not expand channel table.\n"
  1688. ));
  1689. // failure
  1690. return FALSE;
  1691. }
  1692. // adjust index into table
  1693. i = pCallTable->dwNumSlots;
  1694. // adjust number of slots
  1695. pCallTable->dwNumSlots *= 2;
  1696. // transfer pointer to caller
  1697. *ppCallTable = pCallTable;
  1698. }
  1699. // allocate new object
  1700. if (!H323AllocCall(&pCall)) {
  1701. // failure
  1702. return FALSE;
  1703. }
  1704. // search table looking for slot with no object allocated
  1705. while (H323IsCallAllocated(pCallTable->pCalls[i])) {
  1706. // increment index and adjust to wrap
  1707. i = H323GetNextIndex(i, pCallTable->dwNumSlots);
  1708. }
  1709. // store pointer to object
  1710. pCallTable->pCalls[i] = pCall;
  1711. // mark entry as being in use
  1712. pCall->nState = H323_CALLSTATE_IN_USE;
  1713. // initialize call handle with index
  1714. pCall->hdCall = H323CreateCallHandle(PtrToUlong(pLine->hdLine),i);
  1715. // increment number in use
  1716. pCallTable->dwNumInUse++;
  1717. // increment number allocated
  1718. pCallTable->dwNumAllocated++;
  1719. // adjust next available index
  1720. pCallTable->dwNextAvailable =
  1721. H323GetNextIndex(i, pCallTable->dwNumSlots);
  1722. H323DBG((
  1723. DEBUG_LEVEL_VERBOSE,
  1724. "call 0x%08lx stored in slot %d (hdCall=0x%08lx).\n",
  1725. pCall, i,
  1726. pCall->hdCall
  1727. ));
  1728. // transfer pointer
  1729. *ppCall = pCall;
  1730. // success
  1731. return TRUE;
  1732. }
  1733. BOOL
  1734. H323FreeCallFromTable(
  1735. PH323_CALL pCall,
  1736. PH323_CALL_TABLE pCallTable
  1737. )
  1738. /*++
  1739. Routine Description:
  1740. Deallocates call object in table.
  1741. Arguments:
  1742. pCall - Pointer to object to deallocate.
  1743. pCallTable - Pointer to table containing object.
  1744. Return Values:
  1745. Returns true if successful.
  1746. --*/
  1747. {
  1748. // reset call object
  1749. H323ResetCall(pCall);
  1750. // decrement entries in use
  1751. pCallTable->dwNumInUse--;
  1752. // success
  1753. return TRUE;
  1754. }
  1755. BOOL
  1756. H323AcceptCall(
  1757. PH323_CALL pCall
  1758. )
  1759. /*++
  1760. Routine Description:
  1761. Accepts incoming call.
  1762. Arguments:
  1763. pCall - Pointer to object to accept.
  1764. Return Values:
  1765. Returns true if successful.
  1766. --*/
  1767. {
  1768. HRESULT hr;
  1769. PH323_U2ULE pU2ULE = NULL;
  1770. CC_NONSTANDARDDATA NonStandardData;
  1771. PCC_NONSTANDARDDATA pNonStandardData = NULL;
  1772. PWSTR pwszDisplay = NULL;
  1773. // see if user user information specified
  1774. if (H323RemoveU2U(&pCall->OutgoingU2U,&pU2ULE)) {
  1775. // transfer header information
  1776. NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
  1777. NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
  1778. NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
  1779. // initialize octet string containing data
  1780. NonStandardData.sData.wOctetStringLength = LOWORD(pU2ULE->dwU2USize);
  1781. NonStandardData.sData.pOctetString = pU2ULE->pU2U;
  1782. // point to stack based structure
  1783. pNonStandardData = &NonStandardData;
  1784. }
  1785. // see if callee alias specified
  1786. if (g_dwAliasLength > 0)
  1787. {
  1788. pwszDisplay = g_strAlias;
  1789. }
  1790. else if ((pCall->ccCalleeAlias.wType == CC_ALIAS_H323_ID) ||
  1791. (pCall->ccCalleeAlias.wType == CC_ALIAS_H323_PHONE)) {
  1792. // send caller name as display
  1793. pwszDisplay = pCall->ccCalleeAlias.pData;
  1794. }
  1795. // accept call
  1796. hr = CC_AcceptCall(
  1797. pCall->hccConf, // hConference
  1798. pNonStandardData, // pNonStandardData
  1799. pwszDisplay, // pwszDisplay
  1800. pCall->hccCall, // hCall
  1801. 0, // dwBandwidth
  1802. PtrToUlong(pCall->hdCall) // dwUserToken
  1803. );
  1804. // validate status
  1805. if (hr != CC_OK) {
  1806. H323DBG((
  1807. DEBUG_LEVEL_ERROR,
  1808. "error %s (0x%08lx) answering call 0x%08lx.\n",
  1809. H323StatusToString((DWORD)hr), hr,
  1810. pCall
  1811. ));
  1812. // release memory
  1813. H323HeapFree(pU2ULE);
  1814. // drop call using disconnect mode
  1815. H323DropCall(pCall, LINEDISCONNECTMODE_TEMPFAILURE);
  1816. // failure
  1817. return FALSE;
  1818. }
  1819. // release memory
  1820. H323HeapFree(pU2ULE);
  1821. // change call state to accepted from offering
  1822. H323ChangeCallState(pCall, LINECALLSTATE_ACCEPTED, 0);
  1823. // success
  1824. return TRUE;
  1825. }
  1826. ///////////////////////////////////////////////////////////////////////////////
  1827. // //
  1828. // TSPI procedures //
  1829. // //
  1830. ///////////////////////////////////////////////////////////////////////////////
  1831. LONG
  1832. TSPIAPI
  1833. TSPI_lineAnswer(
  1834. DRV_REQUESTID dwRequestID,
  1835. HDRVCALL hdCall,
  1836. LPCSTR pUserUserInfo,
  1837. DWORD dwSize
  1838. )
  1839. /*++
  1840. Routine Description:
  1841. This function answers the specified offering call.
  1842. When a new call arrives, the Service Provider sends the TAPI DLL a
  1843. LINE_NEWCALL event to exchange opaque handles for the call. The Service
  1844. Provider follows this with a LINE_CALLSTATE message inform the TAPI DLL
  1845. and its client applications of the call's call state. The TAPI DLL
  1846. typically answers this call (on behalf of an application) using
  1847. TSPI_lineAnswer. After the call has been successfully answered, the call
  1848. will typically transition to the connected state.
  1849. In some telephony environments (like ISDN) where user alerting is separate
  1850. from call offering, the TAPI DLL and its client apps may have the option to
  1851. first accept a call prior to answering, or instead to reject or redirect
  1852. the offering call.
  1853. If a call comes in (is offered) at the time another call is already active,
  1854. then the new call is connected to by invoking TSPI_lineAnswer. The effect
  1855. this has on the existing active call depends on the line's device
  1856. capabilities. The first call may be unaffected, it may automatically be
  1857. dropped, or it may automatically be placed on hold. The appropriate
  1858. LINE_CALLSTATE messages will report state transitions to the TAPI DLL about
  1859. both calls.
  1860. The TAPI DLL has the option to send user-to-user information at the time of
  1861. the answer. Even if user-to-user information can be sent, often no
  1862. guarantees are made that the network will deliver this information to the
  1863. calling party. The TAPI DLL can consult a line's device capabilities to
  1864. determine whether or not sending user-to-user information on answer is
  1865. available.
  1866. Arguments:
  1867. dwRequestID - Specifies the identifier of the asynchronous request.
  1868. The Service Provider returns this value if the function completes
  1869. asynchronously.
  1870. hdCall - Specifies the Service Provider's opaque handle to the call to be
  1871. answered. Valid call states: offering, accepted.
  1872. pUserUserInfo - Specifies a far pointer to a string containing
  1873. user-to-user information to be sent to the remote party at the time of
  1874. answering the call. If this pointer is NULL, it indicates that no
  1875. user-to-user information is to be sent. User-to-user information is
  1876. only sent if supported by the underlying network (see LINEDEVCAPS).
  1877. dwSize - Specifies the size in bytes of the user-to-user information in
  1878. pUserUserInfo. If pUserUserInfo is NULL, no user-to-user
  1879. information is sent to the calling party and dwSize is ignored.
  1880. Return Values:
  1881. Returns zero if the function is successful, the (positive) dwRequestID
  1882. value if the function will be completed asynchronously, or a negative
  1883. error number if an error has occurred. Possible error returns are:
  1884. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  1885. LINEERR_INVALCALLSTATE - The call is not in a valid state for the
  1886. requested operation.
  1887. LINEERR_OPERATIONFAILED - The specified operation failed for
  1888. unspecified reason.
  1889. --*/
  1890. {
  1891. PH323_CALL pCall = NULL;
  1892. CC_NONSTANDARDDATA NonStandardData;
  1893. PCC_NONSTANDARDDATA pNonStandardData = NULL;
  1894. // retrieve call pointer from handle
  1895. if (!H323GetCallAndLock(&pCall, hdCall)) {
  1896. // invalid call handle
  1897. return LINEERR_INVALCALLHANDLE;
  1898. }
  1899. // see if call in offering state
  1900. if (!H323IsCallOffering(pCall)) {
  1901. H323DBG((
  1902. DEBUG_LEVEL_ERROR,
  1903. "call 0x%08lx cannot be accepted state 0x%08lx.\n",
  1904. pCall,
  1905. pCall->dwCallState
  1906. ));
  1907. // release line device
  1908. H323UnlockLine(pCall->pLine);
  1909. // invalid call state
  1910. return LINEERR_INVALCALLSTATE;
  1911. }
  1912. // save outgoing user user information (if specified)
  1913. if (!H323AddU2U(&pCall->OutgoingU2U,dwSize,(PBYTE)pUserUserInfo)) {
  1914. H323DBG((
  1915. DEBUG_LEVEL_ERROR,
  1916. "could not save user user info.\n"
  1917. ));
  1918. // release line device
  1919. H323UnlockLine(pCall->pLine);
  1920. // no memory available
  1921. return LINEERR_NOMEM;
  1922. }
  1923. // post place request to callback thread
  1924. if (!H323PostAcceptCallMessage(pCall->hdCall)) {
  1925. H323DBG((
  1926. DEBUG_LEVEL_ERROR,
  1927. "could not accept place call message.\n"
  1928. ));
  1929. // drop call using disconnect mode
  1930. H323PostDropCallMessage(pCall->hdCall, LINEDISCONNECTMODE_TEMPFAILURE);
  1931. // release line device
  1932. H323UnlockLine(pCall->pLine);
  1933. // could not complete operation
  1934. return LINEERR_OPERATIONFAILED;
  1935. }
  1936. // complete the async accept operation now
  1937. (*g_pfnCompletionProc)(dwRequestID, NOERROR);
  1938. // release line device
  1939. H323UnlockLine(pCall->pLine);
  1940. // async success
  1941. return dwRequestID;
  1942. }
  1943. LONG
  1944. TSPIAPI
  1945. TSPI_lineCloseCall(
  1946. HDRVCALL hdCall
  1947. )
  1948. /*++
  1949. Routine Description:
  1950. This function deletes the call after completing or aborting all outstanding
  1951. asynchronous operations on the call.
  1952. The Service Provider has the responsibility to (eventually) report
  1953. completion for every operation it decides to execute asynchronously.
  1954. If this procedure is called for a call on which there are outstanding
  1955. asynchronous operations, the operations should be reported complete with an
  1956. appropriate result or error code before this procedure returns. If there
  1957. is an active call on the line at the time of TSPI_lineCloseCall, the call
  1958. must be dropped. Generally the TAPI DLL would wait for calls to be
  1959. finished and asynchronous operations to complete in an orderly fashion.
  1960. However, the Service Provider should be prepared to handle an early call to
  1961. TSPI_lineCloseCall in "abort" or "emergency shutdown" situations.
  1962. After this procedure returns the Service Provider must report no further
  1963. events on the call. The Service Provider's opaque handle for the call
  1964. becomes "invalid".
  1965. This function is presumed to complete successfully and synchronously.
  1966. Arguments:
  1967. hdCall - Specifies the Service Provider's opaque handle to the call to be
  1968. deleted. After the call has been successfully deleted, this handle is
  1969. no longer valid. Valid call states: any.
  1970. Return Values:
  1971. None.
  1972. --*/
  1973. {
  1974. PH323_CALL pCall = NULL;
  1975. // retrieve call pointer from handle
  1976. if (!H323GetCallAndLock(&pCall, hdCall)) {
  1977. // invalid call handle
  1978. return LINEERR_INVALCALLHANDLE;
  1979. }
  1980. // close call asynchronously
  1981. if (!H323PostCloseCallMessage(pCall->hdCall)) {
  1982. // could not close call
  1983. return LINEERR_OPERATIONFAILED;
  1984. }
  1985. // release line device
  1986. H323UnlockLine(pCall->pLine);
  1987. // success
  1988. return NOERROR;
  1989. }
  1990. LONG
  1991. TSPIAPI
  1992. TSPI_lineDrop(
  1993. DRV_REQUESTID dwRequestID,
  1994. HDRVCALL hdCall,
  1995. LPCSTR pUserUserInfo,
  1996. DWORD dwSize
  1997. )
  1998. /*++
  1999. Routine Description:
  2000. This functions drops or disconnects the specified call. The TAPI DLL has
  2001. the option to specify user-to-user information to be transmitted as part
  2002. of the call disconnect.
  2003. When invoking TSPI_lineDrop related calls may sometimes be affected as
  2004. well. For example, dropping a conference call may drop all individual
  2005. participating calls. LINE_CALLSTATE messages are sent to the TAPI DLL for
  2006. all calls whose call state is affected. A dropped call will typically
  2007. transition to the idle state.
  2008. Invoking TSPI_lineDrop on a call in the offering state rejects the call.
  2009. Not all telephone networks provide this capability.
  2010. Invoking TSPI_lineDrop on a consultation call that was set up using either
  2011. TSPI_lineSetupTransfer or TSPI_lineSetupConference, will cancel the
  2012. consultation call. Some switches automatically unhold the other call.
  2013. The TAPI DLL has the option to send user-to-user information at the time
  2014. of the drop. Even if user-to-user information can be sent, often no
  2015. guarantees are made that the network will deliver this information to the
  2016. remote party.
  2017. Note that in various bridged or party line configurations when multiple
  2018. parties are on the call, TSPI_lineDrop by the application may not actually
  2019. clear the call.
  2020. Arguments:
  2021. dwRequestID - Specifies the identifier of the asynchronous request.
  2022. The Service Provider returns this value if the function completes
  2023. asynchronously.
  2024. hdCall - Specifies the Service Provider's opaque handle to the call to
  2025. be dropped. Valid call states: any.
  2026. psUserUserInfo - Specifies a far pointer to a string containing
  2027. user-to-user information to be sent to the remote party as part of
  2028. the call disconnect. This pointer is unused if dwUserUserInfoSize
  2029. is zero and no user-to-user information is to be sent. User-to-user
  2030. information is only sent if supported by the underlying network
  2031. (see LINEDEVCAPS).
  2032. dwSize - Specifies the size in bytes of the user-to-user information in
  2033. psUserUserInfo. If zero, then psUserUserInfo can be left NULL, and
  2034. no user-to-user information will be sent to the remote party.
  2035. Return Values:
  2036. Returns zero if the function is successful, the (positive) dwRequestID
  2037. value if the function will be completed asynchronously, or a negative error
  2038. number if an error has occurred. Possible error returns are:
  2039. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  2040. LINEERR_INVALPOINTER - The specified pointer parameter is invalid.
  2041. LINEERR_INVALCALLSTATE - The current state of the call does not allow
  2042. the call to be dropped.
  2043. LINEERR_OPERATIONUNAVAIL - The specified operation is not available.
  2044. LINEERR_OPERATIONFAILED - The specified operation failed for
  2045. unspecified reasons.
  2046. --*/
  2047. {
  2048. PH323_CALL pCall = NULL;
  2049. // retrieve call pointer from handle
  2050. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2051. // invalid call handle
  2052. return LINEERR_INVALCALLHANDLE;
  2053. }
  2054. // save outgoing user user information (if specified)
  2055. if (!H323AddU2U(&pCall->OutgoingU2U,dwSize,(PBYTE)pUserUserInfo)) {
  2056. H323DBG((
  2057. DEBUG_LEVEL_ERROR,
  2058. "could not save user user info.\n"
  2059. ));
  2060. // release line device
  2061. H323UnlockLine(pCall->pLine);
  2062. // no memory available
  2063. return LINEERR_NOMEM;
  2064. }
  2065. // drop specified call
  2066. if (!H323PostDropCallMessage(pCall->hdCall,LINEDISCONNECTMODE_NORMAL)) {
  2067. // release line device
  2068. H323UnlockLine(pCall->pLine);
  2069. // could not drop call
  2070. return LINEERR_OPERATIONFAILED;
  2071. }
  2072. // complete the async accept operation now
  2073. (*g_pfnCompletionProc)(dwRequestID, NOERROR);
  2074. // release line device
  2075. H323UnlockLine(pCall->pLine);
  2076. // async success
  2077. return dwRequestID;
  2078. }
  2079. LONG
  2080. TSPIAPI
  2081. TSPI_lineGetCallAddressID(
  2082. HDRVCALL hdCall,
  2083. LPDWORD pdwAddressID
  2084. )
  2085. /*++
  2086. Routine Description:
  2087. This operation allows the TAPI DLL to retrieve the address ID for the
  2088. indicated call.
  2089. This operation must be executed synchronously by the Service Provider,
  2090. with presumed success. This operation may be called from within the
  2091. context of the ASYNC_LINE_COMPLETION or LINEEVENT callbacks (i.e., from
  2092. within an interrupt context). This function would typically be called
  2093. at the start of the call life cycle.
  2094. If the Service Provider models lines as "pools" of channel resources
  2095. and does "inverse multiplexing" of a call over several address IDs it
  2096. should consistently choose one of these address IDs as the primary
  2097. identifier reported by this function and in the LINE_CALLINFO data
  2098. structure.
  2099. Arguments:
  2100. hdCall - Specifies the Service Provider's opaque handle to the call
  2101. whose address ID is to be retrieved. Valid call states: any.
  2102. pdwAddressID - Specifies a far pointer to a DWORD into which the
  2103. Service Provider writes the call's address ID.
  2104. Return Values:
  2105. None.
  2106. --*/
  2107. {
  2108. // only one addr
  2109. *pdwAddressID = 0;
  2110. // success
  2111. return NOERROR;
  2112. }
  2113. LONG
  2114. TSPIAPI
  2115. TSPI_lineGetCallInfo(
  2116. HDRVCALL hdCall,
  2117. LPLINECALLINFO pCallInfo
  2118. )
  2119. /*++
  2120. Routine Description:
  2121. This operation enables the TAPI DLL to obtain fixed information about
  2122. the specified call.
  2123. A separate LINECALLINFO structure exists for every (inbound or outbound)
  2124. call. The structure contains primarily fixed information about the call.
  2125. An application would typically be interested in checking this information
  2126. when it receives its handle for a call via the LINE_CALLSTATE message, or
  2127. each time it receives notification via a LINE_CALLINFO message that parts
  2128. of the call information structure have changed. These messages supply the
  2129. handle for the call as a parameter.
  2130. If the Service Provider models lines as "pools" of channel resources and
  2131. does "inverse multiplexing" of a call over several address IDs it should
  2132. consistently choose one of these address IDs as the primary identifier
  2133. reported by this function in the LINE_CALLINFO data structure.
  2134. Arguments:
  2135. hdCall - Specifies the Service Provider's opaque handle to the call
  2136. whose call information is to be retrieved.
  2137. pCallInfo - Specifies a far pointer to a variable sized data structure
  2138. of type LINECALLINFO. Upon successful completion of the request, this
  2139. structure is filled with call related information.
  2140. Return Values:
  2141. Returns zero if the function is successful or a negative error
  2142. number if an error has occurred. Possible error returns are:
  2143. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  2144. LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure does
  2145. not specify enough memory to contain the fixed portion of the
  2146. structure. The dwNeededSize field has been set to the amount
  2147. required.
  2148. --*/
  2149. {
  2150. PH323_CALL pCall = NULL;
  2151. DWORD dwCalleeNameSize = 0;
  2152. DWORD dwCallerNameSize = 0;
  2153. DWORD dwCallerNumberSize = 0;
  2154. DWORD dwNextOffset = sizeof(LINECALLINFO);
  2155. DWORD dwU2USize = 0;
  2156. WCHAR IPAddress[20];
  2157. PBYTE pU2U = NULL;
  2158. // retrieve call pointer from handle
  2159. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2160. // invalid call handle
  2161. return LINEERR_INVALCALLHANDLE;
  2162. }
  2163. // see if user user info available
  2164. if (!IsListEmpty(&pCall->IncomingU2U)) {
  2165. PLIST_ENTRY pLE;
  2166. PH323_U2ULE pU2ULE;
  2167. // get first list entry
  2168. pLE = pCall->IncomingU2U.Flink;
  2169. // convert to user user structure
  2170. pU2ULE = CONTAINING_RECORD(pLE, H323_U2ULE, Link);
  2171. // transfer info
  2172. dwU2USize = pU2ULE->dwU2USize;
  2173. pU2U = pU2ULE->pU2U;
  2174. }
  2175. // initialize caller and callee id flags now
  2176. pCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
  2177. pCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
  2178. // calculate memory necessary for strings
  2179. dwCalleeNameSize = H323SizeOfWSZ(pCall->ccCalleeAlias.pData);
  2180. dwCallerNameSize = H323SizeOfWSZ(pCall->ccCallerAlias.pData);
  2181. // convert the IP address to string. It is in host order.
  2182. wsprintfW(IPAddress, L"%d.%d.%d.%d",
  2183. (pCall->ccCallerAddr.Addr.IP_Binary.dwAddr >> 24) & 0xff,
  2184. (pCall->ccCallerAddr.Addr.IP_Binary.dwAddr >> 16) & 0xff,
  2185. (pCall->ccCallerAddr.Addr.IP_Binary.dwAddr >> 8) & 0xff,
  2186. (pCall->ccCallerAddr.Addr.IP_Binary.dwAddr) & 0xff
  2187. );
  2188. dwCallerNumberSize = H323SizeOfWSZ(IPAddress);
  2189. // determine number of bytes needed
  2190. pCallInfo->dwNeededSize = sizeof(LINECALLINFO) +
  2191. dwCalleeNameSize +
  2192. dwCallerNameSize +
  2193. dwCallerNumberSize +
  2194. dwU2USize
  2195. ;
  2196. // see if structure size is large enough
  2197. if (pCallInfo->dwTotalSize >= pCallInfo->dwNeededSize) {
  2198. // record number of bytes used
  2199. pCallInfo->dwUsedSize = pCallInfo->dwNeededSize;
  2200. // validate string size
  2201. if (dwCalleeNameSize > 0) {
  2202. // callee name was specified
  2203. pCallInfo->dwCalledIDFlags = LINECALLPARTYID_NAME;
  2204. // determine size and offset for callee name
  2205. pCallInfo->dwCalledIDNameSize = dwCalleeNameSize;
  2206. pCallInfo->dwCalledIDNameOffset = dwNextOffset;
  2207. // copy call info after fixed portion
  2208. memcpy((LPBYTE)pCallInfo + pCallInfo->dwCalledIDNameOffset,
  2209. (LPBYTE)pCall->ccCalleeAlias.pData,
  2210. pCallInfo->dwCalledIDNameSize
  2211. );
  2212. // adjust offset to include string
  2213. dwNextOffset += pCallInfo->dwCalledIDNameSize;
  2214. }
  2215. // validate string size
  2216. if (dwCallerNameSize > 0) {
  2217. // caller name was specified
  2218. pCallInfo->dwCallerIDFlags = LINECALLPARTYID_NAME;
  2219. // determine size and offset for caller name
  2220. pCallInfo->dwCallerIDNameSize = dwCallerNameSize;
  2221. pCallInfo->dwCallerIDNameOffset = dwNextOffset;
  2222. // copy call info after fixed portion
  2223. memcpy((LPBYTE)pCallInfo + pCallInfo->dwCallerIDNameOffset,
  2224. (LPBYTE)pCall->ccCallerAlias.pData,
  2225. pCallInfo->dwCallerIDNameSize
  2226. );
  2227. // adjust offset to include string
  2228. dwNextOffset += pCallInfo->dwCallerIDNameSize;
  2229. }
  2230. // validate string size
  2231. if (dwCallerNumberSize > 0) {
  2232. // caller name was specified
  2233. pCallInfo->dwCallerIDFlags |= LINECALLPARTYID_ADDRESS;
  2234. // determine size and offset for caller name
  2235. pCallInfo->dwCallerIDSize = dwCallerNumberSize;
  2236. pCallInfo->dwCallerIDOffset = dwNextOffset;
  2237. // copy call info after fixed portion
  2238. memcpy((LPBYTE)pCallInfo + pCallInfo->dwCallerIDOffset,
  2239. (LPBYTE)IPAddress,
  2240. pCallInfo->dwCallerIDSize
  2241. );
  2242. // adjust offset to include string
  2243. dwNextOffset += pCallInfo->dwCallerIDSize;
  2244. }
  2245. // validate buffer
  2246. if (dwU2USize > 0) {
  2247. // determine size and offset of info
  2248. pCallInfo->dwUserUserInfoSize = dwU2USize;
  2249. pCallInfo->dwUserUserInfoOffset = dwNextOffset;
  2250. // copy user user info after fixed portion
  2251. memcpy((LPBYTE)pCallInfo + pCallInfo->dwUserUserInfoOffset,
  2252. (LPBYTE)pU2U,
  2253. pCallInfo->dwUserUserInfoSize
  2254. );
  2255. // adjust offset to include string
  2256. dwNextOffset += pCallInfo->dwUserUserInfoSize;
  2257. }
  2258. } else if (pCallInfo->dwTotalSize >= sizeof(LINECALLINFO)) {
  2259. H323DBG((
  2260. DEBUG_LEVEL_WARNING,
  2261. "linecallinfo structure too small for strings.\n"
  2262. ));
  2263. // structure only contains fixed portion
  2264. pCallInfo->dwUsedSize = sizeof(LINECALLINFO);
  2265. } else {
  2266. H323DBG((
  2267. DEBUG_LEVEL_WARNING,
  2268. "linecallinfo structure too small.\n"
  2269. ));
  2270. // release line device
  2271. H323UnlockLine(pCall->pLine);
  2272. // structure is too small
  2273. return LINEERR_STRUCTURETOOSMALL;
  2274. }
  2275. // initialize call line device and address info
  2276. pCallInfo->dwLineDeviceID = pCall->pLine->dwDeviceID;
  2277. pCallInfo->dwAddressID = 0;
  2278. // initialize variable call parameters
  2279. pCallInfo->dwOrigin = pCall->dwOrigin;
  2280. pCallInfo->dwMediaMode = pCall->dwIncomingModes | pCall->dwOutgoingModes;
  2281. pCallInfo->dwReason = H323IsCallInbound(pCall)
  2282. ? LINECALLREASON_UNAVAIL
  2283. : LINECALLREASON_DIRECT
  2284. ;
  2285. pCallInfo->dwCallStates = H323IsCallInbound(pCall)
  2286. ? H323_CALL_INBOUNDSTATES
  2287. : H323_CALL_OUTBOUNDSTATES
  2288. ;
  2289. // initialize constant call parameters
  2290. pCallInfo->dwBearerMode = H323_LINE_BEARERMODES;
  2291. pCallInfo->dwRate = H323_LINE_MAXRATE;
  2292. // initialize unsupported call capabilities
  2293. pCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
  2294. pCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
  2295. pCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
  2296. //pass on the dwAppSpecific info
  2297. pCallInfo->dwAppSpecific = pCall->dwAppSpecific;
  2298. // release line device
  2299. H323UnlockLine(pCall->pLine);
  2300. // success
  2301. return NOERROR;
  2302. }
  2303. /*++
  2304. Parameters
  2305. hdCall - The handle to the call whose application-specific field is to be
  2306. set. The call state of hdCall can be any state.
  2307. dwAppSpecific - The new content of the dwAppSpecific member for the call's
  2308. LINECALLINFO structure. This value is uninterpreted by the service
  2309. provider. This parameter is not validated by TAPI when this function is called.
  2310. Return Values
  2311. Returns zero if the function succeeds, or an error number if an error
  2312. occurs. Possible return values are as follows:
  2313. LINEERR_INVALCALLHANDLE,
  2314. LINEERR_OPERATIONFAILED,
  2315. LINEERR_NOMEM,
  2316. LINEERR_RESOURCEUNAVAIL,
  2317. LINEERR_OPERATIONUNAVAIL.
  2318. Routine Description:
  2319. The application-specific field in the LINECALLINFO data structure that
  2320. exists for each call is uninterpreted by the Telephony API or any of its
  2321. service providers. Its usage is entirely defined by the applications. The
  2322. field can be read from the LINECALLINFO record returned by
  2323. TSPI_lineGetCallInfo. However, TSPI_lineSetAppSpecific must be used to set
  2324. the field so that changes become visible to other applications. When this
  2325. field is changed, the service provider sends a LINE_CALLINFO message with
  2326. an indication that the AppSpecific field has changed.
  2327. ++*/
  2328. LONG
  2329. TSPIAPI
  2330. TSPI_lineSetAppSpecific(
  2331. HDRVCALL hdCall,
  2332. DWORD dwAppSpecific
  2333. )
  2334. {
  2335. PH323_CALL pCall = NULL;
  2336. // retrieve call pointer from handle
  2337. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2338. // invalid call handle
  2339. return LINEERR_INVALCALLHANDLE;
  2340. }
  2341. pCall->dwAppSpecific = dwAppSpecific;
  2342. (*g_pfnLineEventProc)(
  2343. pCall->pLine->htLine,
  2344. pCall->htCall,
  2345. LINE_CALLINFO,
  2346. LINECALLINFOSTATE_APPSPECIFIC,
  2347. 0,
  2348. 0
  2349. );
  2350. // release line device
  2351. H323UnlockLine( pCall->pLine );
  2352. // success
  2353. return ERROR_SUCCESS;
  2354. }
  2355. LONG
  2356. TSPIAPI
  2357. TSPI_lineGetCallStatus(
  2358. HDRVCALL hdCall,
  2359. LPLINECALLSTATUS pCallStatus
  2360. )
  2361. /*++
  2362. Routine Description:
  2363. This operation returns the current status of the specified call.
  2364. TSPI_lineCallStatus returns the dynamic status of a call, whereas
  2365. TSPI_lineGetCallInfo returns primarily static information about a call.
  2366. Call status information includes the current call state, detailed mode
  2367. information related to the call while in this state (if any), as well
  2368. as a list of the available TSPI functions the TAPI DLL can invoke on the
  2369. call while the call is in this state. An application would typically be
  2370. interested in requesting this information when it receives notification
  2371. about a call state change via the LINE_CALLSTATE message.
  2372. Arguments:
  2373. hdCall - Specifies the Service Provider's opaque handle to the call
  2374. to be queried for its status. Valid call states: any.
  2375. pCallStatus - Specifies a far pointer to a variable sized data structure
  2376. of type LINECALLSTATUS. Upon successful completion of the request,
  2377. this structure is filled with call status information.
  2378. Return Values:
  2379. Returns zero if the function is successful or a negative error
  2380. number if an error has occurred. Possible error returns are:
  2381. LINEERR_INVALCALLHANDLE - The specified call handle is invalid.
  2382. LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure does
  2383. not specify enough memory to contain the fixed portion of the
  2384. structure. The dwNeededSize field has been set to the amount
  2385. required.
  2386. --*/
  2387. {
  2388. PH323_CALL pCall = NULL;
  2389. // retrieve call pointer from handle
  2390. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2391. // invalid call handle
  2392. return LINEERR_INVALCALLHANDLE;
  2393. }
  2394. // determine number of bytes needed
  2395. pCallStatus->dwNeededSize = sizeof(LINECALLSTATUS);
  2396. // see if structure size is large enough
  2397. if (pCallStatus->dwTotalSize < pCallStatus->dwNeededSize) {
  2398. H323DBG((
  2399. DEBUG_LEVEL_ERROR,
  2400. "linecallstatus structure too small.\n"
  2401. ));
  2402. // release line device
  2403. H323UnlockLine(pCall->pLine);
  2404. // allocated structure too small
  2405. return LINEERR_STRUCTURETOOSMALL;
  2406. }
  2407. // record amount of memory used
  2408. pCallStatus->dwUsedSize = pCallStatus->dwNeededSize;
  2409. // transer call state information
  2410. pCallStatus->dwCallState = pCall->dwCallState;
  2411. pCallStatus->dwCallStateMode = pCall->dwCallStateMode;
  2412. // determine call feature based on state
  2413. pCallStatus->dwCallFeatures = H323GetCallFeatures(pCall);
  2414. // release line device
  2415. H323UnlockLine(pCall->pLine);
  2416. // success
  2417. return NOERROR;
  2418. }
  2419. LONG
  2420. TSPIAPI
  2421. TSPI_lineMakeCall(
  2422. DRV_REQUESTID dwRequestID,
  2423. HDRVLINE hdLine,
  2424. HTAPICALL htCall,
  2425. LPHDRVCALL phdCall,
  2426. LPCWSTR pwszDialableAddr,
  2427. DWORD dwCountryCode,
  2428. LPLINECALLPARAMS const pCallParams
  2429. )
  2430. /*++
  2431. Routine Description:
  2432. This function places a call on the specified line to the specified
  2433. destination address, exchanging opaque handles for the new call
  2434. between the TAPI DLL and Service Provider. Optionally, call parameters
  2435. can be specified if anything but default call setup parameters are
  2436. requested.
  2437. After dialing has completed, several LINE_CALLSTATE messages will
  2438. typically be sent to the TAPI DLL to notify it about the progress of the
  2439. call. No generally valid sequence of call state transitions is specified
  2440. as no single fixed sequence of transitions can be guaranteed in practice.
  2441. A typical sequence may cause a call to transition from dialtone, dialing,
  2442. proceeding, ringback, to connected. With non-dialed lines, the call may
  2443. typically transition directly to connected state.
  2444. The TAPI DLL has the option to specify an originating address on the
  2445. specified line device. A service provider that models all stations on a
  2446. switch as addresses on a single line device allows the TAPI DLL to
  2447. originate calls from any of these stations using TSPI_lineMakeCall.
  2448. The call parameters allow the TAPI DLL to make non voice calls or request
  2449. special call setup options that are not available by default.
  2450. The TAPI DLL can partially dial using TSPI_lineMakeCall and continue
  2451. dialing using TSPI_lineDial. To abandon a call attempt, use TSPI_lineDrop.
  2452. The Service Provider initially does media monitoring on the new call for
  2453. at least the set of media modes that were monitored for on the line.
  2454. Arguments:
  2455. dwRequestID - Specifies the identifier of the asynchronous request.
  2456. The Service Provider returns this value if the function completes
  2457. asynchronously.
  2458. hdLine - Specifies the Service Provider's opaque handle to the line on
  2459. which the new call is to be originated.
  2460. htCall - Specifies the TAPI DLL's opaque handle to the new call. The
  2461. Service Provider must save this and use it in all subsequent calls to
  2462. the LINEEVENT procedure reporting events on the call.
  2463. phdCall - Specifies a far pointer to an opaque HDRVCALL representing the
  2464. Service Provider's identifier for the call. The Service Provider must
  2465. fill this location with its opaque handle for the call before this
  2466. procedure returns, whether it decides to execute the request
  2467. sychronously or asynchronously. This handle is invalid if the function
  2468. results in an error (either synchronously or asynchronously).
  2469. pwszDialableAddr - Specifies a far pointer to the destination address. This
  2470. follows the standard dialable number format. This pointer may be
  2471. specified as NULL for non-dialed addresses (i.e., a hot phone) or when
  2472. all dialing will be performed using TSPI_lineDial. In the latter case,
  2473. TSPI_lineMakeCall will allocate an available call appearance which
  2474. would typically remain in the dialtone state until dialing begins.
  2475. Service providers that have inverse multiplexing capabilities may allow
  2476. an application to specify multiple addresses at once.
  2477. dwCountryCode - Specifies the country code of the called party. If a value
  2478. of zero is specified, then a default will be used by the
  2479. implementation.
  2480. pCallParams - Specifies a far pointer to a LINECALLPARAMS structure. This
  2481. structure allows the TAPI DLL to specify how it wants the call to be
  2482. set up. If NULL is specified, then a default 3.1kHz voice call is
  2483. established, and an arbitrary origination address on the line is
  2484. selected. This structure allows the TAPI DLL to select such elements
  2485. as the call's bearer mode, data rate, expected media mode, origination
  2486. address, blocking of caller ID information, dialing parameters, etc.
  2487. Return Values:
  2488. Returns zero if the function is successful, the (positive) dwRequestID
  2489. value if the function will be completed asynchronously, or a negative error
  2490. number if an error has occurred. Possible error returns are:
  2491. LINEERR_CALLUNAVAIL - All call appearances on the specified address are
  2492. currently in use.
  2493. LINEERR_INVALADDRESSID - The specified address ID is out of range.
  2494. LINEERR_INVALADDRESSMODE - The address mode is invalid.
  2495. LINEERR_INVALBEARERMODE - The bearer mode is invalid.
  2496. LINEERR_INVALCALLPARAMS - The specified call parameter structure is
  2497. invalid.
  2498. LINEERR_INVALLINEHANDLE - The specified line handle is invalid.
  2499. LINEERR_INVALLINESTATE - The line is currently not in a state in
  2500. which this operation can be performed.
  2501. LINEERR_INVALMEDIAMODE - One or more media modes specified as a
  2502. parameter or in a list is invalid or not supported by the the
  2503. service provider.
  2504. LINEERR_OPERATIONFAILED - The operation failed for unspecified reasons.
  2505. LINEERR_RESOURCEUNAVAIL - The specified operation cannot be completed
  2506. because of resource overcommitment.
  2507. --*/
  2508. {
  2509. PH323_CALL pCall = NULL;
  2510. PH323_LINE pLine = NULL;
  2511. DWORD dwStatus = dwRequestID;
  2512. UNREFERENCED_PARAMETER(dwCountryCode);
  2513. // retrieve line device pointer from handle
  2514. if (!H323GetLineAndLock(&pLine, hdLine)) {
  2515. // invalid line device handle
  2516. return LINEERR_INVALLINEHANDLE;
  2517. }
  2518. // validate line state
  2519. if (!H323IsLineOpen(pLine)) {
  2520. H323DBG((
  2521. DEBUG_LEVEL_ERROR,
  2522. "line %d is not currently opened.\n",
  2523. pLine->dwDeviceID
  2524. ));
  2525. // release line device
  2526. H323UnlockLine(pLine);
  2527. // line needs to be opened
  2528. return LINEERR_INVALLINESTATE;
  2529. }
  2530. // see if line is available
  2531. if (!H323IsLineAvailable(pLine)) {
  2532. H323DBG((
  2533. DEBUG_LEVEL_ERROR,
  2534. "line %d is currently at maximum capacity.\n",
  2535. pLine->dwDeviceID
  2536. ));
  2537. // release line device
  2538. H323UnlockLine(pLine);
  2539. // line is currenty maxed
  2540. return LINEERR_RESOURCEUNAVAIL;
  2541. }
  2542. // allocate outgoing call from line call table
  2543. if (!H323AllocCallFromTable(&pCall,&pLine->pCallTable,pLine)) {
  2544. H323DBG((
  2545. DEBUG_LEVEL_ERROR,
  2546. "could not allocate outgoing call.\n"
  2547. ));
  2548. // release line device
  2549. H323UnlockLine(pLine);
  2550. // no memory available
  2551. return LINEERR_NOMEM;
  2552. }
  2553. // save tapi handle
  2554. pCall->htCall = htCall;
  2555. // save back pointer
  2556. pCall->pLine = pLine;
  2557. // specify outgoing call direction
  2558. pCall->dwOrigin = LINECALLORIGIN_OUTBOUND;
  2559. // validate call parameters
  2560. if (!H323ValidateCallParams(
  2561. pCall,
  2562. pCallParams,
  2563. pwszDialableAddr,
  2564. &dwStatus)) {
  2565. // failure
  2566. goto cleanup;
  2567. }
  2568. // bind outgoing call
  2569. if (!H323BindCall(pCall,NULL)) {
  2570. H323DBG((
  2571. DEBUG_LEVEL_ERROR,
  2572. "could not bind call.\n"
  2573. ));
  2574. // no memory available
  2575. dwStatus = LINEERR_NOMEM;
  2576. // failure
  2577. goto cleanup;
  2578. }
  2579. // post place request to callback thread
  2580. if (!H323PostPlaceCallMessage(pCall->hdCall)) {
  2581. H323DBG((
  2582. DEBUG_LEVEL_ERROR,
  2583. "could not post place call message.\n"
  2584. ));
  2585. // could not complete operation
  2586. dwStatus = LINEERR_OPERATIONFAILED;
  2587. // failure
  2588. goto cleanup;
  2589. }
  2590. // complete the async accept operation now
  2591. (*g_pfnCompletionProc)(dwRequestID, NOERROR);
  2592. // change call state to accepted from offering
  2593. H323ChangeCallState(pCall, LINECALLSTATE_DIALING, 0);
  2594. // transfer handle
  2595. *phdCall = pCall->hdCall;
  2596. // release line device
  2597. H323UnlockLine(pLine);
  2598. // success
  2599. return dwStatus;
  2600. cleanup:
  2601. // unbind call
  2602. H323UnbindCall(pCall);
  2603. // release outgoing call from line call table
  2604. H323FreeCallFromTable(pCall,pLine->pCallTable);
  2605. // release line device
  2606. H323UnlockLine(pLine);
  2607. // failure
  2608. return dwStatus;
  2609. }
  2610. LONG
  2611. TSPIAPI
  2612. TSPI_lineReleaseUserUserInfo(
  2613. DRV_REQUESTID dwRequestID,
  2614. HDRVCALL hdCall
  2615. )
  2616. {
  2617. PLIST_ENTRY pLE;
  2618. PH323_U2ULE pU2ULE;
  2619. PH323_CALL pCall = NULL;
  2620. // retrieve call pointer from handle
  2621. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2622. // invalid call handle
  2623. return LINEERR_INVALCALLHANDLE;
  2624. }
  2625. // see if list is empty
  2626. if (!IsListEmpty(&pCall->IncomingU2U)) {
  2627. // remove first entry from list
  2628. pLE = RemoveHeadList(&pCall->IncomingU2U);
  2629. // convert to user user structure
  2630. pU2ULE = CONTAINING_RECORD(pLE, H323_U2ULE, Link);
  2631. // release memory
  2632. H323HeapFree(pU2ULE);
  2633. }
  2634. // see if list contains pending data
  2635. if (!IsListEmpty(&pCall->IncomingU2U)) {
  2636. H323DBG((
  2637. DEBUG_LEVEL_VERBOSE,
  2638. "more user user info available.\n"
  2639. ));
  2640. // signal incoming
  2641. (*g_pfnLineEventProc)(
  2642. pCall->pLine->htLine,
  2643. pCall->htCall,
  2644. LINE_CALLINFO,
  2645. LINECALLINFOSTATE_USERUSERINFO,
  2646. 0,
  2647. 0
  2648. );
  2649. }
  2650. // complete the async accept operation now
  2651. (*g_pfnCompletionProc)(dwRequestID, NOERROR);
  2652. // release line device
  2653. H323UnlockLine(pCall->pLine);
  2654. // async success
  2655. return dwRequestID;
  2656. }
  2657. LONG
  2658. TSPIAPI
  2659. TSPI_lineSendUserUserInfo(
  2660. DRV_REQUESTID dwRequestID,
  2661. HDRVCALL hdCall,
  2662. LPCSTR pUserUserInfo,
  2663. DWORD dwSize
  2664. )
  2665. {
  2666. HRESULT hr;
  2667. PH323_CALL pCall = NULL;
  2668. CC_NONSTANDARDDATA NonStandardData;
  2669. PCC_NONSTANDARDDATA pNonStandardData = NULL;
  2670. // retrieve call pointer from handle
  2671. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2672. // invalid call handle
  2673. return LINEERR_INVALCALLHANDLE;
  2674. }
  2675. // check for user user info
  2676. if (pUserUserInfo != NULL) {
  2677. // transfer header information
  2678. NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
  2679. NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
  2680. NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
  2681. // initialize octet string containing data
  2682. NonStandardData.sData.wOctetStringLength = LOWORD(dwSize);
  2683. NonStandardData.sData.pOctetString = (PBYTE)pUserUserInfo;
  2684. // point to stack based structure
  2685. pNonStandardData = &NonStandardData;
  2686. }
  2687. // send user user data
  2688. hr = CC_SendNonStandardMessage(
  2689. pCall->hccCall,
  2690. CC_H245_MESSAGE_COMMAND,
  2691. pNonStandardData
  2692. );
  2693. // validate status
  2694. if (hr != CC_OK) {
  2695. H323DBG((
  2696. DEBUG_LEVEL_ERROR,
  2697. "error %s (0x%08lx) sending non-standard message.\n",
  2698. H323StatusToString((DWORD)hr), hr
  2699. ));
  2700. // release line device
  2701. H323UnlockLine(pCall->pLine);
  2702. // unable to answer call
  2703. return LINEERR_OPERATIONFAILED;
  2704. }
  2705. // complete the async accept operation now
  2706. (*g_pfnCompletionProc)(dwRequestID, NOERROR);
  2707. // release line device
  2708. H323UnlockLine(pCall->pLine);
  2709. // async success
  2710. return dwRequestID;
  2711. }
  2712. LONG
  2713. TSPIAPI
  2714. TSPI_lineMonitorDigits(
  2715. HDRVCALL hdCall,
  2716. DWORD dwDigitModes
  2717. )
  2718. {
  2719. PH323_CALL pCall = NULL;
  2720. // retrieve call pointer from handle
  2721. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2722. // invalid call handle
  2723. return LINEERR_INVALCALLHANDLE;
  2724. }
  2725. // see if mode empty
  2726. if (dwDigitModes == 0) {
  2727. H323DBG((
  2728. DEBUG_LEVEL_VERBOSE,
  2729. "disabling dtmf detection.\n"
  2730. ));
  2731. // enable monitoring digits
  2732. pCall->fMonitoringDigits = FALSE;
  2733. // release line device
  2734. H323UnlockLine(pCall->pLine);
  2735. // success
  2736. return NOERROR;
  2737. } else if (dwDigitModes != LINEDIGITMODE_DTMF) {
  2738. H323DBG((
  2739. DEBUG_LEVEL_ERROR,
  2740. "invalid digit modes 0x%08lx.\n",
  2741. dwDigitModes
  2742. ));
  2743. // release line device
  2744. H323UnlockLine(pCall->pLine);
  2745. // invalid call handle
  2746. return LINEERR_INVALDIGITMODE;
  2747. }
  2748. H323DBG((
  2749. DEBUG_LEVEL_VERBOSE,
  2750. "enabling dtmf detection.\n"
  2751. ));
  2752. // enable monitoring digits
  2753. pCall->fMonitoringDigits = TRUE;
  2754. // release line device
  2755. H323UnlockLine(pCall->pLine);
  2756. // success
  2757. return NOERROR;
  2758. }
  2759. LONG
  2760. TSPIAPI
  2761. TSPI_lineGenerateDigits(
  2762. HDRVCALL hdCall,
  2763. DWORD dwEndToEndID,
  2764. DWORD dwDigitMode,
  2765. LPCWSTR pwszDigits,
  2766. DWORD dwDuration
  2767. )
  2768. {
  2769. HRESULT hr;
  2770. PH323_CALL pCall = NULL;
  2771. UNREFERENCED_PARAMETER(dwDuration);
  2772. // retrieve call pointer from handle
  2773. if (!H323GetCallAndLock(&pCall, hdCall)) {
  2774. // invalid call handle
  2775. return LINEERR_INVALCALLHANDLE;
  2776. }
  2777. // verify that the call was connected
  2778. if (!H323IsCallConnected(pCall)) {
  2779. H323DBG((
  2780. DEBUG_LEVEL_ERROR,
  2781. "call 0x%08lx not connected.\n",
  2782. pCall
  2783. ));
  2784. // release line device
  2785. H323UnlockLine(pCall->pLine);
  2786. return LINEERR_INVALCALLSTATE;
  2787. }
  2788. // verify monitor modes
  2789. if (dwDigitMode != LINEDIGITMODE_DTMF) {
  2790. H323DBG((
  2791. DEBUG_LEVEL_ERROR,
  2792. "invalid digit mode 0x%08lx.\n",
  2793. dwDigitMode
  2794. ));
  2795. // release line device
  2796. H323UnlockLine(pCall->pLine);
  2797. // invalid call handle
  2798. return LINEERR_INVALDIGITMODE;
  2799. }
  2800. H323DBG((
  2801. DEBUG_LEVEL_VERBOSE,
  2802. "sending user input %S.\n",
  2803. pwszDigits
  2804. ));
  2805. // send user input message
  2806. hr = CC_UserInput(pCall->hccCall, (PWSTR)pwszDigits);
  2807. // validate
  2808. if (hr != CC_OK) {
  2809. H323DBG((
  2810. DEBUG_LEVEL_ERROR,
  2811. "error 0x%08lx sending user input message.\n",
  2812. hr
  2813. ));
  2814. // signal completion
  2815. (*g_pfnLineEventProc)(
  2816. pCall->pLine->htLine,
  2817. pCall->htCall,
  2818. LINE_GENERATE,
  2819. LINEGENERATETERM_CANCEL,
  2820. dwEndToEndID,
  2821. GetTickCount()
  2822. );
  2823. // release line device
  2824. H323UnlockLine(pCall->pLine);
  2825. // failure
  2826. return LINEERR_INVALDIGITS;
  2827. }
  2828. // signal completion
  2829. (*g_pfnLineEventProc)(
  2830. pCall->pLine->htLine,
  2831. pCall->htCall,
  2832. LINE_GENERATE,
  2833. LINEGENERATETERM_DONE,
  2834. dwEndToEndID,
  2835. GetTickCount()
  2836. );
  2837. // release line device
  2838. H323UnlockLine(pCall->pLine);
  2839. // success
  2840. return NOERROR;
  2841. }