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

1358 lines
41 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dial.c
  6. * Content: Wrappers for TAPI routines
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 6/10/96 kipo created it
  12. * 6/22/96 kipo close com port when disconnected; allow checking for
  13. * valid TAPI lines during NewComPort().
  14. * 7/08/96 kipo added support for new dialogs
  15. * 8/10/96 kipo added support for dialing location
  16. * 1/06/97 kipo updated for objects
  17. * 1/24/97 kipo bug #5400: Compaq Presario was overwriting the dev caps
  18. * buffer, causing a crash. Fixed to allocated a larger
  19. * buffer with some slop as a workaround.
  20. * 3/04/97 kipo close com port handle when deallocating call; use string
  21. * table for modem strings; updated debug output.
  22. * 3/24/97 kipo added support for specifying which modem to use
  23. * 4/08/97 kipo added support for separate modem and serial baud rates
  24. * 5/07/97 kipo added support for modem choice list
  25. * 5/23/97 kipo added support return status codes
  26. * 4/21/98 a-peterz #22920 Handle LINE_CLOSE message
  27. * 5/07/98 a-peterz #15251 Track call errors in DPDIAL
  28. * 10/13/99 johnkan #413516 - Mismatch between modem dialog selection and TAPI device ID
  29. * 12/22/00 aarono #190380 - use process heap for memory allocation
  30. *@@END_MSINTERNAL
  31. ***************************************************************************/
  32. #include <windows.h>
  33. #include <windowsx.h>
  34. #include "dputils.h"
  35. #include "macros.h"
  36. #include "dial.h"
  37. void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
  38. DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3);
  39. void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  40. void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  41. void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
  42. void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege);
  43. void ProcessReplyMessage(LPDPDIAL globals, DWORD asyncID, LINERESULT lResult);
  44. LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet);
  45. LINERESULT dialGetCommHandle(LPDPDIAL globals);
  46. LINERESULT dialCloseCommHandle(LPDPDIAL globals);
  47. LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
  48. LPCSTR lpszDialAddress,
  49. LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet);
  50. LPSTR GetLineErrStr(LONG err);
  51. LPSTR GetCallStateStr(DWORD callState);
  52. LPSTR GetLineMsgStr(DWORD msg);
  53. #ifdef DEBUG
  54. extern LONG lineError(LONG err, LPSTR modName, DWORD lineNum);
  55. #define LINEERROR(err) (lineError(err, DPF_MODNAME, __LINE__))
  56. #else
  57. #define LINEERROR(err) (err)
  58. #endif
  59. /* dial initialize */
  60. #undef DPF_MODNAME
  61. #define DPF_MODNAME "dialInitialize"
  62. LINERESULT dialInitialize(HINSTANCE hInst, LPTSTR szAppName,
  63. LPDPCOMPORT lpComPort, LPDPDIAL *storage)
  64. {
  65. LPDPDIAL globals;
  66. LINERESULT lResult; /* Stores return code from TAPI calls */
  67. // create globals
  68. globals =(LPDPDIAL) SP_MemAlloc(sizeof(DPDIAL));
  69. FAILWITHACTION(globals == NULL, lResult = LINEERR_NOMEM, Failure);
  70. DPF(3, "lineInitialize");
  71. DPF(3, "> hInstance: %08X", hInst);
  72. DPF(3, "> szAppName: %s", szAppName);
  73. // init the line
  74. lResult = lineInitialize(&globals->hLineApp,
  75. hInst,
  76. LineCallBackProc,
  77. szAppName,
  78. &globals->dwNumLines);
  79. FAILIF(LINEERROR(lResult), Failure);
  80. DPF(3, "< hLineApp: %08X", globals->hLineApp);
  81. DPF(3, "< dwNumLines: %d", globals->dwNumLines);
  82. // no lines available
  83. FAILWITHACTION(globals->dwNumLines == 0, lResult = LINEERR_NODEVICE, Failure);
  84. // store pointer to com port object
  85. globals->lpComPort = lpComPort;
  86. *storage = globals;
  87. return (SUCCESS);
  88. Failure:
  89. dialShutdown(globals);
  90. return (lResult);
  91. }
  92. /* dial shutdown */
  93. #undef DPF_MODNAME
  94. #define DPF_MODNAME "dialShutdown"
  95. LINERESULT dialShutdown(LPDPDIAL globals)
  96. {
  97. LINERESULT lResult;
  98. if (globals == NULL)
  99. return (SUCCESS);
  100. if (globals->hLineApp)
  101. {
  102. dialDropCall(globals);
  103. dialDeallocCall(globals);
  104. dialLineClose(globals);
  105. DPF(3, "lineShutdown");
  106. DPF(3, "> hLineApp: %08X", globals->hLineApp);
  107. lResult = lineShutdown(globals->hLineApp);
  108. LINEERROR(lResult);
  109. }
  110. SP_MemFree(globals);
  111. return (SUCCESS);
  112. }
  113. /* dialLineOpen - wrapper for lineOpen */
  114. #undef DPF_MODNAME
  115. #define DPF_MODNAME "dialLineOpen"
  116. LINERESULT dialLineOpen(LPDPDIAL globals, DWORD dwLine)
  117. {
  118. LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
  119. LPLINEDEVCAPS lpLineDevCaps = NULL;
  120. LINERESULT lResult;
  121. // fail if line is already open
  122. FAILWITHACTION(globals->hLine != 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  123. /* negotiate API version for each line */
  124. lResult = lineNegotiateAPIVersion(globals->hLineApp, dwLine,
  125. TAPIVERSION, TAPIVERSION,
  126. &globals->dwAPIVersion, &lineExtensionID);
  127. FAILIF(LINEERROR(lResult), Failure);
  128. lResult = dialGetDevCaps(globals, dwLine, globals->dwAPIVersion, &lpLineDevCaps);
  129. FAILIF(LINEERROR(lResult), Failure);
  130. /* check for supported media mode. If not datamodem, continue to next line */
  131. FAILWITHACTION(!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM),
  132. lResult = LINEERR_NODEVICE, Failure);
  133. DPF(3, "lineOpen");
  134. DPF(3, "> hLineApp: %08X", globals->hLineApp);
  135. DPF(3, "> dwDeviceID: %d", dwLine);
  136. // reset error tracking
  137. globals->dwCallError = CALL_OK;
  138. /* open the line that supports data modems */
  139. lResult = lineOpen( globals->hLineApp, dwLine, &globals->hLine,
  140. globals->dwAPIVersion, 0L,
  141. (DWORD_PTR) globals,
  142. LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM,
  143. NULL);
  144. FAILIF(LINEERROR(lResult), Failure);
  145. DPF(3, "< hLine: %08X", globals->hLine);
  146. /* if we are here then we found a compatible line */
  147. globals->dwLineID = dwLine;
  148. globals->dwCallState = LINECALLSTATE_IDLE; // line is now idle and ready to make/receive calls
  149. lResult = SUCCESS;
  150. Failure:
  151. if (lpLineDevCaps)
  152. SP_MemFree(lpLineDevCaps);
  153. return (lResult);
  154. }
  155. /* dialLineClose - wrapper for lineClose */
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "dialLineClose"
  158. LINERESULT dialLineClose(LPDPDIAL globals)
  159. {
  160. LINERESULT lResult;
  161. // fail if line is already closed
  162. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  163. DPF(3, "lineClose");
  164. DPF(3, "> hLine: %08X", globals->hLine);
  165. lResult = lineClose(globals->hLine);
  166. LINEERROR(lResult);
  167. globals->hLine = 0;
  168. Failure:
  169. return (lResult);
  170. }
  171. /* dialMakeCall - wrapper for lineMakeCall */
  172. #undef DPF_MODNAME
  173. #define DPF_MODNAME "dialMakeCall"
  174. LINERESULT dialMakeCall(LPDPDIAL globals, LPTSTR szDestination)
  175. {
  176. LINECALLPARAMS callparams;
  177. LINERESULT lResult;
  178. // fail if line not open or if call is already open
  179. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  180. FAILWITHACTION(globals->hCall != 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  181. // set call parameters
  182. ZeroMemory(&callparams, sizeof(LINECALLPARAMS));
  183. callparams.dwBearerMode = LINEBEARERMODE_VOICE;
  184. callparams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  185. callparams.dwTotalSize = sizeof(LINECALLPARAMS);
  186. DPF(3, "lineMakeCall");
  187. DPF(3, "> hLine: %08X", globals->hLine);
  188. DPF(3, "> szDestAddr: \"%s\"", szDestination);
  189. lResult = lineMakeCall(globals->hLine, &globals->hCall, szDestination, 0, &callparams);
  190. // lResult will be > 0 if call is asynchronous
  191. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  192. FAILMSG(lResult == 0);
  193. DPF(3, "< hCall: %08X", globals->hCall);
  194. DPF(3, "< dwAsyncID: %d", lResult);
  195. globals->dwAsyncID = lResult; // store async ID
  196. lResult = SUCCESS;
  197. Failure:
  198. return (lResult);
  199. }
  200. /* dialDropCall - wrapper for lineDrop */
  201. #undef DPF_MODNAME
  202. #define DPF_MODNAME "dialDropCall"
  203. LINERESULT dialDropCall(LPDPDIAL globals)
  204. {
  205. MSG msg;
  206. DWORD dwStopTicks;
  207. LINERESULT lResult;
  208. // fail if line not open or if call not open
  209. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  210. FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  211. DPF(3, "lineDrop");
  212. DPF(3, "> hCall: %08X", globals->hCall);
  213. lResult = lineDrop(globals->hCall, NULL, 0);
  214. // lResult will be > 0 if call is asynchronous
  215. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  216. FAILMSG(lResult == 0);
  217. DPF(3, "< dwAsyncID: %d", lResult);
  218. globals->dwAsyncID = lResult; // store async ID
  219. // wait for call to get dropped
  220. dwStopTicks = GetTickCount() + LINEDROPTIMEOUT;
  221. while (GetTickCount() < dwStopTicks)
  222. {
  223. // see if reply has occured and we are idle
  224. if ((globals->dwAsyncID == 0) &&
  225. (globals->dwCallState == LINECALLSTATE_IDLE))
  226. {
  227. break;
  228. }
  229. // give TAPI a chance to call our callback
  230. if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  231. {
  232. TranslateMessage(&msg);
  233. DispatchMessage(&msg);
  234. }
  235. }
  236. lResult = SUCCESS;
  237. Failure:
  238. return (lResult);
  239. }
  240. /* dialDeallocCall - wrapper for lineDeallocCall */
  241. #undef DPF_MODNAME
  242. #define DPF_MODNAME "dialDeallocCall"
  243. LINERESULT dialDeallocCall(LPDPDIAL globals)
  244. {
  245. LINERESULT lResult;
  246. // fail if line not open or if call not open
  247. FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
  248. FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
  249. // close the com port
  250. dialCloseCommHandle(globals);
  251. DPF(3, "lineDeallocateCall");
  252. DPF(3, "> hCall: %08X", globals->hCall);
  253. lResult = lineDeallocateCall(globals->hCall);
  254. LINEERROR(lResult);
  255. globals->hCall = 0;
  256. Failure:
  257. return (lResult);
  258. }
  259. /* dialIsConnected- returns TRUE if call is connected */
  260. #undef DPF_MODNAME
  261. #define DPF_MODNAME "dialIsConnected"
  262. BOOL dialIsConnected(LPDPDIAL globals)
  263. {
  264. // connected if we have a call handle and the state is connected
  265. if ((globals->hCall) &&
  266. (globals->dwCallState == LINECALLSTATE_CONNECTED))
  267. return (TRUE);
  268. else
  269. return (FALSE);
  270. }
  271. /* callback function */
  272. #undef DPF_MODNAME
  273. #define DPF_MODNAME "LineCallBackProc"
  274. void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
  275. DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3)
  276. {
  277. LPDPDIAL globals = (LPDPDIAL) dwInstance;
  278. DPF(3, "Line message: %s", GetLineMsgStr(dwMessage));
  279. switch (dwMessage)
  280. {
  281. case LINE_LINEDEVSTATE:
  282. break;
  283. case LINE_CALLSTATE:
  284. globals->dwCallState = dwParam1;
  285. DPF(3, " call state: %s", GetCallStateStr((DWORD)globals->dwCallState));
  286. switch (globals->dwCallState)
  287. {
  288. case LINECALLSTATE_OFFERING:
  289. ProcessOfferingState(globals, (HCALL) hDevice, (DWORD)dwParam3);
  290. break;
  291. case LINECALLSTATE_CONNECTED:
  292. ProcessConnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  293. break;
  294. case LINECALLSTATE_DISCONNECTED:
  295. ProcessDisconnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  296. break;
  297. case LINECALLSTATE_IDLE:
  298. ProcessIdleState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
  299. break;
  300. case LINECALLSTATE_BUSY:
  301. break;
  302. }
  303. break;
  304. case LINE_REPLY:
  305. ProcessReplyMessage(globals, (DWORD)dwParam1, (LINERESULT) dwParam2);
  306. break;
  307. /* other messages that can be processed */
  308. case LINE_CLOSE:
  309. // the line has shut itself down
  310. globals->hLine = 0;
  311. globals->dwCallError = CALL_CLOSED;
  312. break;
  313. case LINE_ADDRESSSTATE:
  314. break;
  315. case LINE_CALLINFO:
  316. break;
  317. case LINE_DEVSPECIFIC:
  318. break;
  319. case LINE_DEVSPECIFICFEATURE:
  320. break;
  321. case LINE_GATHERDIGITS:
  322. break;
  323. case LINE_GENERATE:
  324. break;
  325. case LINE_MONITORDIGITS:
  326. break;
  327. case LINE_MONITORMEDIA:
  328. break;
  329. case LINE_MONITORTONE:
  330. break;
  331. } /* switch */
  332. } /* LineCallBackProc */
  333. /* ProcessOfferingState - handler for LINECALLSTATE_OFFERING state */
  334. #undef DPF_MODNAME
  335. #define DPF_MODNAME "ProcessOfferingState"
  336. void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege)
  337. {
  338. LINERESULT lResult;
  339. DDASSERT(hCall);
  340. DDASSERT(globals->hCall == 0);
  341. DDASSERT(globals->dwAsyncID == 0);
  342. DPF(3, " hCall: %08X", hCall);
  343. DPF(3, " privilege: %08X", (DWORD)dwCallPrivilege);
  344. // fail if we don't own the call
  345. FAILIF(dwCallPrivilege != LINECALLPRIVILEGE_OWNER, Failure);
  346. // answer the call
  347. lResult = lineAnswer(hCall, NULL, 0);
  348. // lResult will be > 0 if call is asynchronous
  349. FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
  350. FAILMSG(lResult == 0);
  351. globals->hCall = hCall; // store call handle
  352. globals->dwAsyncID = lResult; // store async ID
  353. Failure:
  354. return;
  355. }
  356. /* ProcessConnectedState - handler for LINECALLSTATE_CONNECTED state */
  357. #undef DPF_MODNAME
  358. #define DPF_MODNAME "ProcessConnectedState"
  359. void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  360. {
  361. LINERESULT lResult;
  362. HRESULT hr;
  363. DDASSERT(hCall);
  364. DDASSERT(globals->hCall);
  365. DDASSERT(globals->hCall == hCall);
  366. DPF(3, " hCall: %08X", hCall);
  367. DPF(3, " privilege: %08X", dwCallPrivilege);
  368. DPF(3, " detail: %08X", dwCallStateDetail);
  369. // get the id of the COM device connected to the modem
  370. // NOTE: once we get the handle, it is our responsibility to close it
  371. lResult = dialGetCommHandle(globals);
  372. FAILIF(LINEERROR(lResult), Failure);
  373. DPF(3, " hComPort: %08X", globals->hComm);
  374. // setup com port
  375. hr = globals->lpComPort->Setup(globals->lpComPort, globals->hComm);
  376. FAILIF(FAILED(hr), Failure);
  377. {
  378. DWORD dwBaudRate;
  379. lResult = dialGetBaudRate(globals, &dwBaudRate);
  380. }
  381. Failure:
  382. return;
  383. }
  384. /* ProcessDisconnectedState - handler for LINECALLSTATE_DISCONNECTED state */
  385. #undef DPF_MODNAME
  386. #define DPF_MODNAME "ProcessDisconnectedState"
  387. void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  388. {
  389. LINERESULT lResult;
  390. DDASSERT(hCall);
  391. DDASSERT(globals->hCall);
  392. DDASSERT(globals->hCall == hCall);
  393. DPF(3, " hCall: %08X", hCall);
  394. DPF(3, " privilege: %08X", dwCallPrivilege);
  395. DPF(3, " detail: %08X", dwCallStateDetail);
  396. // record error
  397. globals->dwCallError = CALL_DISCONNECTED;
  398. // shutdown com port and deallocate call handle
  399. lResult = dialDeallocCall(globals);
  400. FAILMSG(LINEERROR(lResult));
  401. }
  402. /* ProcessIdleState - handler for LINECALLSTATE_IDLE state */
  403. #undef DPF_MODNAME
  404. #define DPF_MODNAME "ProcessIdleState"
  405. void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
  406. {
  407. DDASSERT(hCall);
  408. DPF(3, " hCall: %08X", hCall);
  409. DPF(3, " privilege: %08X", dwCallPrivilege);
  410. DPF(3, " detail: %08X", dwCallStateDetail);
  411. }
  412. /* ProcessReplyMessage - handler for LINE_REPLY message */
  413. #undef DPF_MODNAME
  414. #define DPF_MODNAME "ProcessReplyMessage"
  415. void ProcessReplyMessage(LPDPDIAL globals, DWORD dwAsyncID, LINERESULT lResult)
  416. {
  417. DDASSERT(dwAsyncID);
  418. DDASSERT(globals->dwAsyncID);
  419. DDASSERT(globals->dwAsyncID == dwAsyncID);
  420. DPF(3, " dwAsyncID: %d", dwAsyncID);
  421. DPF(3, " error: %d", lResult);
  422. // check for an error
  423. if (LINEERROR(lResult))
  424. globals->dwCallError = CALL_LINEERROR;
  425. // reset field so we know reply happened
  426. globals->dwAsyncID = 0;
  427. }
  428. /* dialGetDevCaps - wrapper for lineGetDevCaps */
  429. /* Bug #5400
  430. My trusty Compaq Presario returns two line devices. The second device says it
  431. needs 555 bytes for dev caps, but when you give it a pointer to a 555-byte block
  432. it actually writes 559 (!) bytes into the buffer! Whoah, Bessy!
  433. This makes Windows very unhappy in strange and magical ways.
  434. The fix is to start with a very large buffer (1024 bytes?) like all the samples do
  435. and then leave some slop in subsequent reallocs, which should hopefully clean up
  436. after these messy critters.
  437. */
  438. #define DEVCAPSINITIALSIZE 1024 // size of first alloc
  439. #define DEVCAPSSLOP 100 // extra space that loser service providers can party on
  440. #undef DPF_MODNAME
  441. #define DPF_MODNAME "dialGetDevCaps"
  442. LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet)
  443. {
  444. LPLINEDEVCAPS lpDevCaps;
  445. LINERESULT lResult;
  446. LPVOID lpTemp;
  447. // create a buffer for dev caps
  448. lpDevCaps = (LPLINEDEVCAPS) SP_MemAlloc(DEVCAPSINITIALSIZE + DEVCAPSSLOP);
  449. FAILWITHACTION(lpDevCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  450. lpDevCaps->dwTotalSize = DEVCAPSINITIALSIZE;
  451. while (TRUE)
  452. {
  453. // get device caps
  454. lResult = lineGetDevCaps(globals->hLineApp, dwLine,
  455. dwAPIVersion, 0, lpDevCaps);
  456. if (lResult == SUCCESS)
  457. {
  458. // make sure there is enough space
  459. if (lpDevCaps->dwNeededSize <= lpDevCaps->dwTotalSize)
  460. break; // there is enough space, so exit
  461. }
  462. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  463. {
  464. LINEERROR(lResult);
  465. goto Failure;
  466. }
  467. // reallocate buffer if not big enough */
  468. lpTemp = SP_MemReAlloc(lpDevCaps, lpDevCaps->dwNeededSize + DEVCAPSSLOP);
  469. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  470. lpDevCaps = lpTemp;
  471. lpDevCaps->dwTotalSize = lpDevCaps->dwNeededSize;
  472. }
  473. *lpDevCapsRet = lpDevCaps;
  474. return (SUCCESS);
  475. Failure:
  476. if (lpDevCaps)
  477. SP_MemFree(lpDevCaps);
  478. return (lResult);
  479. }
  480. /* dialGetCallInfo - wrapper for lineGetCallInfo */
  481. #undef DPF_MODNAME
  482. #define DPF_MODNAME "dialGetCallInfo"
  483. LINERESULT dialGetCallInfo(LPDPDIAL globals, LPLINECALLINFO *lpCallInfoRet)
  484. {
  485. LPLINECALLINFO lpCallInfo;
  486. LINERESULT lResult;
  487. LPVOID lpTemp;
  488. // create a buffer for call info
  489. lpCallInfo = (LPLINECALLINFO) SP_MemAlloc(sizeof(LINECALLINFO));
  490. FAILWITHACTION(lpCallInfo == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  491. lpCallInfo->dwTotalSize = sizeof(LINECALLINFO);
  492. while (TRUE)
  493. {
  494. // get device info
  495. lResult = lineGetCallInfo(globals->hCall, lpCallInfo);
  496. if (lResult == SUCCESS)
  497. {
  498. // make sure there is enough space
  499. if (lpCallInfo->dwNeededSize <= lpCallInfo->dwTotalSize)
  500. break; // there is enough space, so exit
  501. }
  502. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  503. {
  504. LINEERROR(lResult);
  505. goto Failure;
  506. }
  507. // reallocate buffer if not big enough */
  508. lpTemp = SP_MemReAlloc(lpCallInfo, lpCallInfo->dwNeededSize);
  509. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  510. lpCallInfo = lpTemp;
  511. lpCallInfo->dwTotalSize = lpCallInfo->dwNeededSize;
  512. }
  513. *lpCallInfoRet = lpCallInfo;
  514. return (SUCCESS);
  515. Failure:
  516. if (lpCallInfo)
  517. SP_MemFree(lpCallInfo);
  518. return (lResult);
  519. }
  520. /* dialGetBaudRate - get baud rate of current connecton */
  521. #undef DPF_MODNAME
  522. #define DPF_MODNAME "dialGetBaudRate"
  523. LINERESULT dialGetBaudRate(LPDPDIAL globals, LPDWORD lpdwBaudRate)
  524. {
  525. LPLINECALLINFO lpCallInfo;
  526. LINERESULT lResult;
  527. lResult = dialGetCallInfo(globals, &lpCallInfo);
  528. if LINEERROR(lResult)
  529. return (lResult);
  530. *lpdwBaudRate = lpCallInfo->dwRate;
  531. SP_MemFree(lpCallInfo);
  532. return (SUCCESS);
  533. }
  534. /* dialGetTranslateCaps - wrapper for lineGetTranslateCaps */
  535. #undef DPF_MODNAME
  536. #define DPF_MODNAME "dialGetTranslateCaps"
  537. LINERESULT dialGetTranslateCaps(LPDPDIAL globals, DWORD dwAPIVersion, LPLINETRANSLATECAPS *lpTranslateCapsRet)
  538. {
  539. LPLINETRANSLATECAPS lpTranslateCaps;
  540. LPVOID lpTemp;
  541. LINERESULT lResult;
  542. // create a buffer for translate caps
  543. lpTranslateCaps = (LPLINETRANSLATECAPS) SP_MemAlloc(sizeof(LINETRANSLATECAPS));
  544. FAILWITHACTION(lpTranslateCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  545. lpTranslateCaps->dwTotalSize = sizeof(LINETRANSLATECAPS);
  546. while (TRUE)
  547. {
  548. // get translate caps
  549. lResult = lineGetTranslateCaps(globals->hLineApp, dwAPIVersion, lpTranslateCaps);
  550. if (lResult == SUCCESS)
  551. {
  552. // make sure there is enough space
  553. if (lpTranslateCaps->dwNeededSize <= lpTranslateCaps->dwTotalSize)
  554. break; // there is enough space, so exit
  555. }
  556. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  557. {
  558. LINEERROR(lResult);
  559. goto Failure;
  560. }
  561. // reallocate buffer if not big enough */
  562. lpTemp = SP_MemReAlloc(lpTranslateCaps, lpTranslateCaps->dwNeededSize);
  563. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  564. lpTranslateCaps = lpTemp;
  565. lpTranslateCaps->dwTotalSize = lpTranslateCaps->dwNeededSize;
  566. }
  567. *lpTranslateCapsRet = lpTranslateCaps;
  568. return (SUCCESS);
  569. Failure:
  570. if (lpTranslateCaps)
  571. SP_MemFree(lpTranslateCaps);
  572. return (lResult);
  573. }
  574. /* dialGetCommHandle - wrapper for lineGetID */
  575. #undef DPF_MODNAME
  576. #define DPF_MODNAME "dialGetCommHandle"
  577. /* structure returned by Unimodem which contains device handle and name */
  578. typedef struct {
  579. HANDLE hComm;
  580. CHAR szDeviceName[1];
  581. } COMMID, *LPCOMMID;
  582. LINERESULT dialGetCommHandle(LPDPDIAL globals)
  583. {
  584. LPCOMMID lpCommID;
  585. VARSTRING *vs, *temp;
  586. LINERESULT lResult;
  587. vs = (VARSTRING *) SP_MemAlloc(sizeof(VARSTRING));
  588. FAILWITHACTION(vs == NULL, lResult = LINEERR_NOMEM, Failure);
  589. vs->dwTotalSize = sizeof(VARSTRING);
  590. vs->dwStringFormat = STRINGFORMAT_BINARY;
  591. while (TRUE)
  592. {
  593. // get line ID
  594. lResult = lineGetID(0, 0L, globals->hCall, LINECALLSELECT_CALL, vs, "comm/datamodem");
  595. if (lResult == SUCCESS)
  596. {
  597. // make sure there is enough space
  598. if (vs->dwNeededSize <= vs->dwTotalSize)
  599. break; // there is enough space, so exit
  600. }
  601. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  602. {
  603. LINEERROR(lResult);
  604. goto Failure;
  605. }
  606. // reallocate buffer if not big enough */
  607. temp = SP_MemReAlloc(vs, vs->dwNeededSize);
  608. FAILWITHACTION(temp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  609. vs = temp;
  610. vs->dwTotalSize = vs->dwNeededSize;
  611. }
  612. lpCommID = (LPCOMMID) ((LPSTR)vs + vs->dwStringOffset);
  613. // lstrcpy(globals->szDeviceName, cid->szDeviceName);
  614. globals->hComm = lpCommID->hComm;
  615. Failure:
  616. if (vs)
  617. SP_MemFree(vs);
  618. return (lResult);
  619. }
  620. /* dialCloseCommHandle - make sure com port is closed */
  621. /* NOTE: As per the docs for the "comm/datamodem" device class,
  622. the handle to the com port returned by lineGetID() MUST be explictly
  623. closed using CloseHandle() or you will not be able to to open this
  624. line again!
  625. */
  626. #undef DPF_MODNAME
  627. #define DPF_MODNAME "dialCloseCommHandle"
  628. LINERESULT dialCloseCommHandle(LPDPDIAL globals)
  629. {
  630. HANDLE hCom;
  631. // make sure the com port globals are available
  632. if (globals->lpComPort)
  633. {
  634. // get handle to com port
  635. hCom = globals->lpComPort->GetHandle(globals->lpComPort);
  636. // make sure its closed down
  637. if (hCom)
  638. {
  639. globals->lpComPort->Shutdown(globals->lpComPort);
  640. CloseHandle(hCom);
  641. }
  642. }
  643. return (SUCCESS);
  644. }
  645. /* dialTranslateAddress - wrapper for lineTranslateAddress */
  646. #undef DPF_MODNAME
  647. #define DPF_MODNAME "dialTranslateAddress"
  648. LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
  649. LPCSTR lpszDialAddress,
  650. LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet)
  651. {
  652. LPLINETRANSLATEOUTPUT lpLineTranslateOutput;
  653. LPVOID lpTemp;
  654. LINERESULT lResult;
  655. // create a buffer for translate caps
  656. lpLineTranslateOutput = (LPLINETRANSLATEOUTPUT) SP_MemAlloc(sizeof(LINETRANSLATEOUTPUT));
  657. FAILWITHACTION(lpLineTranslateOutput == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  658. lpLineTranslateOutput->dwTotalSize = sizeof(LINETRANSLATEOUTPUT);
  659. while (TRUE)
  660. {
  661. // translate address
  662. lResult = lineTranslateAddress(globals->hLineApp, dwDeviceID, dwAPIVersion,
  663. lpszDialAddress, 0, LINETRANSLATEOPTION_CANCELCALLWAITING,
  664. lpLineTranslateOutput);
  665. if (lResult == SUCCESS)
  666. {
  667. // make sure there is enough space
  668. if (lpLineTranslateOutput->dwNeededSize <= lpLineTranslateOutput->dwTotalSize)
  669. break; // there is enough space, so exit
  670. }
  671. else if (lResult != LINEERR_STRUCTURETOOSMALL)
  672. {
  673. LINEERROR(lResult);
  674. goto Failure;
  675. }
  676. // reallocate buffer if not big enough */
  677. lpTemp = SP_MemReAlloc(lpLineTranslateOutput, lpLineTranslateOutput->dwNeededSize);
  678. FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
  679. lpLineTranslateOutput = lpTemp;
  680. lpLineTranslateOutput->dwTotalSize = lpLineTranslateOutput->dwNeededSize;
  681. }
  682. *lpLineTranslateOutputRet = lpLineTranslateOutput;
  683. return (SUCCESS);
  684. Failure:
  685. if (lpLineTranslateOutput)
  686. SP_MemFree(lpLineTranslateOutput);
  687. return (lResult);
  688. }
  689. LINERESULT dialTranslateDialog(LPDPDIAL globals, HWND hWnd,
  690. DWORD dwDeviceID, LPTSTR szPhoneNumber)
  691. {
  692. LINERESULT lResult;
  693. lResult = lineTranslateDialog(globals->hLineApp, dwDeviceID,
  694. TAPIVERSION, hWnd, szPhoneNumber);
  695. return (lResult);
  696. }
  697. //
  698. // FUNCTION: void dialFillModemComboBox(HWND)
  699. //
  700. // PURPOSE: Fills the modem control with the available line devices.
  701. //
  702. // PARAMETERS:
  703. // hwndDlg - handle to the current "Dial" dialog
  704. //
  705. // RETURN VALUE:
  706. // none
  707. //
  708. // COMMENTS:
  709. //
  710. // This function enumerates through all the TAPI line devices and
  711. // queries each for the device name. The device name is then put into
  712. // the 'TAPI Line' control. These device names are kept in order rather
  713. // than sorted. This allows "Dial" to know which device ID the user
  714. // selected just by the knowing the index of the selected string.
  715. //
  716. // There are default values if there isn't a device name, if there is
  717. // an error on the device, or if the device name is an empty string.
  718. // The device name is also checked to make sure it is null terminated.
  719. //
  720. // Note that a Legacy API Version is negotiated. Since the fields in
  721. // the LINEDEVCAPS structure that we are interested in haven't moved, we
  722. // can negotiate a lower API Version than this sample is designed for
  723. // and still be able to access the necessary structure members.
  724. //
  725. // The first line that is usable by TapiComm is selected as the 'default'
  726. // line. Also note that if there was a previously selected line, this
  727. // remains the default line. This would likely only occur if this
  728. // function is called after the dialog has initialized once; for example,
  729. // if a new line is added.
  730. //
  731. //
  732. LINERESULT dialGetModemName(LPDPDIAL globals, DWORD dwDeviceID,
  733. LPSTR lpszModemName, DWORD dwModemNameSize)
  734. {
  735. LPLINEDEVCAPS lpLineDevCaps = NULL;
  736. LPSTR lpszLineName;
  737. LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
  738. DWORD dwAPIVersion; // api version
  739. DWORD dwStrSize;
  740. LINERESULT lResult;
  741. /* negotiate API version for each line */
  742. lResult = lineNegotiateAPIVersion(globals->hLineApp, dwDeviceID,
  743. TAPIVERSION, TAPIVERSION,
  744. &dwAPIVersion, &lineExtensionID);
  745. if LINEERROR(lResult)
  746. goto FAILURE;
  747. lResult = dialGetDevCaps(globals, dwDeviceID, dwAPIVersion, &lpLineDevCaps);
  748. if LINEERROR(lResult)
  749. goto FAILURE;
  750. if ((lpLineDevCaps->dwLineNameSize) &&
  751. (lpLineDevCaps->dwLineNameOffset) &&
  752. (lpLineDevCaps->dwStringFormat == STRINGFORMAT_ASCII) &&
  753. (lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM))
  754. {
  755. // This is the name of the device.
  756. lpszLineName = ((char *) lpLineDevCaps) + lpLineDevCaps->dwLineNameOffset;
  757. if (lpszLineName[0] != '\0')
  758. {
  759. // Reverse indented to make this fit
  760. // Make sure the device name is null terminated.
  761. if (lpszLineName[lpLineDevCaps->dwLineNameSize -1] != '\0')
  762. {
  763. // If the device name is not null terminated, null
  764. // terminate it. Yes, this looses the end character.
  765. // Its a bug in the service provider.
  766. lpszLineName[lpLineDevCaps->dwLineNameSize-1] = '\0';
  767. DPF(0, "Device name for device 0x%lx is not null terminated.", dwDeviceID);
  768. }
  769. }
  770. else // Line name started with a NULL.
  771. {
  772. lResult = LINEERR_OPERATIONFAILED;
  773. goto FAILURE;
  774. }
  775. }
  776. else // DevCaps doesn't have a valid line name. Unnamed.
  777. {
  778. lResult = LINEERR_OPERATIONFAILED;
  779. goto FAILURE;
  780. }
  781. // return modem name (make sure it fits)
  782. dwStrSize = strlen(lpszLineName) + 1;
  783. if (dwStrSize <= dwModemNameSize)
  784. CopyMemory(lpszModemName, lpszLineName, dwStrSize);
  785. else
  786. {
  787. CopyMemory(lpszModemName, lpszLineName, dwModemNameSize - 1);
  788. lpszModemName[dwModemNameSize - 1] = '\0';
  789. }
  790. FAILURE:
  791. if (lpLineDevCaps)
  792. SP_MemFree(lpLineDevCaps);
  793. return (lResult);
  794. }
  795. LINERESULT dialGetModemList(LPDPDIAL globals, BOOL bAnsi, LPVOID *lplpData, LPDWORD lpdwDataSize)
  796. {
  797. DWORD dwDeviceID;
  798. CHAR szModemName[MAXSTRINGSIZE];
  799. LPBYTE lpData;
  800. DWORD dwDataSize, dwStrBytes, dwStrLen;
  801. LINERESULT lResult;
  802. // make space for all possible strings plus terminating null
  803. lpData = (LPBYTE) SP_MemAlloc(globals->dwNumLines * MAXSTRINGSIZE * sizeof(WCHAR) + sizeof(WCHAR));
  804. FAILWITHACTION(lpData == NULL, lResult = LINEERR_NOMEM, Failure);
  805. dwDataSize = 0;
  806. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  807. {
  808. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  809. if LINEERROR(lResult)
  810. continue;
  811. if (bAnsi)
  812. {
  813. dwStrBytes = (lstrlen(szModemName) + 1) * sizeof(CHAR);
  814. memcpy(lpData + dwDataSize, szModemName, dwStrBytes);
  815. }
  816. else
  817. {
  818. // NOTE: AnsiToWide returns the character count INCLUDING the terminating null character
  819. dwStrLen = AnsiToWide((LPWSTR) (lpData + dwDataSize), szModemName, MAXSTRINGSIZE * sizeof(WCHAR));
  820. dwStrBytes = dwStrLen * sizeof(WCHAR);
  821. }
  822. dwDataSize += dwStrBytes;
  823. }
  824. // put a null at end of list to terminate it
  825. if (bAnsi)
  826. {
  827. *(lpData + dwDataSize) = 0;
  828. dwDataSize += sizeof(CHAR);
  829. }
  830. else
  831. {
  832. *((LPWSTR) (lpData + dwDataSize)) = 0;
  833. dwDataSize += sizeof(WCHAR);
  834. }
  835. // return buffer pointer and size
  836. *lplpData = lpData;
  837. *lpdwDataSize = dwDataSize;
  838. return (SUCCESS);
  839. Failure:
  840. return (lResult);
  841. }
  842. void dialFillModemComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultDevice)
  843. {
  844. DWORD dwDeviceID;
  845. CHAR szModemName[MAXSTRINGSIZE];
  846. LINERESULT lResult;
  847. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  848. {
  849. //
  850. // Attempt to get the modem name. If this fails, don't add the modem
  851. // to the dialog.
  852. //
  853. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  854. if ( LINEERROR(lResult) == FALSE )
  855. {
  856. //
  857. // This line appears to be usable, put the device name into the
  858. // dialog control and associate the TAPI modem ID with it
  859. //
  860. lResult = (DWORD) SendDlgItemMessage(hwndDlg, item,
  861. CB_ADDSTRING, 0, (LPARAM) szModemName);
  862. if ( lResult != CB_ERRSPACE )
  863. {
  864. DWORD_PTR TempReturn;
  865. //
  866. // We've managed to get this entry into the control, make sure
  867. // we associate the proper TAPI modem ID with this item. This
  868. // should never fail.
  869. //
  870. TempReturn = SendDlgItemMessage( hwndDlg, item, CB_SETITEMDATA, lResult, dwDeviceID );
  871. DDASSERT( TempReturn != CB_ERR );
  872. // If this line is usable and we don't have a default initial
  873. // line yet, make this the initial line.
  874. if (dwDefaultDevice == MAXDWORD)
  875. dwDefaultDevice = lResult;
  876. }
  877. }
  878. }
  879. if (dwDefaultDevice == MAXDWORD)
  880. dwDefaultDevice = 0;
  881. // Set the initial default line
  882. SendDlgItemMessage(hwndDlg, item,
  883. CB_SETCURSEL, dwDefaultDevice, 0);
  884. }
  885. LRESULT dialGetDeviceIDFromName(LPDPDIAL globals, LPCSTR szTargetName, DWORD *lpdwDeviceID)
  886. {
  887. DWORD dwDeviceID;
  888. CHAR szModemName[MAXSTRINGSIZE];
  889. LINERESULT lResult;
  890. for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
  891. {
  892. lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
  893. if LINEERROR(lResult)
  894. continue;
  895. if (strcmp(szModemName, szTargetName) == 0)
  896. {
  897. *lpdwDeviceID = dwDeviceID;
  898. return (SUCCESS);
  899. }
  900. }
  901. return (LINEERR_OPERATIONFAILED);
  902. }
  903. //
  904. // FUNCTION: void dialFillLocationComboBox(HWND)
  905. //
  906. // PURPOSE: Fills the control with the available calling from locations.
  907. //
  908. // PARAMETERS:
  909. // hwndDlg - handle to the current "Dial" dialog
  910. //
  911. // RETURN VALUE:
  912. // none
  913. //
  914. // COMMENTS:
  915. //
  916. //
  917. void dialFillLocationComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultLocation)
  918. {
  919. LPLINETRANSLATECAPS lpTranslateCaps = NULL;
  920. LPLINELOCATIONENTRY lpLocationEntry;
  921. DWORD dwCounter;
  922. LONG index;
  923. LINERESULT lResult;
  924. // get translate caps
  925. lResult = dialGetTranslateCaps(globals, TAPIVERSION, &lpTranslateCaps);
  926. if LINEERROR(lResult)
  927. return;
  928. // Find the location information in the TRANSLATECAPS
  929. lpLocationEntry = (LPLINELOCATIONENTRY)
  930. (((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
  931. // First empty the combobox
  932. SendDlgItemMessage(hwndDlg, item, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0);
  933. // enumerate all the locations
  934. for (dwCounter = 0; dwCounter < lpTranslateCaps->dwNumLocations; dwCounter++)
  935. {
  936. // Put each one into the combobox
  937. index = (DWORD)SendDlgItemMessage(hwndDlg, item,
  938. CB_ADDSTRING,
  939. (WPARAM) 0,
  940. (LPARAM) (((LPBYTE) lpTranslateCaps) +
  941. lpLocationEntry[dwCounter].dwLocationNameOffset));
  942. // Is this location the 'current' location?
  943. if (lpLocationEntry[dwCounter].dwPermanentLocationID ==
  944. lpTranslateCaps->dwCurrentLocationID)
  945. {
  946. // Set this to be the active location.
  947. SendDlgItemMessage(hwndDlg, item, CB_SETCURSEL, (WPARAM) index, (LPARAM) 0);
  948. }
  949. }
  950. if (lpTranslateCaps)
  951. SP_MemFree(lpTranslateCaps);
  952. }
  953. char gTempStr[200];
  954. LONG lineError(LONG err, LPSTR modName, DWORD lineNum)
  955. {
  956. if (err)
  957. DPF(0, "TAPI line error in %s at line %d : %s", modName, lineNum, GetLineErrStr(err));
  958. return (err);
  959. }
  960. LPSTR GetCallStateStr(DWORD callState)
  961. {
  962. switch (callState)
  963. {
  964. case LINECALLSTATE_IDLE: return ("LINECALLSTATE_IDLE");
  965. case LINECALLSTATE_OFFERING: return ("LINECALLSTATE_OFFERING");
  966. case LINECALLSTATE_ACCEPTED: return ("LINECALLSTATE_ACCEPTED");
  967. case LINECALLSTATE_DIALTONE: return ("LINECALLSTATE_DIALTONE");
  968. case LINECALLSTATE_DIALING: return ("LINECALLSTATE_DIALING");
  969. case LINECALLSTATE_RINGBACK: return ("LINECALLSTATE_RINGBACK");
  970. case LINECALLSTATE_BUSY: return ("LINECALLSTATE_BUSY");
  971. case LINECALLSTATE_SPECIALINFO: return ("LINECALLSTATE_SPECIALINFO");
  972. case LINECALLSTATE_CONNECTED: return ("LINECALLSTATE_CONNECTED");
  973. case LINECALLSTATE_PROCEEDING: return ("LINECALLSTATE_PROCEEDING");
  974. case LINECALLSTATE_ONHOLD: return ("LINECALLSTATE_ONHOLD");
  975. case LINECALLSTATE_CONFERENCED: return ("LINECALLSTATE_CONFERENCED");
  976. case LINECALLSTATE_ONHOLDPENDCONF: return ("LINECALLSTATE_ONHOLDPENDCONF");
  977. case LINECALLSTATE_ONHOLDPENDTRANSFER: return ("LINECALLSTATE_ONHOLDPENDTRANSFER");
  978. case LINECALLSTATE_DISCONNECTED: return ("LINECALLSTATE_DISCONNECTED");
  979. case LINECALLSTATE_UNKNOWN: return ("LINECALLSTATE_UNKNOWN");
  980. }
  981. wsprintf(gTempStr, "UNKNOWN CALL STATE = %lu", callState);
  982. return (gTempStr);
  983. }
  984. LPSTR GetLineMsgStr(DWORD msg)
  985. {
  986. switch (msg)
  987. {
  988. case LINE_ADDRESSSTATE: return ("LINE_ADDRESSSTATE");
  989. case LINE_CALLINFO: return ("LINE_CALLINFO");
  990. case LINE_CALLSTATE: return ("LINE_CALLSTATE");
  991. case LINE_CLOSE: return ("LINE_CLOSE");
  992. case LINE_DEVSPECIFIC: return ("LINE_DEVSPECIFIC");
  993. case LINE_DEVSPECIFICFEATURE: return ("LINE_DEVSPECIFICFEATURE");
  994. case LINE_GATHERDIGITS: return ("LINE_GATHERDIGITS");
  995. case LINE_GENERATE: return ("LINE_GENERATE");
  996. case LINE_LINEDEVSTATE: return ("LINE_LINEDEVSTATE");
  997. case LINE_MONITORDIGITS: return ("LINE_MONITORDIGITS");
  998. case LINE_MONITORMEDIA: return ("LINE_MONITORMEDIA");
  999. case LINE_MONITORTONE: return ("LINE_MONITORTONE");
  1000. case LINE_REPLY: return ("LINE_REPLY");
  1001. case LINE_REQUEST: return ("LINE_REQUEST");
  1002. }
  1003. wsprintf(gTempStr, "UNKNOWN LINE MESSAGE = %lu", msg);
  1004. return (gTempStr);
  1005. }
  1006. LPSTR GetLineErrStr(LONG err)
  1007. {
  1008. switch (err)
  1009. {
  1010. case LINEERR_ADDRESSBLOCKED: return ("LINEERR_ADDRESSBLOCKED");
  1011. case LINEERR_ALLOCATED: return ("LINEERR_ALLOCATED");
  1012. case LINEERR_BADDEVICEID: return ("LINEERR_BADDEVICEID");
  1013. case LINEERR_BEARERMODEUNAVAIL: return ("LINEERR_BEARERMODEUNAVAIL");
  1014. case LINEERR_CALLUNAVAIL: return ("LINEERR_CALLUNAVAIL");
  1015. case LINEERR_COMPLETIONOVERRUN: return ("LINEERR_COMPLETIONOVERRUN");
  1016. case LINEERR_CONFERENCEFULL: return ("LINEERR_CONFERENCEFULL");
  1017. case LINEERR_DIALBILLING: return ("LINEERR_DIALBILLING");
  1018. case LINEERR_DIALQUIET: return ("LINEERR_DIALQUIET");
  1019. case LINEERR_DIALDIALTONE: return ("LINEERR_DIALDIALTONE");
  1020. case LINEERR_DIALPROMPT: return ("LINEERR_DIALPROMPT");
  1021. case LINEERR_INCOMPATIBLEAPIVERSION: return ("LINEERR_INCOMPATIBLEAPIVERSION");
  1022. case LINEERR_INCOMPATIBLEEXTVERSION: return ("LINEERR_INCOMPATIBLEEXTVERSION");
  1023. case LINEERR_INIFILECORRUPT: return ("LINEERR_INIFILECORRUPT");
  1024. case LINEERR_INUSE: return ("LINEERR_INUSE");
  1025. case LINEERR_INVALADDRESS: return ("LINEERR_INVALADDRESS");
  1026. case LINEERR_INVALADDRESSID: return ("LINEERR_INVALADDRESSID");
  1027. case LINEERR_INVALADDRESSMODE: return ("LINEERR_INVALADDRESSMODE");
  1028. case LINEERR_INVALADDRESSSTATE: return ("LINEERR_INVALADDRESSSTATE");
  1029. case LINEERR_INVALAPPHANDLE: return ("LINEERR_INVALAPPHANDLE");
  1030. case LINEERR_INVALAPPNAME: return ("LINEERR_INVALAPPNAME");
  1031. case LINEERR_INVALBEARERMODE: return ("LINEERR_INVALBEARERMODE");
  1032. case LINEERR_INVALCALLCOMPLMODE: return ("LINEERR_INVALCALLCOMPLMODE");
  1033. case LINEERR_INVALCALLHANDLE: return ("LINEERR_INVALCALLHANDLE");
  1034. case LINEERR_INVALCALLPARAMS: return ("LINEERR_INVALCALLPARAMS");
  1035. case LINEERR_INVALCALLPRIVILEGE: return ("LINEERR_INVALCALLPRIVILEGE");
  1036. case LINEERR_INVALCALLSELECT: return ("LINEERR_INVALCALLSELECT");
  1037. case LINEERR_INVALCALLSTATE: return ("LINEERR_INVALCALLSTATE");
  1038. case LINEERR_INVALCALLSTATELIST: return ("LINEERR_INVALCALLSTATELIST");
  1039. case LINEERR_INVALCARD: return ("LINEERR_INVALCARD");
  1040. case LINEERR_INVALCOMPLETIONID: return ("LINEERR_INVALCOMPLETIONID");
  1041. case LINEERR_INVALCONFCALLHANDLE: return ("LINEERR_INVALCONFCALLHANDLE");
  1042. case LINEERR_INVALCONSULTCALLHANDLE: return ("LINEERR_INVALCONSULTCALLHANDLE");
  1043. case LINEERR_INVALCOUNTRYCODE: return ("LINEERR_INVALCOUNTRYCODE");
  1044. case LINEERR_INVALDEVICECLASS: return ("LINEERR_INVALDEVICECLASS");
  1045. case LINEERR_INVALDIGITLIST: return ("LINEERR_INVALDIGITLIST");
  1046. case LINEERR_INVALDIGITMODE: return ("LINEERR_INVALDIGITMODE");
  1047. case LINEERR_INVALDIGITS: return ("LINEERR_INVALDIGITS");
  1048. case LINEERR_INVALFEATURE: return ("LINEERR_INVALFEATURE");
  1049. case LINEERR_INVALGROUPID: return ("LINEERR_INVALGROUPID");
  1050. case LINEERR_INVALLINEHANDLE: return ("LINEERR_INVALLINEHANDLE");
  1051. case LINEERR_INVALLINESTATE: return ("LINEERR_INVALLINESTATE");
  1052. case LINEERR_INVALLOCATION: return ("LINEERR_INVALLOCATION");
  1053. case LINEERR_INVALMEDIALIST: return ("LINEERR_INVALMEDIALIST");
  1054. case LINEERR_INVALMEDIAMODE: return ("LINEERR_INVALMEDIAMODE");
  1055. case LINEERR_INVALMESSAGEID: return ("LINEERR_INVALMESSAGEID");
  1056. case LINEERR_INVALPARAM: return ("LINEERR_INVALPARAM");
  1057. case LINEERR_INVALPARKMODE: return ("LINEERR_INVALPARKMODE");
  1058. case LINEERR_INVALPOINTER: return ("LINEERR_INVALPOINTER");
  1059. case LINEERR_INVALPRIVSELECT: return ("LINEERR_INVALPRIVSELECT");
  1060. case LINEERR_INVALRATE: return ("LINEERR_INVALRATE");
  1061. case LINEERR_INVALREQUESTMODE: return ("LINEERR_INVALREQUESTMODE");
  1062. case LINEERR_INVALTERMINALID: return ("LINEERR_INVALTERMINALID");
  1063. case LINEERR_INVALTERMINALMODE: return ("LINEERR_INVALTERMINALMODE");
  1064. case LINEERR_INVALTIMEOUT: return ("LINEERR_INVALTIMEOUT");
  1065. case LINEERR_INVALTONE: return ("LINEERR_INVALTONE");
  1066. case LINEERR_INVALTONELIST: return ("LINEERR_INVALTONELIST");
  1067. case LINEERR_INVALTONEMODE: return ("LINEERR_INVALTONEMODE");
  1068. case LINEERR_INVALTRANSFERMODE: return ("LINEERR_INVALTRANSFERMODE");
  1069. case LINEERR_LINEMAPPERFAILED: return ("LINEERR_LINEMAPPERFAILED");
  1070. case LINEERR_NOCONFERENCE: return ("LINEERR_NOCONFERENCE");
  1071. case LINEERR_NODEVICE: return ("LINEERR_NODEVICE");
  1072. case LINEERR_NODRIVER: return ("LINEERR_NODRIVER");
  1073. case LINEERR_NOMEM: return ("LINEERR_NOMEM");
  1074. case LINEERR_NOMULTIPLEINSTANCE: return ("LINEERR_NOMULTIPLEINSTANCE");
  1075. case LINEERR_NOREQUEST: return ("LINEERR_NOREQUEST");
  1076. case LINEERR_NOTOWNER: return ("LINEERR_NOTOWNER");
  1077. case LINEERR_NOTREGISTERED: return ("LINEERR_NOTREGISTERED");
  1078. case LINEERR_OPERATIONFAILED: return ("LINEERR_OPERATIONFAILED");
  1079. case LINEERR_OPERATIONUNAVAIL: return ("LINEERR_OPERATIONUNAVAIL");
  1080. case LINEERR_RATEUNAVAIL: return ("LINEERR_RATEUNAVAIL");
  1081. case LINEERR_REINIT: return ("LINEERR_REINIT");
  1082. case LINEERR_RESOURCEUNAVAIL: return ("LINEERR_RESOURCEUNAVAIL");
  1083. case LINEERR_STRUCTURETOOSMALL: return ("LINEERR_STRUCTURETOOSMALL");
  1084. case LINEERR_TARGETNOTFOUND: return ("LINEERR_TARGETNOTFOUND");
  1085. case LINEERR_TARGETSELF: return ("LINEERR_TARGETSELF");
  1086. case LINEERR_UNINITIALIZED: return ("LINEERR_UNINITIALIZED");
  1087. case LINEERR_USERUSERINFOTOOBIG: return ("LINEERR_USERUSERINFOTOOBIG");
  1088. }
  1089. wsprintf(gTempStr, "UNKNOWN LINE ERROR = %ld", err);
  1090. return (gTempStr);
  1091. }