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.

3280 lines
91 KiB

  1. /* File: D:\WACKER\cncttapi\cncttapi.c (Created: 08-Feb-1994)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 53 $
  7. * $Date: 7/12/02 9:06a $
  8. */
  9. #define TAPI_CURRENT_VERSION 0x00010004 // cab:11/14/96 - required!
  10. #include <tapi.h>
  11. #include <unimodem.h>
  12. #pragma hdrstop
  13. //#define DEBUGSTR
  14. #include <time.h>
  15. #include <tdll\stdtyp.h>
  16. #include <tdll\session.h>
  17. #include <tdll\statusbr.h>
  18. #include <tdll\tdll.h>
  19. #include <tdll\misc.h>
  20. #include <tdll\mc.h>
  21. #include <tdll\assert.h>
  22. #include <tdll\errorbox.h>
  23. #include <tdll\cnct.h>
  24. #include <tdll\globals.h>
  25. #include <tdll\sf.h>
  26. #include <tdll\sess_ids.h>
  27. #include <tdll\com.h>
  28. #include <tdll\comdev.h>
  29. #include <tdll\com.hh>
  30. #include <tdll\htchar.h>
  31. #include <tdll\cloop.h>
  32. #include <emu\emu.h>
  33. #include <term\res.h>
  34. #include "cncttapi.h"
  35. #include "cncttapi.hh"
  36. #include <tdll\XFER_MSC.HH> // XD_TYPE
  37. #include <tdll\XFER_MSC.H> // xfrGetDisplayWindow(), xfrDoTransfer()
  38. #include "tdll\XFDSPDLG.H" // XFR_SHUTDOWN
  39. static int DoNewModemWizard(HWND hWnd, int iTimeout);
  40. static int tapiReinit(const HHDRIVER hhDriver);
  41. static int tapiReinitMessage(const HHDRIVER hhDriver);
  42. static int DoDelayedCall(const HHDRIVER hhDriver);
  43. const TCHAR *g_achApp = TEXT("HyperTerminal");
  44. static HHDRIVER gbl_hhDriver; // see LINEDEVSTATE for explaination.
  45. #if 0
  46. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  47. * FUNCTION:
  48. * cnctdrvEntry
  49. *
  50. * DESCRIPTION:
  51. * Currently, just initializes the C-Runtime library but may be used
  52. * for other things later.
  53. *
  54. * ARGUMENTS:
  55. * hInstDll - Instance of this DLL
  56. * fdwReason - Why this entry point is called
  57. * lpReserved - reserved
  58. *
  59. * RETURNS:
  60. * BOOL
  61. *
  62. */
  63. BOOL WINAPI cnctdrvEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved)
  64. {
  65. hInstance = hInstDll;
  66. return _CRT_INIT(hInstDll, fdwReason, lpReserved);
  67. }
  68. #endif
  69. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  70. * FUNCTION:
  71. * cnctdrvCreate
  72. *
  73. * DESCRIPTION:
  74. * Initializes the connection driver and returns a handle to the driver
  75. * if successful.
  76. *
  77. * ARGUMENTS:
  78. * hCnct - public connection handle
  79. *
  80. * RETURNS:
  81. * Handle to driver if successful, else 0.
  82. *
  83. */
  84. HDRIVER WINAPI cnctdrvCreate(const HCNCT hCnct, const HSESSION hSession)
  85. {
  86. HHDRIVER hhDriver;
  87. if (hCnct == 0)
  88. {
  89. assert(FALSE);
  90. return 0;
  91. }
  92. hhDriver = malloc(sizeof(*hhDriver));
  93. if (hhDriver == 0)
  94. {
  95. assert(FALSE);
  96. return 0;
  97. }
  98. gbl_hhDriver = hhDriver;
  99. memset(hhDriver, 0, sizeof(*hhDriver));
  100. InitializeCriticalSection(&hhDriver->cs);
  101. hhDriver->hCnct = hCnct;
  102. hhDriver->hSession = hSession;
  103. hhDriver->iStatus = CNCT_STATUS_FALSE;
  104. hhDriver->dwLine = (DWORD)-1;
  105. cnctdrvInit(hhDriver);
  106. return (HDRIVER)hhDriver;
  107. }
  108. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  109. * FUNCTION:
  110. * cnctdrvDestroy
  111. *
  112. * DESCRIPTION:
  113. * Destroys a connection driver handle.
  114. *
  115. * ARGUMENTS:
  116. * hhDriver - private driver handle.
  117. *
  118. * RETURNS:
  119. * 0 or error code
  120. *
  121. */
  122. int WINAPI cnctdrvDestroy(const HHDRIVER hhDriver)
  123. {
  124. if (hhDriver == 0)
  125. {
  126. assert(FALSE);
  127. return CNCT_BAD_HANDLE;
  128. }
  129. // Disconnect if we're connected or in the process.
  130. // Note: cnctdrvDisconnect should terminate the thread.
  131. cnctdrvDisconnect(hhDriver, DISCNCT_NOBEEP);
  132. if (hhDriver->hLine)
  133. {
  134. lineClose(hhDriver->hLine);
  135. memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
  136. hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
  137. hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  138. hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  139. hhDriver->stCallPar.dwBearerMode = 0;
  140. hhDriver->hLine = 0;
  141. }
  142. if (hhDriver->hLineApp)
  143. {
  144. LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
  145. if (lLineShutdown == LINEERR_NOMEM)
  146. {
  147. //
  148. // We are in a low memory state, so wait for a while,
  149. // then try to shutdown the line again. REV: 5/1/2002
  150. //
  151. Sleep(500);
  152. lLineShutdown = lineShutdown(hhDriver->hLineApp);
  153. }
  154. if (lLineShutdown != 0)
  155. {
  156. assert(FALSE);
  157. }
  158. hhDriver->hLineApp = 0;
  159. }
  160. if (IsWindow(hhDriver->hwndCnctDlg))
  161. EndModelessDialog(hhDriver->hwndCnctDlg);
  162. if (IsWindow(hhDriver->hwndTAPIWindow))
  163. {
  164. DestroyWindow(hhDriver->hwndTAPIWindow);
  165. }
  166. /* --- Cleanup --- */
  167. DeleteCriticalSection(&hhDriver->cs);
  168. free(hhDriver);
  169. return 0;
  170. }
  171. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  172. * FUNCTION:
  173. * cnctdrvLock
  174. *
  175. * DESCRIPTION:
  176. * Locks the connection driver's critical section semaphore.
  177. *
  178. * ARGUMENTS:
  179. * hhDriver - private driver handle
  180. *
  181. * RETURNS:
  182. * void
  183. *
  184. */
  185. void cnctdrvLock(const HHDRIVER hhDriver)
  186. {
  187. EnterCriticalSection(&hhDriver->cs);
  188. }
  189. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  190. * FUNCTION:
  191. * cnctdrvUnlock
  192. *
  193. * DESCRIPTION:
  194. * Unlocks the connection driver's critical section semaphore.
  195. *
  196. * ARGUMENTS:
  197. * hhDriver - private driver handle
  198. *
  199. * RETURNS:
  200. * void
  201. *
  202. */
  203. void cnctdrvUnlock(const HHDRIVER hhDriver)
  204. {
  205. LeaveCriticalSection(&hhDriver->cs);
  206. }
  207. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  208. * FUNCTION:
  209. * cnctdrvInit
  210. *
  211. * DESCRIPTION:
  212. * Initializes the connection handle. Can be called to reinitialize
  213. * the handle. Does an implicit disconnect.
  214. *
  215. * ARGUMENTS:
  216. * hhDriver - private driver handle
  217. *
  218. * RETURNS:
  219. * 0
  220. *
  221. */
  222. int WINAPI cnctdrvInit(const HHDRIVER hhDriver)
  223. {
  224. long lRet;
  225. int id = 0;
  226. int iReturn = 0;
  227. // Make sure we're disconnected.
  228. //
  229. cnctdrvDisconnect(hhDriver, DISCNCT_NOBEEP);
  230. // ----------------------------------------------------------------
  231. // Need to shut down hLineApp and reinitialize everytime we read
  232. // new data file so that TAPI starts out in a clean and initialized
  233. // state. Otherwise, we might inherit values from the previous
  234. // session.
  235. // ----------------------------------------------------------------
  236. if (hhDriver->hLineApp)
  237. {
  238. LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
  239. if (lLineShutdown == LINEERR_NOMEM)
  240. {
  241. //
  242. // We are in a low memory state, so wait for a while,
  243. // then try to shutdown the line again. REV: 5/1/2002
  244. //
  245. Sleep(500);
  246. lLineShutdown = lineShutdown(hhDriver->hLineApp);
  247. }
  248. if (lLineShutdown != 0)
  249. {
  250. assert(FALSE);
  251. hhDriver->hLineApp = 0;
  252. return -2;
  253. }
  254. }
  255. hhDriver->hLineApp = 0;
  256. // Try to get a new LineApp handle now.
  257. //
  258. lRet = lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
  259. lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt);
  260. if (lRet != 0)
  261. {
  262. iReturn = -3;
  263. switch (lRet)
  264. {
  265. case LINEERR_INIFILECORRUPT:
  266. id = IDS_ER_TAPI_INIFILE;
  267. break;
  268. case LINEERR_NODRIVER:
  269. id = IDS_ER_TAPI_NODRIVER;
  270. break;
  271. case LINEERR_NOMULTIPLEINSTANCE:
  272. id = IDS_ER_TAPI_NOMULTI;
  273. break;
  274. #if 0 // rev:08/05/99 We are now printing the lineInitialize() error.
  275. // rev:08/26/98 We need to make sure there was no error reported.
  276. //
  277. case LINEERR_INVALAPPNAME:
  278. case LINEERR_OPERATIONFAILED:
  279. case LINEERR_RESOURCEUNAVAIL:
  280. case LINEERR_INVALPOINTER:
  281. case LINEERR_REINIT:
  282. case LINEERR_NODEVICE:
  283. case LINEERR_NOMEM:
  284. id = IDS_ER_CNCT_TAPIFAILED;
  285. break;
  286. #endif
  287. case LINEERR_OPERATIONUNAVAIL:
  288. //rev: 08-05-99 If TAPI has not been installed, then return a
  289. // unique error code (since it will be handled
  290. // differently than other TAPI errors).
  291. //
  292. iReturn = -4;
  293. #if ((NT_EDITION && !NDEBUG) || !NT_EDITION)
  294. // Run the new Modem wizard if we have not prompted before.
  295. //
  296. DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
  297. sessQueryTimeout(hhDriver->hSession));
  298. #endif // ((NT_EDITION && !NDEBUG) || !NT_EDITION)
  299. break;
  300. default:
  301. id = IDS_ER_TAPI_UNKNOWN;
  302. break;
  303. }
  304. //
  305. // Only display these errors if in Debug mode in NT_EDITION.
  306. //
  307. #if ((NT_EDITION && !NDEBUG) || !NT_EDITION)
  308. if ( id )
  309. {
  310. TCHAR ach[256];
  311. TCHAR achMessage[256];
  312. LoadString(glblQueryDllHinst(), id, ach, sizeof(ach) / sizeof(TCHAR));
  313. if (id == IDS_ER_TAPI_UNKNOWN)
  314. {
  315. wsprintf(achMessage, ach, lRet);
  316. }
  317. else
  318. {
  319. lstrcpy(achMessage, ach);
  320. }
  321. TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
  322. achMessage, NULL, MB_OK | MB_ICONSTOP,
  323. sessQueryTimeout(hhDriver->hSession));
  324. }
  325. #endif //((NT_EDITION && !NDEBUG) || !NT_EDITION)
  326. return iReturn;
  327. }
  328. hhDriver->iStatus = CNCT_STATUS_FALSE;
  329. hhDriver->dwLine = (DWORD)-1;
  330. hhDriver->dwCountryID = (DWORD)-1;
  331. hhDriver->dwPermanentLineId = (DWORD)-1;
  332. hhDriver->achDest[0] = TEXT('\0');
  333. hhDriver->achAreaCode[0] = TEXT('\0');
  334. hhDriver->achLineName[0] = TEXT('\0');
  335. hhDriver->fUseCCAC = TRUE;
  336. /* --- This guy will set defaults --- */
  337. EnumerateTapiLocations(hhDriver, 0, 0);
  338. #if defined(INCL_WINSOCK)
  339. hhDriver->iPort = 23;
  340. hhDriver->achDestAddr[0] = TEXT('\0');
  341. #endif
  342. #ifdef INCL_CALL_ANSWERING
  343. hhDriver->fAnswering = FALSE;
  344. hhDriver->fRestoreSettings = FALSE;
  345. hhDriver->nSendCRLF = 0;
  346. hhDriver->nLocalEcho = 0;
  347. hhDriver->nAddLF = 0;
  348. hhDriver->nEchoplex = 0;
  349. hhDriver->pvUnregister = 0;
  350. #endif
  351. return iReturn;
  352. }
  353. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  354. * FUNCTION:
  355. * cnctdrvLoad
  356. *
  357. * DESCRIPTION:
  358. * Reads the session file to get stuff connection driver needs.
  359. *
  360. * ARGUMENTS:
  361. * hhDriver - private driver handle
  362. *
  363. * RETURNS:
  364. * 0=OK, else error
  365. *
  366. */
  367. int WINAPI cnctdrvLoad(const HHDRIVER hhDriver)
  368. {
  369. LPVARSTRING pvs;
  370. unsigned long ul;
  371. const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
  372. hhDriver->dwCountryID = (DWORD)-1;
  373. ul = sizeof(hhDriver->dwCountryID);
  374. sfGetSessionItem(sfhdl, SFID_CNCT_CC, &ul, &hhDriver->dwCountryID);
  375. hhDriver->achAreaCode[0] = TEXT('\0');
  376. ul = sizeof(hhDriver->achAreaCode);
  377. sfGetSessionItem(sfhdl, SFID_CNCT_AREA, &ul, hhDriver->achAreaCode);
  378. hhDriver->achDest[0] = TEXT('\0');
  379. ul = sizeof(hhDriver->achDest);
  380. sfGetSessionItem(sfhdl, SFID_CNCT_DEST, &ul, hhDriver->achDest);
  381. hhDriver->dwPermanentLineId = 0;
  382. ul = sizeof(hhDriver->dwPermanentLineId);
  383. sfGetSessionItem(sfhdl, SFID_CNCT_LINE, &ul, &hhDriver->dwPermanentLineId);
  384. hhDriver->fUseCCAC = 1;
  385. ul = sizeof(hhDriver->fUseCCAC);
  386. sfGetSessionItem(sfhdl, SFID_CNCT_USECCAC, &ul, &hhDriver->fUseCCAC);
  387. hhDriver->fRedialOnBusy = 1;
  388. ul = sizeof(hhDriver->fRedialOnBusy);
  389. sfGetSessionItem(sfhdl, SFID_CNCT_REDIAL, &ul, &hhDriver->fRedialOnBusy);
  390. #if defined (INCL_WINSOCK)
  391. hhDriver->iPort = 23;
  392. ul = sizeof(hhDriver->iPort);
  393. sfGetSessionItem(sfhdl, SFID_CNCT_IPPORT, &ul, &hhDriver->iPort);
  394. hhDriver->achDestAddr[0] = TEXT('\0');
  395. ul = sizeof(hhDriver->achDestAddr);
  396. sfGetSessionItem(sfhdl, SFID_CNCT_IPDEST, &ul, hhDriver->achDestAddr);
  397. #endif
  398. hhDriver->fCarrierDetect = FALSE;
  399. ul = sizeof(hhDriver->fCarrierDetect);
  400. sfGetSessionItem(sfhdl, SFID_CNCT_CARRIERDETECT, &ul, &hhDriver->fCarrierDetect);
  401. if ( IsNT() )
  402. {
  403. hhDriver->achComDeviceName[0] = TEXT('\0');
  404. ul = sizeof(hhDriver->achComDeviceName);
  405. sfGetSessionItem(sfhdl, SFID_CNCT_COMDEVICE, &ul, hhDriver->achComDeviceName);
  406. }
  407. // ----------------------------------------------------------------
  408. // Need to shut down hLineApp and reinitialize everytime we read
  409. // new data file so that TAPI starts out in a clean and initialized
  410. // state. Otherwise, we might inherit values from the previous
  411. // session.
  412. // ----------------------------------------------------------------
  413. if (hhDriver->hLineApp)
  414. {
  415. LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
  416. if (lLineShutdown == LINEERR_NOMEM)
  417. {
  418. //
  419. // We are in a low memory state, so wait for a while,
  420. // then try to shutdown the line again. REV: 5/1/2002
  421. //
  422. Sleep(500);
  423. lLineShutdown = lineShutdown(hhDriver->hLineApp);
  424. }
  425. if (lLineShutdown != 0)
  426. {
  427. assert(FALSE);
  428. hhDriver->hLineApp = 0;
  429. return -2;
  430. }
  431. hhDriver->hLineApp = 0;
  432. if (lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
  433. lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt))
  434. {
  435. assert(FALSE);
  436. return -3;
  437. }
  438. }
  439. // EnumerateLines() will set the hhDriver->fMatchedPermanentLineID
  440. // guy if it finds a match for our saved dwPermanentLineId guy
  441. //
  442. if ( IsNT() )
  443. {
  444. EnumerateLinesNT(hhDriver, 0);
  445. }
  446. else
  447. {
  448. EnumerateLines(hhDriver, 0);
  449. }
  450. /* --- If we saved a tapi configuration, restore it. --- */
  451. if (sfGetSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, &ul, 0) != 0)
  452. return 0; // Ok, might not be there.
  453. if ((pvs = malloc(ul)) == 0)
  454. {
  455. assert(FALSE);
  456. return -4;
  457. }
  458. if (sfGetSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, &ul, pvs) == 0)
  459. {
  460. if (hhDriver->fMatchedPermanentLineID)
  461. {
  462. LPVOID pv = (BYTE *)pvs + pvs->dwStringOffset;
  463. if (lineSetDevConfig(hhDriver->dwLine, pv,
  464. pvs->dwStringSize, DEVCLASS) != 0)
  465. {
  466. // This error prevented a user from even opening a session
  467. // file if the file contained TAPI info and the user had
  468. // never installed a modem. We modified the error that appears
  469. // when you actually try to USE a non-existant modem so that
  470. // we could suppress the display of this error jkh 8/3/98
  471. #if 0
  472. TCHAR ach[FNAME_LEN];
  473. LoadString(glblQueryDllHinst(), IDS_OPEN_FAILED, ach,
  474. sizeof(ach) / sizeof(TCHAR));
  475. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  476. MB_OK | MB_ICONINFORMATION,
  477. sessQueryTimeout(hhDriver->hSession));
  478. free(pvs);
  479. pvs = NULL;
  480. return -5;
  481. #endif
  482. }
  483. }
  484. }
  485. free(pvs);
  486. pvs = NULL;
  487. return 0;
  488. }
  489. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  490. * FUNCTION:
  491. * cnctdrvSave
  492. *
  493. * DESCRIPTION:
  494. * Saves connection settings to the session file
  495. *
  496. * ARGUMENTS:
  497. * hhDriver - private driver handle
  498. *
  499. * RETURNS:
  500. * 0=OK, else error
  501. *
  502. */
  503. int WINAPI cnctdrvSave(const HHDRIVER hhDriver)
  504. {
  505. DWORD dwSize;
  506. unsigned long ul;
  507. LPVARSTRING pvs = NULL;
  508. const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
  509. sfPutSessionItem(sfhdl, SFID_CNCT_CC, sizeof(hhDriver->dwCountryID),
  510. &hhDriver->dwCountryID);
  511. sfPutSessionItem(sfhdl, SFID_CNCT_AREA,
  512. (lstrlen(hhDriver->achAreaCode) + 1) * sizeof(TCHAR),
  513. hhDriver->achAreaCode);
  514. sfPutSessionItem(sfhdl, SFID_CNCT_DEST,
  515. (lstrlen(hhDriver->achDest) + 1) * sizeof(TCHAR), hhDriver->achDest);
  516. sfPutSessionItem(sfhdl, SFID_CNCT_LINE, sizeof(hhDriver->dwPermanentLineId),
  517. &hhDriver->dwPermanentLineId);
  518. sfPutSessionItem(sfhdl, SFID_CNCT_USECCAC, sizeof(hhDriver->fUseCCAC),
  519. &hhDriver->fUseCCAC);
  520. sfPutSessionItem(sfhdl, SFID_CNCT_REDIAL, sizeof(hhDriver->fRedialOnBusy),
  521. &hhDriver->fRedialOnBusy);
  522. #if defined (INCL_WINSOCK)
  523. sfPutSessionItem(sfhdl, SFID_CNCT_IPPORT, sizeof(hhDriver->iPort),
  524. &hhDriver->iPort);
  525. sfPutSessionItem(sfhdl, SFID_CNCT_IPDEST,
  526. (lstrlen(hhDriver->achDestAddr) + 1) * sizeof(TCHAR),
  527. hhDriver->achDestAddr);
  528. #endif
  529. /* --- Usual lines of code to use TAPI --- */
  530. if (hhDriver->hLineApp && hhDriver->dwLine != (DWORD)-1 &&
  531. !IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
  532. hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE &&
  533. hhDriver->dwPermanentLineId != DIRECT_COMWINSOCK)
  534. {
  535. if ((pvs = malloc(sizeof(VARSTRING))) == 0)
  536. {
  537. assert(FALSE);
  538. return 0;
  539. }
  540. memset( pvs, 0, sizeof(VARSTRING) );
  541. pvs->dwTotalSize = sizeof(VARSTRING);
  542. if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
  543. {
  544. assert(FALSE);
  545. free(pvs);
  546. pvs = NULL;
  547. return 0;
  548. }
  549. if (pvs->dwNeededSize > pvs->dwTotalSize)
  550. {
  551. dwSize = pvs->dwNeededSize;
  552. free(pvs);
  553. pvs = NULL;
  554. if ((pvs = malloc(dwSize)) == 0)
  555. {
  556. assert(FALSE);
  557. return 0;
  558. }
  559. memset( pvs, 0, dwSize );
  560. pvs->dwTotalSize = dwSize;
  561. if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
  562. {
  563. assert(FALSE);
  564. free(pvs);
  565. pvs = NULL;
  566. return 0;
  567. }
  568. }
  569. /* --- Store the whole structure --- */
  570. ul = pvs->dwTotalSize;
  571. sfPutSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, ul, pvs);
  572. free(pvs);
  573. pvs = NULL;
  574. }
  575. if ( IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
  576. {
  577. ul = sizeof(hhDriver->achComDeviceName);
  578. sfPutSessionItem(sfhdl, SFID_CNCT_COMDEVICE, ul,
  579. hhDriver->achComDeviceName);
  580. }
  581. sfPutSessionItem(sfhdl, SFID_CNCT_CARRIERDETECT, sizeof(hhDriver->fCarrierDetect),
  582. &hhDriver->fCarrierDetect);
  583. return 0;
  584. }
  585. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  586. * FUNCTION:
  587. * cnctdrvQueryStatus
  588. *
  589. * DESCRIPTION:
  590. * Returns the current connection status as defined in <tdll\cnct.h>
  591. *
  592. * ARGUMENTS:
  593. * hhDriver - private driver handle
  594. *
  595. * RETURNS:
  596. * connection status or error code
  597. *
  598. */
  599. int WINAPI cnctdrvQueryStatus(const HHDRIVER hhDriver)
  600. {
  601. int iStatus = CNCT_STATUS_FALSE;
  602. if (hhDriver == 0)
  603. {
  604. assert(FALSE);
  605. iStatus = CNCT_BAD_HANDLE;
  606. }
  607. else
  608. {
  609. cnctdrvLock(hhDriver);
  610. iStatus = hhDriver->iStatus; //* hard-code for now.
  611. cnctdrvUnlock(hhDriver);
  612. }
  613. return iStatus;
  614. }
  615. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  616. * FUNCTION:
  617. * SetStatus
  618. *
  619. * DESCRIPTION:
  620. * There's actually more to setting the connection status than just
  621. * setting the status variable as the code below indicates. Dumb
  622. * question: Why aren't there any locks in this code. Dumb Answer:
  623. * This function is only called from the ConnectLoop thread context
  624. * which has already locked things down.
  625. *
  626. * ARGUMENTS:
  627. * hhDriver - private driver handle
  628. * iStatus - new status
  629. *
  630. * RETURNS:
  631. * void
  632. *
  633. */
  634. void SetStatus(const HHDRIVER hhDriver, const int iStatus)
  635. {
  636. HCLOOP hCLoop;
  637. /* --- Don't do things twice --- */
  638. const HWND hwndToolbar = sessQueryHwndToolbar(hhDriver->hSession);
  639. cnctdrvLock(hhDriver);
  640. if (iStatus == hhDriver->iStatus)
  641. {
  642. if (iStatus == CNCT_STATUS_TRUE || iStatus == CNCT_STATUS_FALSE)
  643. {
  644. hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
  645. if (hCLoop)
  646. CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
  647. }
  648. cnctdrvUnlock(hhDriver);
  649. return;
  650. }
  651. /* --- Set the status, an exciting new adventure game --- */
  652. switch (iStatus)
  653. {
  654. case CNCT_STATUS_TRUE:
  655. hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
  656. #ifdef INCL_CALL_ANSWERING
  657. // If we are going from answering to connected, that means
  658. // we have answered a call. So tweak the ASCII settings so
  659. // that they make chatting possible. - cab:11/20/96
  660. //
  661. if (hhDriver->fAnswering)
  662. {
  663. // Store old ASCII settings, and set the new ones.
  664. //
  665. hhDriver->nSendCRLF = CLoopGetSendCRLF(hCLoop);
  666. hhDriver->nLocalEcho = CLoopGetLocalEcho(hCLoop);
  667. hhDriver->nAddLF = CLoopGetAddLF(hCLoop);
  668. hhDriver->nEchoplex = CLoopGetEchoplex(hCLoop);
  669. CLoopSetSendCRLF(hCLoop, TRUE);
  670. CLoopSetLocalEcho(hCLoop, TRUE);
  671. CLoopSetAddLF(hCLoop, TRUE);
  672. CLoopSetEchoplex(hCLoop, TRUE);
  673. hhDriver->fRestoreSettings = TRUE;
  674. }
  675. #endif
  676. hhDriver->iStatus = CNCT_STATUS_TRUE;
  677. assert(hCLoop);
  678. if (hCLoop)
  679. {
  680. CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
  681. CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
  682. }
  683. NotifyClient(hhDriver->hSession, EVENT_CONNECTION_OPENED, 0);
  684. sessBeeper(hhDriver->hSession);
  685. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
  686. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
  687. break;
  688. case CNCT_STATUS_CONNECTING:
  689. hhDriver->iStatus = CNCT_STATUS_CONNECTING;
  690. DialingMessage(hhDriver, IDS_DIAL_OFFERING); // temp
  691. NotifyClient(hhDriver->hSession, EVENT_CONNECTION_INPROGRESS, 0);
  692. EnableDialNow(hhDriver->hwndCnctDlg, FALSE);
  693. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
  694. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
  695. break;
  696. case CNCT_STATUS_DISCONNECTING:
  697. hhDriver->iStatus = CNCT_STATUS_DISCONNECTING;
  698. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
  699. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, FALSE);
  700. break;
  701. case CNCT_STATUS_FALSE:
  702. hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
  703. #ifdef INCL_CALL_ANSWERING
  704. // Since this is called when we disconnect we need to restore
  705. // any ASCII Settings here. - cab:11/20/96
  706. //
  707. if ( hhDriver->fRestoreSettings && hCLoop ) //mpt: so that we don't reference a null pointer
  708. {
  709. CLoopSetSendCRLF(hCLoop, hhDriver->nSendCRLF);
  710. CLoopSetLocalEcho(hCLoop, hhDriver->nLocalEcho);
  711. CLoopSetAddLF(hCLoop, hhDriver->nAddLF);
  712. CLoopSetEchoplex(hCLoop, hhDriver->nEchoplex);
  713. hhDriver->fRestoreSettings = FALSE;
  714. }
  715. hhDriver->fAnswering = FALSE;
  716. #endif
  717. hhDriver->iStatus = CNCT_STATUS_FALSE;
  718. if (hCLoop)
  719. {
  720. CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
  721. CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
  722. }
  723. NotifyClient(hhDriver->hSession, EVENT_CONNECTION_CLOSED, 0);
  724. EnableDialNow(hhDriver->hwndCnctDlg, TRUE);
  725. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, TRUE);
  726. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, FALSE);
  727. break;
  728. case CNCT_STATUS_ANSWERING:
  729. #ifdef INCL_CALL_ANSWERING
  730. hhDriver->fAnswering = TRUE;
  731. hhDriver->iStatus = CNCT_STATUS_ANSWERING;
  732. NotifyClient(hhDriver->hSession, EVENT_CONNECTION_INPROGRESS, 0);
  733. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
  734. ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
  735. #endif
  736. break;
  737. default:
  738. assert(FALSE);
  739. break;
  740. }
  741. cnctdrvUnlock(hhDriver);
  742. /* --- Notify status bar so it can update it's display --- */
  743. PostMessage(sessQueryHwndStatusbar(hhDriver->hSession), SBR_NTFY_REFRESH,
  744. (WPARAM)SBR_CNCT_PART_NO, 0);
  745. return;
  746. }
  747. #ifdef INCL_CALL_ANSWERING
  748. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  749. * FUNCTION:
  750. * WaitForCRcallback
  751. *
  752. * DESCRIPTION:
  753. * This function gets registered as a callback with the cloop. Every
  754. * character that the cloop gets, is passed back to this function. When
  755. * this function finds a CR, it indicates that a connection has been
  756. * established. Note that this applies only to an answer mode connection,
  757. * in the direct connect driver.
  758. *
  759. * ARGUMENTS:
  760. * ECHAR ech - The character returned from cloop.
  761. * void *p - A void pointer passed back from cloop. This is
  762. * the enternal connection driver handle.
  763. *
  764. * RETURNS:
  765. * CLOOP_DISCARD unless the character is a CR where is returns CLOOP_KEEP.
  766. *
  767. * AUTHOR: C. Baumgartner, 11/20/96 (ported from HAWin32)
  768. */
  769. int WaitForCRcallback(ECHAR ech, void *p)
  770. {
  771. int iRet = CLOOP_DISCARD; // Discard all characters except the CR.
  772. TCHAR chC = (TCHAR) ech;
  773. const HHDRIVER hhDriver = (HHDRIVER)p;
  774. if (chC == TEXT('\r'))
  775. {
  776. CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
  777. hhDriver->pvUnregister = 0;
  778. // Okay, we are connected now.
  779. //
  780. SetStatus(hhDriver, CNCT_STATUS_TRUE);
  781. iRet = CLOOP_KEEP;
  782. }
  783. return iRet;
  784. }
  785. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  786. * FUNCTION:
  787. * WaitForCRinit
  788. *
  789. * DESCRIPTION:
  790. * This function is called to register a new string match function
  791. * with the cloop. It unregisters a previously registered function
  792. * if necessary. It basically will cause us to wait for a carriage
  793. * return.
  794. *
  795. * ARGUMENTS:
  796. * HHDRIVER hhDriver - The internal connection handle.
  797. *
  798. * RETURNS:
  799. * 0 if successful, otherwise -1.
  800. *
  801. * AUTHOR: C. Baumgartner, 11/20/96 (ported from HAWin32)
  802. */
  803. static int WaitForCRinit(const HHDRIVER hhDriver)
  804. {
  805. const HCLOOP hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
  806. if (!hCLoop)
  807. {
  808. return -1;
  809. }
  810. // If we are already registered, unregister.
  811. //
  812. if (hhDriver->pvUnregister != 0)
  813. {
  814. CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
  815. hhDriver->pvUnregister = 0;
  816. }
  817. // We need to un-block CLoop so we can look at the
  818. // characters as they come in.
  819. //
  820. CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
  821. // Register the match function with the cloop.
  822. //
  823. hhDriver->pvUnregister = CLoopRegisterRmtInputChain(hCLoop,
  824. WaitForCRcallback, hhDriver);
  825. if (hhDriver->pvUnregister == 0)
  826. {
  827. return -1;
  828. }
  829. return 0;
  830. }
  831. #endif
  832. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  833. * FUNCTION:
  834. * cnctdrvComEvent
  835. *
  836. * DESCRIPTION:
  837. * Com routines call the this to notify connection routines that some
  838. * significant event has happened (ie. carrier lost). The connetion
  839. * driver decides what it is interested in knowing however by
  840. * querying the com drivers for the specific data.
  841. *
  842. * ARGUMENTS:
  843. * hhDriver - private connection driver handle
  844. * event - the com event we are being notified of
  845. *
  846. * RETURNS:
  847. * 0
  848. *
  849. */
  850. int WINAPI cnctdrvComEvent(const HHDRIVER hhDriver, const enum COM_EVENTS event)
  851. {
  852. int iRet;
  853. TCHAR ach[MAX_PATH];
  854. #if defined(INCL_WINSOCK)
  855. char achMsg[512];
  856. #endif
  857. HCOM hCom;
  858. if (hhDriver == 0)
  859. {
  860. assert(FALSE);
  861. return CNCT_BAD_HANDLE;
  862. }
  863. if (event == CONNECT)
  864. {
  865. #if defined (INCL_WINSOCK)
  866. // If we are connected via Winsock, there will be some ComEvents
  867. // that we have to handle
  868. if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
  869. {
  870. hCom = sessQueryComHdl(hhDriver->hSession);
  871. iRet = ComDriverSpecial(hCom, "Query ISCONNECTED", ach, MAX_PATH);
  872. if (iRet == COM_OK)
  873. {
  874. int iPortOpen = atoi(ach);
  875. // Do we want to initiate a disconnect? Only if we're
  876. // connected.
  877. if (iPortOpen == COM_PORT_NOT_OPEN)
  878. {
  879. if (hhDriver->iStatus == CNCT_STATUS_TRUE)
  880. {
  881. // If we are already connected, then beep when
  882. // we disconnect. - cab:12/06/96
  883. //
  884. //mpt:10-28-97 added exit upon disconnect feature
  885. NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
  886. CNCT_LOSTCARRIER | (sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 ));
  887. }
  888. else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING)
  889. {
  890. NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
  891. CNCT_LOSTCARRIER | DISCNCT_NOBEEP);
  892. LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_BADADDR, ach, MAX_PATH);
  893. wsprintf(achMsg, ach, hhDriver->achDestAddr, hhDriver->iPort);
  894. TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
  895. achMsg, NULL, MB_OK | MB_ICONINFORMATION,
  896. sessQueryTimeout(hhDriver->hSession));
  897. }
  898. }
  899. else if (iPortOpen == COM_PORT_OPEN)
  900. {
  901. SetStatus(hhDriver, CNCT_STATUS_TRUE);
  902. }
  903. }
  904. }
  905. else
  906. #endif // defined (INCL_WINSOCK)
  907. if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) ||
  908. hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
  909. {
  910. // Checking the status of DCD before disconnecting
  911. // is a good idea, prevents us hanging up whenever we
  912. // get any event while connected
  913. // - mpt:08-26-97
  914. hCom = sessQueryComHdl(hhDriver->hSession);
  915. iRet = ComDriverSpecial(hCom, "Query DCD_STATUS", ach, MAX_PATH);
  916. if (iRet == COM_OK)
  917. {
  918. int iPortOpen = atoi(ach);
  919. // Do we want to initiate a disconnect? Only if we're
  920. // connected.
  921. if (iPortOpen == COM_PORT_NOT_OPEN)
  922. {
  923. if (hhDriver->iStatus == CNCT_STATUS_TRUE)
  924. {
  925. // If we are direct cabled, and we're connected, then
  926. // the other end just disconnected, so disconnect now.
  927. // - cab:11/20/96
  928. //
  929. // Note: We must disconnect by posting a message to
  930. // thread one. This is because if we get here, we were
  931. // called from the context of the com thread, which
  932. // will not exit properly if cnctdrvDisconnect is called.
  933. // - cab:11/21/96
  934. //
  935. //
  936. // If we are already connected, then beep when
  937. // we disconnect. - cab:12/06/96
  938. //
  939. //mpt:10-28-97 added exit upon disconnect feature
  940. NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
  941. CNCT_LOSTCARRIER | (sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 ));
  942. }
  943. #if defined(INCL_CALL_ANSWERING)
  944. else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING ||
  945. hhDriver->iStatus == CNCT_STATUS_ANSWERING)
  946. #else // defined(INCL_CALL_ANSWERING)
  947. else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING)
  948. #endif // defined(INCL_CALL_ANSWERING)
  949. {
  950. NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
  951. CNCT_LOSTCARRIER | DISCNCT_NOBEEP);
  952. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED, ach, MAX_PATH);
  953. wsprintf(achMsg, ach, hhDriver->achComDeviceName);
  954. TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
  955. achMsg, NULL, MB_OK | MB_ICONINFORMATION,
  956. sessQueryTimeout(hhDriver->hSession));
  957. }
  958. }
  959. else if (iPortOpen == COM_PORT_OPEN &&
  960. hhDriver->iStatus != CNCT_STATUS_ANSWERING)
  961. {
  962. SetStatus(hhDriver, CNCT_STATUS_TRUE);
  963. }
  964. }
  965. #if defined(INCL_CALL_ANSWERING)
  966. if (hhDriver->iStatus == CNCT_STATUS_ANSWERING)
  967. {
  968. // If we are a direct cabled connection, and we are waiting
  969. // for a call, connect when we see a carriage return.
  970. //
  971. WaitForCRinit(hhDriver);
  972. }
  973. #endif // defined(INCL_CALL_ANSWERING)
  974. }
  975. }
  976. return 0;
  977. }
  978. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  979. * FUNCTION:
  980. * DoAnswerCall
  981. *
  982. * DESCRIPTION:
  983. * Sets up TAPI to answer the next data modem call.
  984. *
  985. * ARGUMENTS:
  986. * hhDriver - private driver handle
  987. *
  988. * RETURNS:
  989. * 0 or error
  990. *
  991. * AUTHOR: C. Baumgartner, 11/25/96 (ported from HAWin32)
  992. */
  993. int DoAnswerCall(const HHDRIVER hhDriver)
  994. {
  995. TCHAR ach[256];
  996. // Believe it or not, this is all one has to do to setup and
  997. // answer a call. Quite a contrast to placing a call.
  998. //
  999. if (TRAP(lineOpen(hhDriver->hLineApp, hhDriver->dwLine, &hhDriver->hLine,
  1000. hhDriver->dwAPIVersion, 0, (DWORD_PTR)hhDriver, LINECALLPRIVILEGE_OWNER,
  1001. LINEMEDIAMODE_DATAMODEM, 0)) != 0)
  1002. {
  1003. assert(0);
  1004. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_TAPIFAILED, ach, sizeof(ach) / sizeof(TCHAR));
  1005. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1006. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  1007. sessQueryTimeout(hhDriver->hSession));
  1008. return -1;
  1009. }
  1010. // The the line app priority for compliance with TAPI specifications.
  1011. // mrw:9/18/96
  1012. //
  1013. LoadString(glblQueryDllHinst(), IDS_GNRL_APPNAME, ach, sizeof(ach) / sizeof(TCHAR));
  1014. TRAP(lineSetAppPriority(ach, LINEMEDIAMODE_DATAMODEM, 0, 0, 0, 1));
  1015. // Set line notifications we want to receive
  1016. //
  1017. TRAP(lineSetStatusMessages(hhDriver->hLine, LINEDEVSTATE_RINGING, 0));
  1018. SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
  1019. return 0;
  1020. }
  1021. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1022. * FUNCTION:
  1023. * DoMakeCall
  1024. *
  1025. * DESCRIPTION:
  1026. * Performs the neccessary TAPI rituals to place an outbound call.
  1027. *
  1028. * ARGUMENTS:
  1029. * hhDriver - private driver handle
  1030. * uFlags - connection flags
  1031. *
  1032. * RETURNS:
  1033. * 0 or error
  1034. *
  1035. * AUTHOR: C. Baumgartner, 11/25/96 (ported from cnctdrvConnect)
  1036. */
  1037. int DoMakeCall(const HHDRIVER hhDriver, const unsigned int uFlags)
  1038. {
  1039. unsigned int uidErr = 0;
  1040. int iRet = 0;
  1041. LINEDEVSTATUS stLnDevStat;
  1042. TCHAR ach[256];
  1043. BOOL msgFlag = FALSE;
  1044. tapiReinit(hhDriver);
  1045. //
  1046. // Set the line settings.
  1047. //
  1048. if (cncttapiSetLineConfig(hhDriver->dwLine, sessQueryComHdl(hhDriver->hSession)) != 0)
  1049. {
  1050. assert(0);
  1051. uidErr = IDS_ER_CNCT_TAPIFAILED;
  1052. iRet = -1;
  1053. msgFlag = TRUE;
  1054. goto ERROR_EXIT;
  1055. }
  1056. /* --- Open the line, pass driver handle for data reference --- */
  1057. if (TRAP(lineOpen(hhDriver->hLineApp, hhDriver->dwLine,
  1058. &hhDriver->hLine, hhDriver->dwAPIVersion, 0, (DWORD_PTR)hhDriver,
  1059. LINECALLPRIVILEGE_NONE, 0, 0)) != 0)
  1060. {
  1061. assert(0);
  1062. uidErr = IDS_ER_CNCT_TAPIFAILED;
  1063. iRet = -1;
  1064. msgFlag = TRUE;
  1065. goto ERROR_EXIT;
  1066. }
  1067. /* --- Set line notifications we want to receive, mrw,2/28/95 --- */
  1068. TRAP(lineSetStatusMessages(hhDriver->hLine,
  1069. LINEDEVSTATE_INSERVICE | LINEDEVSTATE_OUTOFSERVICE, 0));
  1070. /* --- Check if our device is in service, mrw,2/28/95 --- */
  1071. stLnDevStat.dwTotalSize = sizeof(stLnDevStat);
  1072. TRAP(lineGetLineDevStatus(hhDriver->hLine, &stLnDevStat));
  1073. if ((stLnDevStat.dwDevStatusFlags & LINEDEVSTATUSFLAGS_INSERVICE) == 0)
  1074. {
  1075. if (DialogBoxParam(glblQueryDllHinst(),
  1076. MAKEINTRESOURCE(IDD_CNCT_PCMCIA),
  1077. sessQueryHwnd(hhDriver->hSession), PCMCIADlg,
  1078. (LPARAM)hhDriver) == FALSE)
  1079. {
  1080. iRet = -2;
  1081. goto ERROR_EXIT;
  1082. }
  1083. }
  1084. /* --- Launch the dialing dialog, or go right into passthrough mode. --- */
  1085. if ((uFlags & CNCT_PORTONLY) == 0)
  1086. {
  1087. if (!IsWindow(hhDriver->hwndCnctDlg))
  1088. {
  1089. hhDriver->hwndCnctDlg = DoModelessDialog(glblQueryDllHinst(),
  1090. MAKEINTRESOURCE(IDD_DIALING), sessQueryHwnd(hhDriver->hSession),
  1091. DialingDlg, (LPARAM)hhDriver);
  1092. }
  1093. }
  1094. /* --- Make the call (oooh, how exciting!) --- */
  1095. memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
  1096. hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
  1097. hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  1098. hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  1099. if (uFlags & CNCT_PORTONLY)
  1100. hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  1101. if ((hhDriver->lMakeCallId = lineMakeCall(hhDriver->hLine,
  1102. &hhDriver->hCall, hhDriver->achDialableDest,
  1103. hhDriver->dwCountryCode, &hhDriver->stCallPar)) < 0)
  1104. {
  1105. #if defined(_DEBUG)
  1106. char ach[50];
  1107. wsprintf(ach, "lineMakeCall returned %x", hhDriver->lMakeCallId);
  1108. MessageBox (0, ach, "debug", MB_OK);
  1109. #endif
  1110. switch (hhDriver->lMakeCallId)
  1111. {
  1112. case LINEERR_BEARERMODEUNAVAIL:
  1113. case LINEERR_INVALBEARERMODE:
  1114. uidErr = IDS_ER_CNCT_PASSTHROUGH;
  1115. iRet = -6;
  1116. msgFlag = TRUE;
  1117. goto ERROR_EXIT;
  1118. case LINEERR_RESOURCEUNAVAIL:
  1119. case LINEERR_CALLUNAVAIL:
  1120. uidErr = IDS_ER_CNCT_CALLUNAVAIL;
  1121. iRet = -3;
  1122. msgFlag = TRUE;
  1123. goto ERROR_EXIT;
  1124. case LINEERR_DIALDIALTONE:
  1125. case LINEERR_DIALPROMPT:
  1126. if (DoDelayedCall(hhDriver) != 0)
  1127. {
  1128. iRet = -4;
  1129. msgFlag = TRUE;
  1130. goto ERROR_EXIT;
  1131. }
  1132. break;
  1133. default:
  1134. iRet = -5;
  1135. msgFlag = TRUE;
  1136. goto ERROR_EXIT;
  1137. }
  1138. }
  1139. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  1140. return 0;
  1141. /* --- Error exit --- */
  1142. ERROR_EXIT:
  1143. // Change this so that the dialog is destroyed before the
  1144. // error message is displayed. Otherwise, the timer that
  1145. // handled redials continued to pump a redial message once
  1146. // every second, causing HT to go into a very nasty loop. mpt 02SEP98
  1147. if (IsWindow(hhDriver->hwndCnctDlg))
  1148. {
  1149. EndModelessDialog(hhDriver->hwndCnctDlg);
  1150. hhDriver->hwndCnctDlg = 0;
  1151. }
  1152. if ( msgFlag )
  1153. {
  1154. LoadString(glblQueryDllHinst(), uidErr, ach, sizeof(ach) / sizeof(TCHAR));
  1155. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1156. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  1157. sessQueryTimeout(hhDriver->hSession));
  1158. }
  1159. return iRet;
  1160. }
  1161. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1162. * FUNCTION:
  1163. * cnctdrvConnect
  1164. *
  1165. * DESCRIPTION:
  1166. * Attempts to dial the modem.
  1167. *
  1168. * ARGUMENTS:
  1169. * hhDriver - private driver handle
  1170. * uFlags - connection flags
  1171. *
  1172. * RETURNS:
  1173. * 0 or error
  1174. *
  1175. */
  1176. int WINAPI cnctdrvConnect(const HHDRIVER hhDriver, const unsigned int uFlags)
  1177. {
  1178. TCHAR ach[FNAME_LEN];
  1179. #if defined(INCL_WINSOCK)
  1180. //
  1181. // MAX_IP_ADDR_LEN+11+1 = buffer size of hhDriver->achDestAddr +
  1182. // settings string "SET IPADDR=" + 1 for the terminating NULL
  1183. // character. REV 09/20/2000
  1184. //
  1185. TCHAR szInstruct[MAX_IP_ADDR_LEN+11+1]; // Used only for WinSock
  1186. TCHAR szResult[MAX_IP_ADDR_LEN+11+1]; // Used only for WinSock
  1187. int iNumChars;
  1188. #endif //defined (INCL_WINSOCK)
  1189. TCHAR achNewCnct[FNAME_LEN];
  1190. TCHAR achCom[MAX_PATH];
  1191. BOOL fGetNewName = FALSE;
  1192. HICON hIcon;
  1193. HCOM hCom;
  1194. int hIconId;
  1195. int fFlag;
  1196. unsigned int uidErr = IDS_ER_CNCT_TAPIFAILED;
  1197. if (hhDriver == 0)
  1198. {
  1199. assert(FALSE);
  1200. return CNCT_BAD_HANDLE;
  1201. }
  1202. /* --- Makes for easier referencing --- */
  1203. hCom = sessQueryComHdl(hhDriver->hSession);
  1204. /* --- Check to see we're not already connected --- */
  1205. if (cnctdrvQueryStatus(hhDriver) != CNCT_STATUS_FALSE)
  1206. return CNCT_ERROR;
  1207. // JMH 05-29-96 This is needed to prevent CLoop from processing
  1208. // activity on the terminal window while TAPI is connecting.
  1209. //
  1210. CLoopRcvControl(sessQueryCLoopHdl(hhDriver->hSession),
  1211. CLOOP_SUSPEND,
  1212. CLOOP_RB_CNCTDRV);
  1213. CLoopSndControl(sessQueryCLoopHdl(hhDriver->hSession),
  1214. CLOOP_SUSPEND,
  1215. CLOOP_SB_CNCTDRV);
  1216. /* --- Just on the off chance we still have an open line --- */
  1217. if (hhDriver->hLineApp && hhDriver->hLine)
  1218. {
  1219. lineClose(hhDriver->hLine);
  1220. memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
  1221. hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
  1222. hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  1223. hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  1224. hhDriver->stCallPar.dwBearerMode = 0;
  1225. hhDriver->hLine = 0;
  1226. }
  1227. if (hhDriver->hLineApp && hhDriver->dwLineCnt == 0 &&
  1228. (uFlags & CNCT_PORTONLY) == 0)
  1229. {
  1230. DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
  1231. sessQueryTimeout(hhDriver->hSession));
  1232. }
  1233. /* --- Ask for new session name only if needed --- */
  1234. sessQueryName(hhDriver->hSession, ach, sizeof(ach));
  1235. achNewCnct[0] = TEXT('\0');
  1236. LoadString(glblQueryDllHinst(), IDS_GNRL_NEW_CNCT, achNewCnct,
  1237. sizeof(achNewCnct) / sizeof(TCHAR));
  1238. if (ach[0] == TEXT('\0') || lstrcmp(achNewCnct, ach) == 0)
  1239. {
  1240. // This can only happen if the user double-clicks on the term.exe or
  1241. // there is no session name given on the command line.
  1242. // In this case give the "New Connection" name to the session.
  1243. //
  1244. sessSetName(hhDriver->hSession, achNewCnct);
  1245. if (!(uFlags & CNCT_PORTONLY))
  1246. fGetNewName = TRUE;
  1247. }
  1248. else if (uFlags & CNCT_NEW)
  1249. {
  1250. // This can only happen if the user selects 'File | New Connection'
  1251. // from the menus.
  1252. //
  1253. sessSetName(hhDriver->hSession, achNewCnct);
  1254. sessSetIsNewSession(hhDriver->hSession, TRUE);
  1255. }
  1256. #if defined (INCL_WINSOCK)
  1257. else if (uFlags & CNCT_WINSOCK)
  1258. {
  1259. //
  1260. // Make sure we don't overwrite the buffer. If the string
  1261. // is too long, then truncate to the hhDriver->achDestAddr
  1262. // size of MAX_AP_ADDR_LEN. REV 09/20/2000
  1263. //
  1264. StrCharCopyN(hhDriver->achDestAddr, ach, MAX_IP_ADDR_LEN);
  1265. hhDriver->achDestAddr[MAX_IP_ADDR_LEN - 1] = TEXT('\0');
  1266. hhDriver->dwPermanentLineId = DIRECT_COMWINSOCK;
  1267. }
  1268. #endif // defined (INCL_WINSOCK)
  1269. if (fGetNewName || (uFlags & CNCT_NEW))
  1270. {
  1271. if (DialogBoxParam(glblQueryDllHinst(), MAKEINTRESOURCE(IDD_NEWCONNECTION),
  1272. sessQueryHwnd(hhDriver->hSession), NewConnectionDlg,
  1273. (LPARAM)hhDriver->hSession) == FALSE)
  1274. {
  1275. if (uFlags & CNCT_NEW)
  1276. {
  1277. sessQueryOldName(hhDriver->hSession, ach, sizeof(ach));
  1278. sessSetName(hhDriver->hSession, ach);
  1279. sessSetIsNewSession(hhDriver->hSession, FALSE);
  1280. }
  1281. goto ERROR_EXIT;
  1282. }
  1283. else
  1284. {
  1285. if (uFlags & CNCT_NEW)
  1286. {
  1287. sessQueryName(hhDriver->hSession, ach, sizeof(ach));
  1288. hIcon = sessQueryIcon(hhDriver->hSession);
  1289. hIconId = sessQueryIconID(hhDriver->hSession);
  1290. ReinitializeSessionHandle(hhDriver->hSession, FALSE);
  1291. CLoopSndControl(sessQueryCLoopHdl(hhDriver->hSession),
  1292. CLOOP_SUSPEND,
  1293. CLOOP_SB_CNCTDRV);
  1294. sessSetName(hhDriver->hSession, ach);
  1295. sessSetIconID(hhDriver->hSession, hIconId);
  1296. }
  1297. }
  1298. }
  1299. /* --- Load the Standard Com drivers --- */
  1300. ComLoadStdcomDriver(hCom);
  1301. // There are a bunch of conditions that can trigger the
  1302. // phone dialog.
  1303. //
  1304. fFlag = FALSE;
  1305. // If no phone number, bring up new phone dialog here
  1306. // Unless we have a direct to com port selected
  1307. //
  1308. // Don't display the dialog if we are answering, because
  1309. // we don't need a phone number. - cab:11/19/96
  1310. //
  1311. if (!IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
  1312. hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE &&
  1313. !(uFlags & (CNCT_PORTONLY | CNCT_ANSWER)))
  1314. {
  1315. #ifdef INCL_WINSOCK
  1316. // If the driver is WinSock, then check for a
  1317. // destination IP address. - cab:11/19/96
  1318. //
  1319. if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK &&
  1320. hhDriver->achDestAddr[0] == TEXT('\0'))
  1321. {
  1322. fFlag = TRUE;
  1323. }
  1324. #endif // defined (INCL_WINSOCK)
  1325. // If the driver isn't WinSock, then we must be using
  1326. // TAPI, so check for a destination phone number. - cab:11/19/96
  1327. //
  1328. if (hhDriver->dwPermanentLineId != DIRECT_COMWINSOCK &&
  1329. (hhDriver->achDest[0] == TEXT('\0') ||
  1330. hhDriver->achDialableDest[0] == TEXT('\0') ||
  1331. hhDriver->achCanonicalDest[0] == TEXT('\0')))
  1332. {
  1333. fFlag = TRUE;
  1334. }
  1335. }
  1336. // New connections trigger this dialog
  1337. //
  1338. if (uFlags & CNCT_NEW)
  1339. fFlag = TRUE;
  1340. // If the modem/port we saved no longer exists
  1341. //
  1342. //if (!hhDriver->fMatchedPermanentLineID)
  1343. // fFlag = TRUE;
  1344. // Note: Passing the property sheet page here because property
  1345. // sheets use same code and don't have access directly
  1346. // to the private driver handle. Upper wacker will have
  1347. // to address the problem differently - mrw.
  1348. if (fFlag)
  1349. {
  1350. PROPSHEETPAGE psp;
  1351. // Before you go and critize this goto target come talk to
  1352. // me. There are enough things going on here that a goto
  1353. // is warranted in my humble opinion. - mrw
  1354. NEWPHONEDLG:
  1355. psp.lParam = (LPARAM)hhDriver->hSession;
  1356. if (DialogBoxParam(glblQueryDllHinst(),
  1357. MAKEINTRESOURCE(IDD_CNCT_NEWPHONE),
  1358. sessQueryHwnd(hhDriver->hSession), NewPhoneDlg,
  1359. (LPARAM)&psp) == FALSE)
  1360. {
  1361. goto ERROR_EXIT;
  1362. }
  1363. else if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) ||
  1364. (IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE))
  1365. {
  1366. //
  1367. // See if the "Configure..." button has already been clicked
  1368. // and the ComDeviceDialog() function has already been called
  1369. // for this COM device.
  1370. //
  1371. TCHAR szPortName[MAX_PATH];
  1372. ComGetPortName(hCom, szPortName, MAX_PATH);
  1373. if (StrCharCmp(szPortName, hhDriver->achComDeviceName) != 0 )
  1374. {
  1375. /* --- Bring up the port configure dialog --- */
  1376. if (hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
  1377. {
  1378. ComSetPortName(hCom, hhDriver->achComDeviceName);
  1379. }
  1380. else
  1381. {
  1382. wsprintf(ach, TEXT("COM%d"),
  1383. hhDriver->dwPermanentLineId - DIRECT_COM1 + 1);
  1384. ComSetPortName(hCom, ach);
  1385. }
  1386. //
  1387. // Get the current defaults for the serial port.
  1388. //
  1389. if (ComDriverSpecial(hCom, "GET Defaults", NULL, 0) != COM_OK)
  1390. {
  1391. if (ComDeviceDialog(hCom, sessQueryHwnd(hhDriver->hSession))
  1392. != COM_OK)
  1393. {
  1394. goto ERROR_EXIT;
  1395. }
  1396. }
  1397. if (ComDeviceDialog(hCom, sessQueryHwnd(hhDriver->hSession))
  1398. != COM_OK)
  1399. {
  1400. // User canceled
  1401. // --jcm 3-2-95
  1402. //return CNCT_BAD_HANDLE;
  1403. }
  1404. }
  1405. }
  1406. #if defined(INCL_WINSOCK) // mrw:3/5/96
  1407. else if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
  1408. {
  1409. if (hhDriver->achDestAddr[0] == TEXT('\0'))
  1410. {
  1411. LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_MISSING_ADDR,
  1412. ach, sizeof(ach) / sizeof(TCHAR));
  1413. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1414. MB_OK | MB_ICONINFORMATION,
  1415. sessQueryTimeout(hhDriver->hSession));
  1416. goto NEWPHONEDLG;
  1417. }
  1418. }
  1419. #endif
  1420. else
  1421. {
  1422. // mrw: Check that we have valid data.
  1423. //
  1424. if (hhDriver->achDest[0] == TEXT('\0'))
  1425. {
  1426. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_BADADDRESS, ach,
  1427. sizeof(ach) / sizeof(TCHAR));
  1428. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1429. MB_OK | MB_ICONINFORMATION,
  1430. sessQueryTimeout(hhDriver->hSession));
  1431. // goto ERROR_EXIT; // mrw:3/5/96
  1432. goto NEWPHONEDLG; // mrw:3/5/96
  1433. }
  1434. }
  1435. }
  1436. /* --- Enumerate lines, picks default (set in hhDriver->dwLine) --- */
  1437. if ( IsNT() )
  1438. {
  1439. if (EnumerateLinesNT(hhDriver, 0) != 0)
  1440. {
  1441. assert(FALSE);
  1442. goto MSG_EXIT;
  1443. }
  1444. }
  1445. else
  1446. {
  1447. if (EnumerateLines(hhDriver, 0) != 0)
  1448. {
  1449. assert(FALSE);
  1450. goto MSG_EXIT;
  1451. }
  1452. }
  1453. /* --- If we don't match any TAPI lines, go back to new phone --- */
  1454. if (hhDriver->dwLine == (DWORD)-1)
  1455. {
  1456. //
  1457. // If this is not a modem (it is a COM port), then display the modem
  1458. // wizard, otherwise just go back to the new phone. REV: 11/1/2001
  1459. //
  1460. if (!IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
  1461. hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE )
  1462. {
  1463. DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
  1464. sessQueryTimeout(hhDriver->hSession));
  1465. }
  1466. goto NEWPHONEDLG;
  1467. }
  1468. /* --- Redraw window now so dialogs don't overlap ---- */
  1469. UpdateWindow(sessQueryHwnd(hhDriver->hSession));
  1470. /* --- Check if we're doing a direct connect or using passthrough mode --- */
  1471. if (IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
  1472. {
  1473. int iActivatePortReturn = IDS_ER_CNCT_PORTFAILED;
  1474. if (TRAP(ComSetPortName(hCom, hhDriver->achComDeviceName)) != COM_OK ||
  1475. (iActivatePortReturn = TRAP(ComActivatePort(hCom, 0))) != COM_OK)
  1476. {
  1477. if (iActivatePortReturn == COM_PORT_IN_USE)
  1478. {
  1479. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_CALLUNAVAIL,
  1480. ach, sizeof(ach) / sizeof(TCHAR));
  1481. }
  1482. else
  1483. {
  1484. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED,
  1485. achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
  1486. wsprintf(ach, achNewCnct, hhDriver->achComDeviceName);
  1487. }
  1488. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1489. MB_OK | MB_ICONINFORMATION,
  1490. sessQueryTimeout(hhDriver->hSession));
  1491. return -1;
  1492. }
  1493. else
  1494. {
  1495. if (uFlags & CNCT_ANSWER)
  1496. {
  1497. SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
  1498. }
  1499. else
  1500. {
  1501. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  1502. }
  1503. }
  1504. //
  1505. // Allow PASSTHROUGH on serial ports as well so that the session
  1506. // will not be disconnected with loss of carrier. REV: 11/6/2001
  1507. //
  1508. if (uFlags & CNCT_PORTONLY)
  1509. {
  1510. hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  1511. }
  1512. cnctdrvComEvent(hhDriver, CONNECT);
  1513. return COM_OK;
  1514. }
  1515. else if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4))
  1516. {
  1517. int iActivatePortReturn = IDS_ER_CNCT_PORTFAILED;
  1518. wsprintf(achCom, TEXT("COM%d"), hhDriver->dwPermanentLineId -
  1519. DIRECT_COM1 + 1);
  1520. if (TRAP(ComSetPortName(hCom, achCom)) != COM_OK ||
  1521. (iActivatePortReturn = TRAP(ComActivatePort(hCom, 0))) != COM_OK)
  1522. {
  1523. if (iActivatePortReturn == COM_PORT_IN_USE)
  1524. {
  1525. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_CALLUNAVAIL,
  1526. ach, sizeof(ach) / sizeof(TCHAR));
  1527. }
  1528. else
  1529. {
  1530. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED,
  1531. achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
  1532. wsprintf(ach, achNewCnct, achCom);
  1533. }
  1534. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1535. MB_OK | MB_ICONINFORMATION,
  1536. sessQueryTimeout(hhDriver->hSession));
  1537. return -1;
  1538. }
  1539. else
  1540. {
  1541. if (uFlags & CNCT_ANSWER)
  1542. {
  1543. SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
  1544. }
  1545. else
  1546. {
  1547. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  1548. }
  1549. }
  1550. //
  1551. // Allow PASSTHROUGH on serial ports as well so that the session
  1552. // will not be disconnected with loss of carrier. REV: 11/6/2001
  1553. //
  1554. if (uFlags & CNCT_PORTONLY)
  1555. {
  1556. hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
  1557. }
  1558. cnctdrvComEvent(hhDriver, CONNECT);
  1559. return COM_OK;
  1560. }
  1561. #if defined(INCL_WINSOCK)
  1562. else if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
  1563. {
  1564. int iPort;
  1565. /* --- Load the Winsock Com drivers --- */
  1566. ComLoadWinsockDriver(hCom);
  1567. // Baud rate, etc. are meaningless for TCP/IP connections
  1568. //
  1569. ComSetAutoDetect(hCom, FALSE);
  1570. iPort = sessQueryTelnetPort(hhDriver->hSession);
  1571. if (iPort != 0)
  1572. hhDriver->iPort = iPort;
  1573. PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
  1574. SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
  1575. #if 0 //DEADWOOD:jmh 3/24/97 Yes, we really want auto-detection, even in telnet!
  1576. // Auto-detection of emulator type is redundant, since we tell
  1577. // the telnet host what type we want. Seems like ANSI is the
  1578. // most likely choice.
  1579. hEmu = sessQueryEmuHdl(hhDriver->hSession);
  1580. if (emuQueryEmulatorId(hEmu) == EMU_AUTO)
  1581. {
  1582. emuLoad(hEmu, EMU_VT100);
  1583. #if defined(INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID)
  1584. // Make sure the telnet terminal id is correct. - cab:11/18/96
  1585. //
  1586. emuLoadDefaultTelnetId(hEmu);
  1587. #endif // defined(INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID)
  1588. PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
  1589. SBR_NTFY_REFRESH, (WPARAM)SBR_EMU_PART_NO, 0);
  1590. }
  1591. #endif // 0
  1592. #if defined(INCL_CALL_ANSWERING)
  1593. if (uFlags & CNCT_ANSWER)
  1594. {
  1595. wsprintf(szInstruct, "SET ANSWER=1");
  1596. }
  1597. else
  1598. {
  1599. wsprintf(szInstruct, "SET ANSWER=0");
  1600. }
  1601. ComDriverSpecial(hCom, szInstruct, szResult, sizeof(szResult) / sizeof(TCHAR));
  1602. #endif // defined(INCL_CALL_ANSWERING)
  1603. /* --- Do ComDriverSpecial calls to send the IP address & port number
  1604. to the comm driver */
  1605. //
  1606. // Make sure we don't overwrite the buffer. If the string
  1607. // is too long, then truncate to the hhDriver->achDestAddr
  1608. // size of MAX_AP_ADDR_LEN. REV 09/20/2000
  1609. //
  1610. StrCharCopyN(szInstruct, TEXT("SET IPADDR="), sizeof(szInstruct) / sizeof(TCHAR));
  1611. iNumChars = StrCharGetStrLength(szInstruct);
  1612. StrCharCopyN(&szInstruct[iNumChars], hhDriver->achDestAddr,
  1613. sizeof(szInstruct)/sizeof(TCHAR) - iNumChars);
  1614. //
  1615. // Make sure the string is null terminated.
  1616. //
  1617. szInstruct[sizeof(szInstruct)/sizeof(TCHAR) - 1]=TEXT('\0');
  1618. ComDriverSpecial(hCom, szInstruct, szResult,
  1619. sizeof(szResult) / sizeof(TCHAR));
  1620. wsprintf(szInstruct, "SET PORTNUM=%ld", hhDriver->iPort);
  1621. ComDriverSpecial(hCom, szInstruct,
  1622. szResult, sizeof(szResult) / sizeof(TCHAR));
  1623. #if defined(INCL_CALL_ANSWERING)
  1624. if (uFlags & CNCT_ANSWER)
  1625. {
  1626. SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
  1627. }
  1628. else
  1629. {
  1630. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  1631. }
  1632. #else // defined(INCL_CALL_ANSWERING)
  1633. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  1634. #endif // defined(INCL_CALL_ANSWERING)
  1635. /* --- Activate the port ---*/
  1636. if (ComActivatePort(hCom, 0) != COM_OK)
  1637. {
  1638. LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_FAILURE,
  1639. achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
  1640. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  1641. MB_OK | MB_ICONINFORMATION,
  1642. sessQueryTimeout(hhDriver->hSession));
  1643. return -1;
  1644. }
  1645. else
  1646. {
  1647. return COM_OK;
  1648. }
  1649. }
  1650. #endif // defined(INCL_WINSOCK)
  1651. /* --- Display confimation dialog if requested --- */
  1652. if ((uFlags & (CNCT_PORTONLY | CNCT_DIALNOW | CNCT_ANSWER)) == 0)
  1653. {
  1654. if (DialogBoxParam(glblQueryDllHinst(),
  1655. MAKEINTRESOURCE(IDD_CNCT_CONFIRM),
  1656. sessQueryHwnd(hhDriver->hSession), ConfirmDlg,
  1657. (LPARAM)hhDriver) == FALSE)
  1658. {
  1659. goto ERROR_EXIT;
  1660. }
  1661. }
  1662. // Either make the call or wait for a call.
  1663. //
  1664. if (uFlags & CNCT_ANSWER)
  1665. {
  1666. if (DoAnswerCall(hhDriver) != 0)
  1667. {
  1668. goto ERROR_EXIT;
  1669. }
  1670. }
  1671. else
  1672. {
  1673. if (DoMakeCall(hhDriver, uFlags) != 0)
  1674. {
  1675. goto ERROR_EXIT;
  1676. }
  1677. }
  1678. ComSetAutoDetect(hCom, FALSE);
  1679. PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
  1680. SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
  1681. return 0;
  1682. /* --- Message exit --- */
  1683. MSG_EXIT:
  1684. LoadString(glblQueryDllHinst(), uidErr, ach, sizeof(ach) / sizeof(TCHAR));
  1685. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach,
  1686. NULL, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  1687. sessQueryTimeout(hhDriver->hSession));
  1688. /* --- Error exit --- */
  1689. ERROR_EXIT:
  1690. if (hhDriver->hLineApp && hhDriver->hLine)
  1691. {
  1692. lineClose(hhDriver->hLine);
  1693. memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
  1694. hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
  1695. hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  1696. hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  1697. hhDriver->stCallPar.dwBearerMode = 0;
  1698. hhDriver->hLine = 0;
  1699. }
  1700. SetStatus(hhDriver, CNCT_STATUS_FALSE);
  1701. return CNCT_ERROR;
  1702. }
  1703. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1704. * FUNCTION:
  1705. * DoDelayedCall
  1706. *
  1707. * DESCRIPTION:
  1708. * Check the section under Delayed Dialing in the programmers guide to
  1709. * TAPI. Basicly, if the service provider does not provide dialtone
  1710. * support, then we have to break of the dialable string format into
  1711. * pieces and prompt the user.
  1712. *
  1713. * ARGUMENTS:
  1714. * hhDriver - private driver handle.
  1715. *
  1716. * RETURNS:
  1717. * 0=OK, else error.
  1718. *
  1719. * AUTHOR: Mike Ward, 20-Apr-1995
  1720. */
  1721. static int DoDelayedCall(const HHDRIVER hhDriver)
  1722. {
  1723. TCHAR ach[256];
  1724. TCHAR ach2[256];
  1725. TCHAR *pach;
  1726. long lDialRet;
  1727. #define DIAL_DELIMITERS "Ww@$?"
  1728. hhDriver->lMakeCallId = -1;
  1729. lstrcpy(ach, hhDriver->achDialableDest);
  1730. if ((pach = strtok(ach, DIAL_DELIMITERS)) == 0)
  1731. return -1;
  1732. while (pach)
  1733. {
  1734. lstrcpy(ach2, pach);
  1735. // If this is the last segment of the string, don't append the
  1736. // semicolon.
  1737. //
  1738. if ((pach = strtok(NULL, DIAL_DELIMITERS)) != 0)
  1739. lstrcat(ach2, ";");
  1740. if (hhDriver->lMakeCallId < 0)
  1741. {
  1742. // By appending a semicolon to the dialable string, we're
  1743. // telling lineMakeCall that more is on the way.
  1744. //
  1745. if ((hhDriver->lMakeCallId = lineMakeCall(hhDriver->hLine,
  1746. &hhDriver->hCall, ach2, hhDriver->dwCountryCode,
  1747. &hhDriver->stCallPar)) < 0)
  1748. {
  1749. #if defined(_DEBUG)
  1750. char ach[50];
  1751. wsprintf(ach, "DoDelayedCall returned %x", hhDriver->lMakeCallId);
  1752. MessageBox(GetFocus(), ach, "debug", MB_OK);
  1753. #endif
  1754. return -3;
  1755. }
  1756. }
  1757. else
  1758. {
  1759. // Once we have a call handle we have to use lineDial to complete
  1760. // the call.
  1761. //
  1762. if ((lDialRet = lineDial(hhDriver->hCall, ach2,
  1763. hhDriver->dwCountryCode)) < 0)
  1764. {
  1765. #if defined(_DEBUG)
  1766. char ach[50];
  1767. wsprintf(ach, "lineDial returned %x", lDialRet);
  1768. MessageBox(GetFocus(), ach, "debug", MB_OK);
  1769. #endif
  1770. return -4;
  1771. }
  1772. }
  1773. // The user has to tell us when the we can continue dialing
  1774. //
  1775. if (pach != 0)
  1776. {
  1777. LoadString(glblQueryDllHinst(), IDS_CNCT_DELAYEDDIAL, ach2,
  1778. sizeof(ach2) / sizeof(TCHAR));
  1779. if (TimedMessageBox(hhDriver->hwndCnctDlg, ach2, NULL,
  1780. MB_OKCANCEL | MB_ICONINFORMATION | MB_TASKMODAL,
  1781. sessQueryTimeout(hhDriver->hSession)) != IDOK)
  1782. {
  1783. return -4;
  1784. }
  1785. }
  1786. }
  1787. return 0;
  1788. }
  1789. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1790. * FUNCTION:
  1791. * cnctdrvDisconnect
  1792. *
  1793. * DESCRIPTION:
  1794. * Signals a disconnect
  1795. *
  1796. * ARGUMENTS:
  1797. * hhDriver - private driver handle
  1798. * uFlags - disconnect flags
  1799. *
  1800. * RETURNS:
  1801. * 0 or error
  1802. *
  1803. */
  1804. int WINAPI cnctdrvDisconnect(const HHDRIVER hhDriver, const unsigned int uFlags)
  1805. {
  1806. LONG lLineDropId;
  1807. #if defined(INCL_REDIAL_ON_BUSY)
  1808. HKEY hKey;
  1809. DWORD dwSize;
  1810. BYTE ab[20];
  1811. #endif
  1812. XD_TYPE* pX;
  1813. int nReturnVal = 0;
  1814. TCHAR ach[256];
  1815. if (hhDriver == 0)
  1816. {
  1817. assert(FALSE);
  1818. return CNCT_BAD_HANDLE;
  1819. }
  1820. //
  1821. // Cancel any active file transfers that are currently executing.
  1822. // REV: 02/01/2001
  1823. //
  1824. pX = (XD_TYPE*)sessQueryXferHdl(hhDriver->hSession);
  1825. if (pX != NULL && pX->hwndXfrDisplay != NULL &&
  1826. IsWindow(pX->hwndXfrDisplay) && pX->nDirection != XFER_NONE)
  1827. {
  1828. int nCancelTransfer = IDYES;
  1829. if (uFlags & CNCT_XFERABORTCONFIRM)
  1830. {
  1831. //
  1832. // Prompt to cancel the file transfer. REV: 02/16/2001
  1833. //
  1834. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_ACTIVETRANSFER, ach, sizeof(ach) / sizeof(TCHAR));
  1835. nCancelTransfer = TimedMessageBox(pX->hwndXfrDisplay, ach, NULL,
  1836. MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1837. sessQueryTimeout(hhDriver->hSession));
  1838. }
  1839. if (nCancelTransfer == IDYES || nCancelTransfer == -1)
  1840. {
  1841. unsigned int uNewFlags = uFlags;
  1842. if (uFlags & CNCT_LOSTCARRIER)
  1843. {
  1844. //
  1845. // NOTE: We should only have to tell the XFER to abort here.
  1846. // It should not be dependent on a message to a dialog.
  1847. //
  1848. PostMessage(pX->hwndXfrDisplay, WM_COMMAND, XFER_LOST_CARRIER, 0L);
  1849. }
  1850. else if (uFlags & CNCT_XFERABORTCONFIRM)
  1851. {
  1852. //
  1853. // NOTE: We should only have to tell the XFER to abort here.
  1854. // It should not be dependent on a message to a dialog.
  1855. //
  1856. PostMessage(pX->hwndXfrDisplay, WM_COMMAND, XFR_SHUTDOWN, 0L);
  1857. }
  1858. //
  1859. // We can't exit until the file transfer exits, so post a
  1860. // message to try to disconnect again. Make sure to turn
  1861. // of the CNCT_XFERABORTCONFIRM flag as we don't want to
  1862. // prompt the kill the transfer again.
  1863. //
  1864. uNewFlags &= ~CNCT_XFERABORTCONFIRM;
  1865. //
  1866. // We must post a message to disconnect because we are
  1867. // waiting for the file transfer to cancel. We have to
  1868. // post a message otherwise we will get into a deadlock
  1869. // situation. This is not the best way to accomplish
  1870. // this as we may be posting a lot of messages to the
  1871. // session window and there is a potential for the
  1872. // file transfer to not respond quickly causing the
  1873. // disconnect to loop. Eventually, the file transfer
  1874. // will cancel, or will timeout and cancel, so we will
  1875. // not get into an endless loop. REV: 06/22/2001
  1876. //
  1877. //
  1878. // Wait half a second before posting this message so we don't
  1879. // flood ourselves with disconnect messages. REV: 4/25/2002
  1880. //
  1881. Sleep(500);
  1882. PostDisconnect(hhDriver, uNewFlags);
  1883. }
  1884. //
  1885. // Return an status that the current file transfer must be
  1886. // canceled (or is in the process of being canceled). We
  1887. // cannot disconnect until the transfer is complete.
  1888. //
  1889. return XFR_SHUTDOWN;
  1890. }
  1891. #ifdef INCL_CALL_ANSWERING
  1892. // Unregister our cloop callback.
  1893. //
  1894. if (hhDriver->pvUnregister)
  1895. {
  1896. CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
  1897. hhDriver->pvUnregister = 0;
  1898. }
  1899. #endif
  1900. ComDeactivatePort(sessQueryComHdl(hhDriver->hSession));
  1901. if (hhDriver->hCall)
  1902. {
  1903. SetStatus(hhDriver, CNCT_STATUS_DISCONNECTING);
  1904. if ((lLineDropId = lineDrop(hhDriver->hCall, 0, 0)) < 0)
  1905. assert(FALSE);
  1906. hhDriver->hCall = 0;
  1907. // If the drop is completing asychronously, save the flags and
  1908. // wait for the call status to go idle.
  1909. //
  1910. if (lLineDropId > 0)
  1911. {
  1912. hhDriver->uDiscnctFlags = uFlags;
  1913. return 0;
  1914. }
  1915. }
  1916. SetStatus(hhDriver, CNCT_STATUS_FALSE);
  1917. if ((uFlags & DISCNCT_NOBEEP) == 0)
  1918. sessBeeper(hhDriver->hSession);
  1919. //mpt:10-28-97 added exit upon disconnect feature
  1920. if ((uFlags & DISCNCT_EXIT))
  1921. PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CLOSE, 0, 0);
  1922. if (hhDriver->hLine)
  1923. {
  1924. lineClose(hhDriver->hLine);
  1925. memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
  1926. hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
  1927. hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  1928. hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
  1929. hhDriver->stCallPar.dwBearerMode = 0;
  1930. hhDriver->hLine = 0;
  1931. }
  1932. if (uFlags & CNCT_DIALNOW)
  1933. {
  1934. #if defined(INCL_REDIAL_ON_BUSY)
  1935. if (hhDriver->fRedialOnBusy && hhDriver->iRedialCnt > 0)
  1936. {
  1937. hhDriver->uDiscnctFlags = uFlags;
  1938. hhDriver->iRedialSecsRemaining = 2;
  1939. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1940. "SOFTWARE\\Microsoft\\HyperTerminal\\TimeToRedial", 0, KEY_READ,
  1941. &hKey) == ERROR_SUCCESS)
  1942. {
  1943. dwSize = sizeof(ab);
  1944. if (RegQueryValueEx(hKey, "", 0, 0, ab, &dwSize) == ERROR_SUCCESS)
  1945. hhDriver->iRedialSecsRemaining = atoi(ab);
  1946. RegCloseKey(hKey);
  1947. }
  1948. SetTimer(hhDriver->hwndCnctDlg, 1, 1000, 0);
  1949. }
  1950. else
  1951. {
  1952. PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CNCT_DIALNOW,
  1953. uFlags, 0);
  1954. }
  1955. #else
  1956. PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CNCT_DIALNOW,
  1957. uFlags, 0);
  1958. #endif
  1959. }
  1960. else
  1961. {
  1962. // If we're not auto redialing, reset the dial count. - mrw:10/10/95
  1963. //
  1964. hhDriver->iRedialCnt = 0;
  1965. }
  1966. return nReturnVal;
  1967. }
  1968. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  1969. * FUNCTION:
  1970. * lineCallbackFunc
  1971. *
  1972. * DESCRIPTION:
  1973. * Function TAPI calls to handle asynchronous events
  1974. *
  1975. * ARGUMENTS:
  1976. * see TAPI.H
  1977. *
  1978. * RETURNS:
  1979. * void
  1980. *
  1981. */
  1982. void CALLBACK lineCallbackFunc(DWORD hDevice, DWORD dwMsg, DWORD_PTR dwCallback,
  1983. DWORD_PTR dwParm1, DWORD_PTR dwParm2, DWORD_PTR dwParm3)
  1984. {
  1985. const HHDRIVER hhDriver = (HHDRIVER)dwCallback;
  1986. int id;
  1987. unsigned int uFlags;
  1988. #if 0
  1989. {
  1990. char ach[256];
  1991. wsprintf(ach,"%x %x", dwMsg, dwParm1);
  1992. MessageBox(NULL, ach, "debug", MB_OK);
  1993. }
  1994. #endif
  1995. switch (dwMsg)
  1996. {
  1997. case LINE_REPLY:
  1998. if ((LONG)dwParm1 == hhDriver->lMakeCallId)
  1999. {
  2000. hhDriver->lMakeCallId = 0;
  2001. if ((LONG)dwParm2 != 0) // zero indicates success
  2002. {
  2003. switch (dwParm2)
  2004. {
  2005. case LINEERR_CALLUNAVAIL:
  2006. id = IDS_DIAL_NODIALTONE;
  2007. break;
  2008. default:
  2009. id = IDS_DIAL_DISCONNECTED;
  2010. break;
  2011. }
  2012. cnctdrvDisconnect(hhDriver, 0);
  2013. DialingMessage(hhDriver, id);
  2014. }
  2015. }
  2016. break;
  2017. case LINE_LINEDEVSTATE:
  2018. DbgOutStr("LINEDEVSTATE_DISCONNECTED 0x%x\r\n", dwParm1, 0, 0, 0, 0);
  2019. switch (dwParm1)
  2020. {
  2021. case PHONESTATE_CAPSCHANGE:
  2022. //
  2023. // If we are currently disconnected, then reset.
  2024. //
  2025. if (hhDriver != NULL && hhDriver->iStatus != CNCT_STATUS_FALSE)
  2026. break;
  2027. case LINEDEVSTATE_REINIT:
  2028. case PHONESTATE_REINIT:
  2029. if (hhDriver == 0)
  2030. {
  2031. // Until we open a line, we don't have a driver handle
  2032. // since we can't pass one during lineInitialize().
  2033. // This turns out to be a good time to reinit if we get
  2034. // notified to do so however, so it has use.
  2035. //
  2036. if (tapiReinit(gbl_hhDriver) != 0)
  2037. tapiReinitMessage(gbl_hhDriver);
  2038. }
  2039. else
  2040. {
  2041. tapiReinitMessage(hhDriver);
  2042. }
  2043. break;
  2044. case LINEDEVSTATE_INSERVICE:
  2045. // If we are showing our PCMCIA dialog prompting the user
  2046. // to insert the card, we post a message to dismiss the
  2047. // dialog once they insert it. - mrw,2/28/95
  2048. //
  2049. if (IsWindow(hhDriver->hwndPCMCIA))
  2050. {
  2051. PostMessage(hhDriver->hwndPCMCIA, WM_COMMAND,
  2052. MAKEWPARAM(IDOK, 0), (LPARAM)hhDriver->hwndPCMCIA);
  2053. }
  2054. break;
  2055. case LINEDEVSTATE_OUTOFSERVICE:
  2056. // Means they yanked the PCMCIA card - mrw,2/28/95
  2057. //
  2058. cnctdrvDisconnect(hhDriver, 0);
  2059. break;
  2060. case LINEDEVSTATE_RINGING:
  2061. // When the current ring count (as told by dwParam3) equals
  2062. // or exceeds the rings to answer on then we'll do the answer
  2063. // using the hhdriver->hCall handle we cached during the
  2064. // LINECALLSTATE_BURNTOFFERING notification. - rjk. 07-31-96
  2065. //
  2066. if ((hhDriver->lMakeCallId = lineAnswer(hhDriver->hCall,0,0)) >= 0)
  2067. {
  2068. SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
  2069. }
  2070. break;
  2071. case LINEDEVSTATE_CLOSE:
  2072. case PHONESTATE_DISCONNECTED:
  2073. //
  2074. // Another application has disconnected this device. REV: 04/27/2001
  2075. //
  2076. uFlags = CNCT_DIALNOW | CNCT_NOCONFIRM;
  2077. id = IDS_DIAL_DISCONNECTED;
  2078. PostDisconnect(hhDriver, uFlags);
  2079. DialingMessage(hhDriver, id);
  2080. break;
  2081. default:
  2082. break;
  2083. }
  2084. break; // case LINE_LINEDEVSTATE
  2085. case LINE_CREATE: // Sent when new modem is added
  2086. assert(0); // So I know it happened
  2087. // A remote possibilility exists that if two modems were created
  2088. // back to back, that the LINE_CREATE's would come out of order.
  2089. // T. Nixon suggests that we bump the line count by the dwParm1
  2090. // parameter plus one only when it is greater than or equal to
  2091. // the current line count. - mrw
  2092. //
  2093. if (dwParm1 >= gbl_hhDriver->dwLineCnt)
  2094. gbl_hhDriver->dwLineCnt = (DWORD)(dwParm1 + 1);
  2095. break;
  2096. case LINE_CALLSTATE:
  2097. DbgOutStr("LINECALLSTATE 0x%x\r\n", dwParm1, 0, 0, 0, 0);
  2098. switch ((LONG)dwParm1)
  2099. {
  2100. case LINECALLSTATE_OFFERING:
  2101. DialingMessage(hhDriver, IDS_DIAL_OFFERING);
  2102. // Windows sends us this message only one time while receiving
  2103. // a call and that is on the very first ring. See the code
  2104. // that responds to the LINEDEVSTATE_RINGING to see how the call
  2105. // gets answered. - rjk. 07-31-96
  2106. //
  2107. hhDriver->hCall = (HCALL)hDevice;
  2108. break;
  2109. case LINECALLSTATE_DIALTONE:
  2110. DialingMessage(hhDriver, IDS_DIAL_DIALTONE);
  2111. break;
  2112. case LINECALLSTATE_DIALING:
  2113. DialingMessage(hhDriver, IDS_DIAL_DIALING);
  2114. break;
  2115. case LINECALLSTATE_RINGBACK:
  2116. DialingMessage(hhDriver, IDS_DIAL_RINGBACK);
  2117. break;
  2118. case LINECALLSTATE_BUSY:
  2119. DialingMessage(hhDriver, IDS_DIAL_BUSY);
  2120. EnableDialNow(hhDriver->hwndCnctDlg, TRUE);
  2121. uFlags = DISCNCT_NOBEEP;
  2122. #if defined(INCL_REDIAL_ON_BUSY)
  2123. if (hhDriver->fRedialOnBusy && hhDriver->iRedialCnt++ < REDIAL_MAX)
  2124. uFlags = CNCT_DIALNOW | CNCT_NOCONFIRM | DISCNCT_NOBEEP;
  2125. #endif
  2126. PostDisconnect(hhDriver, uFlags);
  2127. break;
  2128. case LINECALLSTATE_CONNECTED:
  2129. DialingMessage(hhDriver, IDS_DIAL_CONNECTED);
  2130. if (Handoff(hhDriver) != 0)
  2131. {
  2132. PostDisconnect(hhDriver, 0);
  2133. }
  2134. else
  2135. {
  2136. if (IsWindow(hhDriver->hwndCnctDlg))
  2137. {
  2138. // Closes the dialing dialog
  2139. PostMessage(hhDriver->hwndCnctDlg, WM_USER+0x100, 0, 0);
  2140. }
  2141. SetStatus(hhDriver, CNCT_STATUS_TRUE);
  2142. }
  2143. break;
  2144. case LINECALLSTATE_DISCONNECTED:
  2145. DbgOutStr("LINECALLSTATE_DISCONNECTED 0x%x\r\n", dwParm2, 0, 0, 0, 0);
  2146. uFlags = 0;
  2147. if (dwParm2 & LINEDISCONNECTMODE_BUSY)
  2148. {
  2149. id = IDS_DIAL_BUSY;
  2150. #if defined(INCL_REDIAL_ON_BUSY)
  2151. if (hhDriver->fRedialOnBusy &&
  2152. hhDriver->iRedialCnt++ < REDIAL_MAX)
  2153. {
  2154. // Wait to let slower phone systems catchup - mrw 2/29/96
  2155. //
  2156. uFlags |= CNCT_DIALNOW|CNCT_NOCONFIRM|DISCNCT_NOBEEP;
  2157. }
  2158. #endif
  2159. }
  2160. else if (dwParm2 & LINEDISCONNECTMODE_NOANSWER)
  2161. id = IDS_DIAL_NOANSWER;
  2162. else if (dwParm2 & LINEDISCONNECTMODE_NODIALTONE)
  2163. id = IDS_DIAL_NODIALTONE;
  2164. else
  2165. {
  2166. id = IDS_DIAL_DISCONNECTED;
  2167. //mpt:10-28-97 added exit upon disconnect feature
  2168. uFlags |= ( sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 );
  2169. }
  2170. PostDisconnect(hhDriver, uFlags);
  2171. DialingMessage(hhDriver, id);
  2172. break;
  2173. case LINECALLSTATE_IDLE:
  2174. cnctdrvDisconnect(hhDriver, hhDriver->uDiscnctFlags);
  2175. break;
  2176. default:
  2177. break;
  2178. }
  2179. default:
  2180. break;
  2181. }
  2182. return;
  2183. }
  2184. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2185. * FUNCTION:
  2186. * Handoff
  2187. *
  2188. * DESCRIPTION:
  2189. * Hands TAPI's com handle to the Wacker's com routines.
  2190. *
  2191. * ARGUMENTS:
  2192. * hhDriver - private driver handle
  2193. *
  2194. * RETURNS:
  2195. * 0=OK
  2196. *
  2197. */
  2198. int Handoff(const HHDRIVER hhDriver)
  2199. {
  2200. LPVARSTRING pVarstr;
  2201. HANDLE hdl;
  2202. DWORD dwSize;
  2203. int i;
  2204. pVarstr = malloc(sizeof(VARSTRING));
  2205. if (pVarstr == 0)
  2206. {
  2207. assert(FALSE);
  2208. return 1;
  2209. }
  2210. memset( pVarstr, 0, sizeof(VARSTRING) );
  2211. pVarstr->dwTotalSize = sizeof(VARSTRING);
  2212. if (lineGetID(hhDriver->hLine, hhDriver->dwLine, hhDriver->hCall,
  2213. LINECALLSELECT_CALL, pVarstr, DEVCLASS) != 0)
  2214. {
  2215. assert(FALSE);
  2216. free(pVarstr);
  2217. pVarstr = NULL;
  2218. return 2;
  2219. }
  2220. if (pVarstr->dwNeededSize > pVarstr->dwTotalSize)
  2221. {
  2222. dwSize = pVarstr->dwNeededSize;
  2223. free(pVarstr);
  2224. pVarstr = NULL;
  2225. pVarstr = malloc(dwSize);
  2226. if (pVarstr == 0)
  2227. {
  2228. assert(FALSE);
  2229. return 3;
  2230. }
  2231. memset( pVarstr, 0, dwSize );
  2232. pVarstr->dwTotalSize = dwSize;
  2233. if (TRAP(lineGetID(hhDriver->hLine, hhDriver->dwLine, hhDriver->hCall,
  2234. LINECALLSELECT_CALL, pVarstr, DEVCLASS)) != 0)
  2235. {
  2236. assert(FALSE);
  2237. free(pVarstr);
  2238. pVarstr = NULL;
  2239. return 4;
  2240. }
  2241. }
  2242. if (pVarstr->dwStringSize == 0)
  2243. {
  2244. assert(FALSE);
  2245. free(pVarstr);
  2246. pVarstr = NULL;
  2247. return 5;
  2248. }
  2249. hdl = *(HANDLE *)((BYTE *)pVarstr + pVarstr->dwStringOffset);
  2250. // Set comm buffers to 32K
  2251. //
  2252. if (SetupComm(hdl, 32768, 32768) == FALSE)
  2253. {
  2254. DWORD dwLastError = GetLastError();
  2255. assert(0);
  2256. }
  2257. if ((i = ComActivatePort(sessQueryComHdl(hhDriver->hSession),
  2258. (DWORD_PTR)hdl)) != COM_OK)
  2259. {
  2260. #if !defined(NDEBUG)
  2261. char ach[256];
  2262. wsprintf(ach, "hdl=%x, i=%d", hdl, i);
  2263. MessageBox(NULL, ach, "debug", MB_OK);
  2264. #endif
  2265. assert(FALSE);
  2266. free(pVarstr);
  2267. pVarstr = NULL;
  2268. return 6;
  2269. }
  2270. if(pVarstr)
  2271. {
  2272. free(pVarstr);
  2273. pVarstr = NULL;
  2274. }
  2275. return 0;
  2276. }
  2277. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2278. * FUNCTION:
  2279. * PostDisconnect
  2280. *
  2281. * DESCRIPTION:
  2282. * Work around to TAPI bug that does not allow us to call lineShutDown()
  2283. * from with the TAPI callback
  2284. *
  2285. * ARGUMENTS:
  2286. * hhDriver - private driver handle
  2287. *
  2288. * RETURNS:
  2289. * void
  2290. *
  2291. */
  2292. void PostDisconnect(const HHDRIVER hhDriver, const unsigned int uFlags)
  2293. {
  2294. PostMessage(sessQueryHwnd(hhDriver->hSession), WM_DISCONNECT,
  2295. uFlags, 0);
  2296. return;
  2297. }
  2298. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2299. * FUNCTION:
  2300. * tapiReinitMessage
  2301. *
  2302. * DESCRIPTION:
  2303. * Displays a messagebox showing TAPI needs to be reinitialized.
  2304. *
  2305. * ARGUMENTS:
  2306. * hhDriver - private driver handle
  2307. *
  2308. * RETURNS:
  2309. * 0=OK, <0=error
  2310. *
  2311. */
  2312. static int tapiReinitMessage(const HHDRIVER hhDriver)
  2313. {
  2314. TCHAR ach[512], achTitle[256];
  2315. if (hhDriver == 0)
  2316. {
  2317. assert(FALSE);
  2318. return -1;
  2319. }
  2320. LoadString(glblQueryDllHinst(), IDS_ER_TAPI_REINIT, ach, sizeof(ach) / sizeof(TCHAR));
  2321. LoadString(glblQueryDllHinst(), IDS_ER_TAPI_REINIT2, achTitle,
  2322. sizeof(achTitle) / sizeof(TCHAR));
  2323. lstrcat(ach, achTitle);
  2324. TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
  2325. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  2326. sessQueryTimeout(hhDriver->hSession));
  2327. return 0;
  2328. }
  2329. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2330. * FUNCTION:
  2331. * tapiReinit
  2332. *
  2333. * DESCRIPTION:
  2334. * Attempts to reinit tapi.
  2335. *
  2336. * ARGUMENTS:
  2337. * hhDriver - private driver handle
  2338. *
  2339. * RETURNS:
  2340. * 0=OK,else error
  2341. *
  2342. */
  2343. static int tapiReinit(const HHDRIVER hhDriver)
  2344. {
  2345. int i;
  2346. LPVARSTRING pvs = 0;
  2347. DWORD dwSize;
  2348. const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
  2349. if (hhDriver == 0)
  2350. {
  2351. assert(FALSE);
  2352. return -1;
  2353. }
  2354. if (hhDriver->hLineApp)
  2355. {
  2356. /* --- Get current config so we can restore it --- */
  2357. if (hhDriver->dwLine != (DWORD)-1)
  2358. {
  2359. if ((pvs = malloc(sizeof(VARSTRING))) == 0)
  2360. {
  2361. assert(FALSE);
  2362. goto SHUTDOWN;
  2363. }
  2364. memset( pvs, 0, sizeof(VARSTRING) );
  2365. pvs->dwTotalSize = sizeof(VARSTRING);
  2366. if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
  2367. {
  2368. assert(FALSE);
  2369. free(pvs);
  2370. pvs = NULL;
  2371. hhDriver->dwLine = (DWORD)-1;
  2372. goto SHUTDOWN;
  2373. }
  2374. if (pvs->dwNeededSize > pvs->dwTotalSize)
  2375. {
  2376. dwSize = pvs->dwNeededSize;
  2377. free(pvs);
  2378. pvs = NULL;
  2379. if ((pvs = malloc(dwSize)) == 0)
  2380. {
  2381. assert(FALSE);
  2382. hhDriver->dwLine = (DWORD)-1;
  2383. goto SHUTDOWN;
  2384. }
  2385. memset( pvs, 0, dwSize );
  2386. pvs->dwTotalSize = dwSize;
  2387. if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
  2388. {
  2389. assert(FALSE);
  2390. free(pvs);
  2391. pvs = NULL;
  2392. hhDriver->dwLine = (DWORD)-1;
  2393. goto SHUTDOWN;
  2394. }
  2395. }
  2396. }
  2397. SHUTDOWN:
  2398. {
  2399. LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
  2400. if (lLineShutdown == LINEERR_NOMEM)
  2401. {
  2402. //
  2403. // We are in a low memory state, so wait for a while,
  2404. // then try to shutdown the line again. REV: 5/1/2002
  2405. //
  2406. Sleep(500);
  2407. lLineShutdown = lineShutdown(hhDriver->hLineApp);
  2408. }
  2409. if (lLineShutdown != 0)
  2410. {
  2411. assert(FALSE);
  2412. return -6;
  2413. }
  2414. }
  2415. hhDriver->hLineApp = 0;
  2416. // Wait for 10 seconds, if nothing happens, return an error
  2417. //
  2418. for (i=0 ;; ++i)
  2419. {
  2420. if (lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
  2421. lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt) != 0)
  2422. {
  2423. if (i > 10)
  2424. {
  2425. assert(0);
  2426. return -7;
  2427. }
  2428. Sleep(1000); // sleep 1 second
  2429. continue;
  2430. }
  2431. break;
  2432. }
  2433. }
  2434. /* --- Ok, we've reintialized, put settings back now --- */
  2435. if (pvs)
  2436. {
  2437. LPVOID pv = (BYTE *)pvs + pvs->dwStringOffset;
  2438. if (lineSetDevConfig(hhDriver->dwLine, pv, pvs->dwStringSize,
  2439. DEVCLASS) != 0)
  2440. {
  2441. assert(FALSE);
  2442. free(pvs);
  2443. pvs = NULL;
  2444. return -8;
  2445. }
  2446. free(pvs);
  2447. pvs = NULL;
  2448. }
  2449. return 0;
  2450. }
  2451. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2452. * FUNCTION:
  2453. * cnctdrvSetDestination
  2454. *
  2455. * DESCRIPTION:
  2456. * Sets the destination (in this case phone number).
  2457. *
  2458. * ARGUMENTS:
  2459. * hhDriver - private driver handle
  2460. * ach - string to set
  2461. * cb - number of chars in ach
  2462. *
  2463. * RETURNS:
  2464. * 0=OK, <0=error
  2465. *
  2466. */
  2467. int WINAPI cnctdrvSetDestination(const HHDRIVER hhDriver, TCHAR * const ach,
  2468. const size_t cb)
  2469. {
  2470. int len;
  2471. if (hhDriver == 0 || ach == 0 || cb == 0)
  2472. {
  2473. assert(FALSE);
  2474. return -1;
  2475. }
  2476. len = (int) min(cb, sizeof(hhDriver->achDest));
  2477. strncpy(hhDriver->achDest, ach, len);
  2478. hhDriver->achDest[len-1];
  2479. return 0;
  2480. }
  2481. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  2482. * FUNCTION:
  2483. * DoNewModemWizard
  2484. *
  2485. * DESCRIPTION:
  2486. * Calls up the new modem wizard
  2487. *
  2488. * ARGUMENTS:
  2489. * hhDriver - private driver handle
  2490. * iTimeout - The timeout length
  2491. *
  2492. * RETURNS:
  2493. * 0=OK,else error
  2494. *
  2495. */
  2496. static int DoNewModemWizard(HWND hWnd, int iTimeout)
  2497. {
  2498. PROCESS_INFORMATION stPI;
  2499. STARTUPINFO stSI;
  2500. TCHAR ach[256];
  2501. int returnVal = 0;
  2502. // Initialize the PROCESS_INFORMATION structure for CreateProcess
  2503. //
  2504. memset( &stPI, 0, sizeof( PROCESS_INFORMATION ) );
  2505. // Initialize the STARTUPINFO structure for CreateProcess
  2506. //
  2507. memset(&stSI, 0, sizeof(stSI));
  2508. stSI.cb = sizeof(stSI);
  2509. stSI.dwFlags = STARTF_USESHOWWINDOW;
  2510. stSI.wShowWindow = SW_SHOW;
  2511. // See if we should run the New modem wizard.
  2512. //
  2513. if(mscAskWizardQuestionAgain())
  2514. {
  2515. LoadString(glblQueryDllHinst(), IDS_ER_CNCT_BADLINE, ach, sizeof(ach) / sizeof(TCHAR));
  2516. if (TimedMessageBox(hWnd, ach, NULL, MB_YESNO | MB_ICONEXCLAMATION, iTimeout) == IDYES)
  2517. {
  2518. TCHAR systemDir[MAX_PATH];
  2519. TCHAR executeString[MAX_PATH * 3];
  2520. TCHAR *pParams = TEXT("\\control.exe\" modem.cpl,,Add");
  2521. UINT numChars = 0;
  2522. TCHAR_Fill(systemDir, TEXT('\0'), MAX_PATH);
  2523. TCHAR_Fill(executeString, TEXT('\0'), MAX_PATH * 3);
  2524. numChars = GetSystemDirectory(systemDir, MAX_PATH);
  2525. if (numChars == 0 || StrCharGetStrLength(systemDir) == 0)
  2526. {
  2527. returnVal = -3;
  2528. }
  2529. else
  2530. {
  2531. if (StrCharGetStrLength(systemDir) + StrCharGetStrLength(pParams) + sizeof(TEXT("\"")) / sizeof(TCHAR) >
  2532. sizeof(executeString) / sizeof(TCHAR))
  2533. {
  2534. returnVal = -2;
  2535. }
  2536. else
  2537. {
  2538. StrCharCopyN(executeString, TEXT("\""), sizeof(executeString) / sizeof(TCHAR));
  2539. StrCharCat(executeString, systemDir);
  2540. StrCharCat(executeString, pParams);
  2541. //
  2542. // Launch the new modem wizard with the command below.
  2543. //
  2544. //if (CreateProcess(0, "rundll sysdm.cpl,InstallDevice_Rundll modem,,",
  2545. // 0, 0, 0, 0, 0, 0, &stSI, &stPI) == FALSE)
  2546. //if (CreateProcess(0, "control.exe modem.cpl,,Add",
  2547. // 0, 0, 0, 0, 0, 0, &stSI, &stPI) == FALSE)
  2548. if (CreateProcess(NULL, executeString,
  2549. NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
  2550. NULL, systemDir, &stSI, &stPI) == FALSE)
  2551. {
  2552. #if defined(_DEBUG)
  2553. {
  2554. char ach[100];
  2555. DWORD dw = GetLastError();
  2556. wsprintf(ach,"CreateProcess (%s, %d) : %x",__FILE__,__LINE__,dw);
  2557. MessageBox(NULL, ach, "Debug", MB_OK);
  2558. }
  2559. #endif
  2560. returnVal = -1;
  2561. }
  2562. else
  2563. {
  2564. mscUpdateRegistryValue();
  2565. //
  2566. // Close the handles.
  2567. //
  2568. CloseHandle(stPI.hProcess);
  2569. CloseHandle(stPI.hThread);
  2570. }
  2571. }
  2572. }
  2573. }
  2574. }
  2575. return returnVal;
  2576. }
  2577. int cncttapiGetLineConfig( const DWORD dwLineId, VOID ** ppvs )
  2578. {
  2579. DWORD dwSize;
  2580. LPVARSTRING pvs = (LPVARSTRING)*ppvs;
  2581. if (pvs != NULL)
  2582. {
  2583. assert(FALSE);
  2584. free(pvs);
  2585. pvs = NULL;
  2586. }
  2587. if ((pvs = malloc(sizeof(VARSTRING))) == 0)
  2588. {
  2589. assert(FALSE);
  2590. return -3;
  2591. }
  2592. memset(pvs, 0, sizeof(VARSTRING));
  2593. pvs->dwTotalSize = sizeof(VARSTRING);
  2594. pvs->dwNeededSize = 0;
  2595. if (lineGetDevConfig(dwLineId, pvs, DEVCLASS) != 0)
  2596. {
  2597. assert(FALSE);
  2598. free(pvs);
  2599. pvs = NULL;
  2600. return -4;
  2601. }
  2602. if (pvs->dwNeededSize > pvs->dwTotalSize)
  2603. {
  2604. dwSize = pvs->dwNeededSize;
  2605. free(pvs);
  2606. pvs = NULL;
  2607. if ((pvs = malloc(dwSize)) == 0)
  2608. {
  2609. assert(FALSE);
  2610. return -5;
  2611. }
  2612. memset(pvs, 0, dwSize);
  2613. pvs->dwTotalSize = dwSize;
  2614. if (lineGetDevConfig(dwLineId, pvs, DEVCLASS) != 0)
  2615. {
  2616. assert(FALSE);
  2617. free(pvs);
  2618. pvs = NULL;
  2619. return -6;
  2620. }
  2621. }
  2622. *ppvs = (VOID *)pvs;
  2623. return 0;
  2624. }
  2625. int cncttapiSetLineConfig(const DWORD dwLineId, const HCOM hCom)
  2626. {
  2627. int retValue = 0;
  2628. LPVARSTRING pvs = NULL;
  2629. PUMDEVCFG pDevCfg = NULL;
  2630. int iBaudRate;
  2631. int iDataBits;
  2632. int iParity;
  2633. int iStopBits;
  2634. LONG lLineReturn;
  2635. retValue = cncttapiGetLineConfig( dwLineId, (VOID **) &pvs);
  2636. if (retValue != 0)
  2637. {
  2638. retValue = retValue;
  2639. }
  2640. if (retValue == 0 && pvs == NULL)
  2641. {
  2642. retValue = -7;
  2643. }
  2644. // The structure of the DevConfig block is as follows
  2645. //
  2646. // VARSTRING
  2647. // UMDEVCFGHDR
  2648. // COMMCONFIG
  2649. // MODEMSETTINGS
  2650. //
  2651. // The UMDEVCFG structure used below is defined in the
  2652. // UNIMODEM.H provided in the platform SDK (in the nih
  2653. // directory for HTPE). REV: 12/01/2000
  2654. //
  2655. if (retValue == 0)
  2656. {
  2657. pDevCfg = (UMDEVCFG *)((BYTE *)pvs + pvs->dwStringOffset);
  2658. if (pDevCfg == NULL)
  2659. {
  2660. retValue = -8;
  2661. }
  2662. }
  2663. if (retValue == 0 && (hCom == NULL || ComValidHandle(hCom) == FALSE))
  2664. {
  2665. retValue = -9;
  2666. }
  2667. //
  2668. // commconfig struct has a DCB structure we dereference for the
  2669. // com settings.
  2670. //
  2671. //
  2672. // The baud rate should be stored with the COM settings for
  2673. // TAPI devices, but we may want to use the current TAPI device
  2674. // baud rate instead. We should find a better solution for this.
  2675. // TODO:REV 05/01/2001
  2676. //
  2677. if (retValue == 0 && ComGetBaud(hCom, &iBaudRate) != COM_OK)
  2678. {
  2679. #if defined(TODO)
  2680. retValue = -10;
  2681. #endif // TODO
  2682. }
  2683. else if (retValue == 0)
  2684. {
  2685. ComSetBaud(hCom, pDevCfg->commconfig.dcb.BaudRate);
  2686. }
  2687. if (retValue == 0 && ComGetDataBits(hCom, &iDataBits) != COM_OK)
  2688. {
  2689. retValue = -11;
  2690. }
  2691. if (retValue == 0 && ComGetParity(hCom, &iParity) != COM_OK)
  2692. {
  2693. retValue = -12;
  2694. }
  2695. if (retValue == 0 && ComGetStopBits(hCom, &iStopBits) != COM_OK)
  2696. {
  2697. retValue = -13;
  2698. }
  2699. if (retValue != 0)
  2700. {
  2701. free(pvs);
  2702. pvs = NULL;
  2703. return retValue;
  2704. }
  2705. #if defined(TODO)
  2706. pDevCfg->commconfig.dcb.BaudRate = iBaudRate;
  2707. #endif // TODO
  2708. pDevCfg->commconfig.dcb.ByteSize = (BYTE)iDataBits;
  2709. pDevCfg->commconfig.dcb.Parity = (BYTE)iParity;
  2710. pDevCfg->commconfig.dcb.StopBits = (BYTE)iStopBits;
  2711. if (iDataBits != 8 && iParity != NOPARITY && iStopBits != ONESTOPBIT)
  2712. {
  2713. ComSetAutoDetect(hCom, FALSE);
  2714. }
  2715. //
  2716. // Actually set the TAPI device's COM settings.
  2717. //
  2718. lLineReturn = lineSetDevConfig(dwLineId, pDevCfg, pvs->dwStringSize, DEVCLASS);
  2719. free(pvs);
  2720. pvs = NULL;
  2721. if (lLineReturn < 0)
  2722. {
  2723. assert(FALSE);
  2724. return lLineReturn;
  2725. }
  2726. retValue = cncttapiGetLineConfig( dwLineId, (VOID **) &pvs);
  2727. if (retValue != 0)
  2728. {
  2729. retValue = retValue - 100;
  2730. }
  2731. //
  2732. // Make sure the port settings get updated.
  2733. //
  2734. retValue = ComConfigurePort(hCom);
  2735. //
  2736. // Make sure the status bar contains the correct settings.
  2737. //
  2738. PostMessage(sessQueryHwndStatusbar(hCom->hSession),
  2739. SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
  2740. if (pvs == NULL)
  2741. {
  2742. return -14;
  2743. }
  2744. // The structure of the DevConfig block is as follows
  2745. //
  2746. // VARSTRING
  2747. // UMDEVCFGHDR
  2748. // COMMCONFIG
  2749. // MODEMSETTINGS
  2750. //
  2751. // The UMDEVCFG structure used below is defined in the
  2752. // UNIMODEM.H provided in the platform SDK (in the nih
  2753. // directory for HTPE). REV: 12/01/2000
  2754. //
  2755. if (retValue == 0)
  2756. {
  2757. pDevCfg = (UMDEVCFG *)((BYTE *)pvs + pvs->dwStringOffset);
  2758. if (pDevCfg == NULL)
  2759. {
  2760. retValue = -15;
  2761. }
  2762. }
  2763. if (retValue == 0 && (
  2764. #if defined(TODO)
  2765. pDevCfg->commconfig.dcb.BaudRate != iBaudRate ||
  2766. #endif // TODO
  2767. pDevCfg->commconfig.dcb.ByteSize != iDataBits ||
  2768. pDevCfg->commconfig.dcb.Parity != iParity ||
  2769. pDevCfg->commconfig.dcb.StopBits != iStopBits))
  2770. {
  2771. //
  2772. // If this is NT and we are currently connected with
  2773. // a modem, we must disconnect and attempt to redial
  2774. // so that the COM settings are set properly for the
  2775. // modem since this can not be done once a connection
  2776. // has been made. REV: 06/05/2001
  2777. //
  2778. if (IsNT())
  2779. {
  2780. HCNCT hCnct = sessQueryCnctHdl(hCom->hSession);
  2781. if (hCnct)
  2782. {
  2783. int iStatus = cnctQueryStatus(hCnct);
  2784. if (iStatus != CNCT_STATUS_FALSE &&
  2785. iStatus != CNCT_BAD_HANDLE &&
  2786. cnctIsModemConnection(hCnct) == 1)
  2787. {
  2788. int nDisconnect = IDYES;
  2789. //
  2790. // Don't prompt if this is NT_EDITION, just do the
  2791. // disconnection quietly and attempt to reconnect.
  2792. //
  2793. #if !defined(NT_EDITION)
  2794. TCHAR ach[256];
  2795. TCHAR_Fill(ach, TEXT('\0'), sizeof(ach) / sizeof(TCHAR));
  2796. //
  2797. // Prompt to disconnect current connection due to TAPI
  2798. // device needing to be reset. REV: 05/31/2001
  2799. //
  2800. LoadString(glblQueryDllHinst(), IDS_ER_TAPI_NEEDS_RESET, ach, sizeof(ach) / sizeof(TCHAR));
  2801. nDisconnect =
  2802. TimedMessageBox(sessQueryHwnd(hCom->hSession), ach, NULL,
  2803. MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL,
  2804. sessQueryTimeout(hCom->hSession));
  2805. #endif //NT_EDITION
  2806. if (nDisconnect == IDYES || nDisconnect == -1)
  2807. {
  2808. retValue = -16;
  2809. }
  2810. }
  2811. } // hCnct
  2812. } // IsNT()
  2813. }
  2814. free(pvs);
  2815. pvs = NULL;
  2816. return retValue;
  2817. }