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.

3614 lines
93 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: DataPort.cpp
  6. * Content: Serial communications port management class
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 01/20/98 jtk Created
  13. * 09/14/99 jtk Derived from ComPort.cpp
  14. ***************************************************************************/
  15. #include "dnmdmi.h"
  16. //**********************************************************************
  17. // Constant definitions
  18. //**********************************************************************
  19. //
  20. // number of BITS in a serial BYTE
  21. //
  22. #define BITS_PER_BYTE 8
  23. //
  24. // maximum size of baud rate string
  25. //
  26. #define MAX_BAUD_STRING_SIZE 7
  27. //
  28. // default size of buffers when parsing
  29. //
  30. #define DEFAULT_COMPONENT_BUFFER_SIZE 1000
  31. //
  32. // device ID assigned to 'all adapters'
  33. //
  34. #define ALL_ADAPTERS_DEVICE_ID 0
  35. //
  36. // NULL token
  37. //
  38. #define NULL_TOKEN '\0'
  39. //
  40. // modem state flags
  41. //
  42. #define STATE_FLAG_CONNECTED 0x00000001
  43. #define STATE_FLAG_OUTGOING_CALL_DIALING 0x00000002
  44. #define STATE_FLAG_OUTGOING_CALL_PROCEEDING 0x00000004
  45. #define STATE_FLAG_INCOMING_CALL_NOTIFICATION 0x00000008
  46. #define STATE_FLAG_INCOMING_CALL_OFFERED 0x00000010
  47. #define STATE_FLAG_INCOMING_CALL_ACCEPTED 0x00000020
  48. //
  49. // default size of buffers when parsing
  50. //
  51. #define DEFAULT_COMPONENT_BUFFER_SIZE 1000
  52. //
  53. // number of milliseconds in one day
  54. //
  55. #define ONE_DAY 86400000
  56. //
  57. // number of BITS in a serial BYTE
  58. //
  59. #define BITS_PER_BYTE 8
  60. //**********************************************************************
  61. // Macro definitions
  62. //**********************************************************************
  63. //**********************************************************************
  64. // Structure definitions
  65. //**********************************************************************
  66. //**********************************************************************
  67. // Variable definitions
  68. //**********************************************************************
  69. //**********************************************************************
  70. // Function prototypes
  71. //**********************************************************************
  72. //**********************************************************************
  73. // Function definitions
  74. //**********************************************************************
  75. //**********************************************************************
  76. // ------------------------------
  77. // CDataPort::ReturnSelfToPool - return this item to the pool
  78. //
  79. // Entry: Nothing
  80. //
  81. // Exit: Error code
  82. // ------------------------------
  83. #undef DPF_MODNAME
  84. #define DPF_MODNAME "CDataPort::ReturnSelfToPool"
  85. void CDataPort::ReturnSelfToPool( void )
  86. {
  87. if (m_fModem)
  88. {
  89. g_ModemPortPool.Release( this );
  90. }
  91. else
  92. {
  93. g_ComPortPool.Release( this );
  94. }
  95. }
  96. //**********************************************************************
  97. //**********************************************************************
  98. // ------------------------------
  99. // CDataPort::EndpointAddRef - increment endpoint reference count
  100. //
  101. // Entry: Nothing
  102. //
  103. // Exit: Nothing
  104. // ------------------------------
  105. #undef DPF_MODNAME
  106. #define DPF_MODNAME "CDataPort::EndpointAddRef"
  107. void CDataPort::EndpointAddRef( void )
  108. {
  109. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  110. Lock();
  111. DNASSERT( m_EndpointRefCount != -1 );
  112. m_EndpointRefCount++;
  113. AddRef();
  114. Unlock();
  115. }
  116. //**********************************************************************
  117. //**********************************************************************
  118. // ------------------------------
  119. // CDataPort::EndpointDecRef - decrement endpoint reference count
  120. //
  121. // Entry: Nothing
  122. //
  123. // Exit: Endpoint reference count
  124. // ------------------------------
  125. #undef DPF_MODNAME
  126. #define DPF_MODNAME "CDataPort::EndpointDecRef"
  127. DWORD CDataPort::EndpointDecRef( void )
  128. {
  129. DWORD dwReturn;
  130. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  131. DNASSERT( m_EndpointRefCount != 0 );
  132. DNASSERT( ( GetState() == DATA_PORT_STATE_RECEIVING ) ||
  133. ( GetState() == DATA_PORT_STATE_INITIALIZED ) );
  134. Lock();
  135. DNASSERT( m_EndpointRefCount != 0 );
  136. m_EndpointRefCount--;
  137. dwReturn = m_EndpointRefCount;
  138. if ( m_EndpointRefCount == 0 )
  139. {
  140. SetState( DATA_PORT_STATE_UNBOUND );
  141. UnbindFromNetwork();
  142. }
  143. Unlock();
  144. DecRef();
  145. return dwReturn;
  146. }
  147. //**********************************************************************
  148. //**********************************************************************
  149. // ------------------------------
  150. // CDataPort::SetPortCommunicationParameters - set generate communication parameters
  151. //
  152. // Entry: Nothing
  153. //
  154. // Exit: Error code
  155. // ------------------------------
  156. #undef DPF_MODNAME
  157. #define DPF_MODNAME "CDataPort::SetPortCommunicationParameters"
  158. HRESULT CDataPort::SetPortCommunicationParameters( void )
  159. {
  160. HRESULT hr;
  161. COMMTIMEOUTS CommTimeouts;
  162. //
  163. // set timeout values for serial port
  164. //
  165. hr = DPN_OK;
  166. memset( &CommTimeouts, 0x00, sizeof( CommTimeouts ) );
  167. CommTimeouts.ReadIntervalTimeout = ONE_DAY; // read timeout interval (none)
  168. CommTimeouts.ReadTotalTimeoutMultiplier = ONE_DAY; // return immediately
  169. CommTimeouts.ReadTotalTimeoutConstant = 0; // return immediately
  170. CommTimeouts.WriteTotalTimeoutMultiplier = 0; // no multiplier
  171. CommTimeouts.WriteTotalTimeoutConstant = WRITE_TIMEOUT_MS; // write timeout interval
  172. if ( SetCommTimeouts( HANDLE_FROM_DNHANDLE(m_hFile), &CommTimeouts ) == FALSE )
  173. {
  174. DWORD dwError;
  175. hr = DPNERR_GENERIC;
  176. dwError = GetLastError();
  177. // report error (there's no cleanup)
  178. DPFX(DPFPREP, 0, "Unable to set comm timeouts!" );
  179. DisplayErrorCode( 0, dwError );
  180. goto Failure;
  181. }
  182. //
  183. // clear any outstanding communication data
  184. //
  185. if ( PurgeComm( HANDLE_FROM_DNHANDLE(m_hFile), ( PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ) == FALSE )
  186. {
  187. DWORD dwError;
  188. dwError = GetLastError();
  189. DPFX(DPFPREP, 0, "Problem with PurgeComm() when opening com port!" );
  190. DisplayErrorCode( 0, dwError );
  191. }
  192. //
  193. // set communication mask to listen for character receive
  194. //
  195. if ( SetCommMask( HANDLE_FROM_DNHANDLE(m_hFile), EV_RXCHAR ) == FALSE )
  196. {
  197. DWORD dwError;
  198. hr = DPNERR_GENERIC;
  199. dwError = GetLastError();
  200. DPFX(DPFPREP, 0, "Error setting communication mask!" );
  201. DisplayErrorCode( 0, dwError );
  202. goto Failure;
  203. }
  204. Exit:
  205. return hr;
  206. Failure:
  207. goto Exit;
  208. }
  209. //**********************************************************************
  210. //**********************************************************************
  211. // ------------------------------
  212. // CDataPort::StartReceiving - start receiving
  213. //
  214. // Entry: Nothing
  215. //
  216. // Exit: Error code
  217. // ------------------------------
  218. #undef DPF_MODNAME
  219. #define DPF_MODNAME "CDataPort::StartReceiving"
  220. HRESULT CDataPort::StartReceiving( void )
  221. {
  222. HRESULT hr;
  223. DPFX(DPFPREP, 7, "(0x%p) Enter", this);
  224. //
  225. // initialize
  226. //
  227. hr = DPN_OK;
  228. Lock();
  229. switch ( GetState() )
  230. {
  231. //
  232. // port is initialized, but not receiving yet, start receiving
  233. //
  234. case DATA_PORT_STATE_INITIALIZED:
  235. {
  236. hr = Receive();
  237. if ( ( hr == DPNERR_PENDING ) ||
  238. ( hr == DPN_OK ) )
  239. {
  240. SetState( DATA_PORT_STATE_RECEIVING );
  241. //
  242. // the receive was successful, return success for this function
  243. //
  244. hr = DPN_OK;
  245. }
  246. else
  247. {
  248. DPFX(DPFPREP, 0, "Failed initial read!" );
  249. DisplayDNError( 0, hr );
  250. goto Failure;
  251. }
  252. break;
  253. }
  254. //
  255. // data port is already receiving, nothing to do
  256. //
  257. case DATA_PORT_STATE_RECEIVING:
  258. {
  259. break;
  260. }
  261. //
  262. // data port is closing, we shouldn't be here!
  263. //
  264. case DATA_PORT_STATE_UNBOUND:
  265. {
  266. DNASSERT( FALSE );
  267. break;
  268. }
  269. //
  270. // bad state
  271. //
  272. case DATA_PORT_STATE_UNKNOWN:
  273. default:
  274. {
  275. DNASSERT( FALSE );
  276. break;
  277. }
  278. }
  279. Unlock();
  280. Exit:
  281. DPFX(DPFPREP, 7, "(0x%p) Return: [0x%lx]", this, hr);
  282. return hr;
  283. Failure:
  284. goto Exit;
  285. }
  286. //**********************************************************************
  287. //**********************************************************************
  288. // ------------------------------
  289. // CDataPort::Receive - read from file
  290. //
  291. // Entry: Nothing
  292. //
  293. // Exit: Error code
  294. // ------------------------------
  295. #undef DPF_MODNAME
  296. #define DPF_MODNAME "CDataPort::Receive"
  297. HRESULT CDataPort::Receive( void )
  298. {
  299. HRESULT hr;
  300. BOOL fReadReturn;
  301. //
  302. // initialize
  303. //
  304. hr = DPN_OK;
  305. AddRef();
  306. Reread:
  307. //
  308. // if there is no pending read, get one from the pool
  309. //
  310. if ( m_pActiveRead == NULL )
  311. {
  312. m_pActiveRead = m_pSPData->GetThreadPool()->CreateReadIOData();
  313. if ( m_pActiveRead == NULL )
  314. {
  315. hr = DPNERR_OUTOFMEMORY;
  316. DPFX(DPFPREP, 0, "Failed to get buffer for read!" );
  317. goto Failure;
  318. }
  319. m_pActiveRead->SetDataPort( this );
  320. }
  321. //
  322. // check the state of the read and perform the appropriate action
  323. //
  324. DNASSERT( m_pActiveRead != NULL );
  325. switch ( m_pActiveRead->m_ReadState )
  326. {
  327. //
  328. // Initialize read state. This involves setting up to read a header
  329. // and then reentering the loop.
  330. //
  331. case READ_STATE_UNKNOWN:
  332. {
  333. m_pActiveRead->SetReadState( READ_STATE_READ_HEADER );
  334. m_pActiveRead->m_dwBytesToRead = sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader );
  335. m_pActiveRead->m_dwReadOffset = 0;
  336. goto Reread;
  337. break;
  338. }
  339. //
  340. // issue a read for a header or user data
  341. //
  342. case READ_STATE_READ_HEADER:
  343. case READ_STATE_READ_DATA:
  344. {
  345. //
  346. // don't change m_dwReadOffset because it might have been set
  347. // elsewhere to recover a partially received message
  348. //
  349. // DNASSERT( m_pActiveReceiveBuffer != NULL );
  350. // m_dwBytesReceived = 0;
  351. // m_pActiveRead->m_dwBytesReceived = 0;
  352. break;
  353. }
  354. //
  355. // unknown state
  356. //
  357. default:
  358. {
  359. DNASSERT( FALSE );
  360. break;
  361. }
  362. }
  363. //
  364. // lock the active read list for Win9x only to prevent reads from completing
  365. // early
  366. //
  367. #ifdef WIN95
  368. m_pSPData->GetThreadPool()->LockReadData();
  369. DNASSERT( m_pActiveRead->Win9xOperationPending() == FALSE );
  370. m_pActiveRead->SetWin9xOperationPending( TRUE );
  371. #endif // WIN95
  372. DNASSERT( m_pActiveRead->jkm_dwOverlappedBytesReceived == 0 );
  373. DPFX(DPFPREP, 8, "Submitting read 0x%p (socketport 0x%p, file 0x%p).",
  374. m_pActiveRead, this, m_hFile);
  375. //
  376. // perform read
  377. //
  378. fReadReturn = ReadFile( HANDLE_FROM_DNHANDLE(m_hFile), // file handle
  379. &m_pActiveRead->m_ReceiveBuffer.ReceivedData[ m_pActiveRead->m_dwReadOffset ], // pointer to destination
  380. m_pActiveRead->m_dwBytesToRead, // number of bytes to read
  381. &m_pActiveRead->jkm_dwImmediateBytesReceived, // pointer to number of bytes received
  382. m_pActiveRead->Overlap() // pointer to overlap structure
  383. );
  384. if ( fReadReturn == FALSE )
  385. {
  386. DWORD dwError;
  387. dwError = GetLastError();
  388. switch ( dwError )
  389. {
  390. //
  391. // I/O is pending, wait for completion notification
  392. //
  393. case ERROR_IO_PENDING:
  394. {
  395. hr = DPNERR_PENDING;
  396. break;
  397. }
  398. //
  399. // comport was closed, nothing else to do
  400. //
  401. case ERROR_INVALID_HANDLE:
  402. {
  403. hr = DPNERR_NOCONNECTION;
  404. DPFX(DPFPREP, 3, "File closed.");
  405. goto Failure;
  406. break;
  407. }
  408. //
  409. // other
  410. //
  411. default:
  412. {
  413. hr = DPNERR_GENERIC;
  414. DPFX(DPFPREP, 0, "Unknown error from ReadFile (%u)!", dwError);
  415. DisplayErrorCode( 0, dwError );
  416. DNASSERT( FALSE );
  417. goto Failure;
  418. break;
  419. }
  420. }
  421. }
  422. else
  423. {
  424. //
  425. // read succeeded immediately, we'll handle it on the async notification
  426. //
  427. DPFX(DPFPREP, 7, "Read 0x%p completed immediately (%u bytes).",
  428. m_pActiveRead, m_pActiveRead->jkm_dwImmediateBytesReceived);
  429. DNASSERT( hr == DPN_OK );
  430. }
  431. Exit:
  432. #ifdef WIN95
  433. m_pSPData->GetThreadPool()->UnlockReadData();
  434. #endif // WIN95
  435. return hr;
  436. Failure:
  437. if ( m_pActiveRead != NULL )
  438. {
  439. #ifdef WIN95
  440. m_pActiveRead->SetWin9xOperationPending( FALSE );
  441. #endif // WIN95
  442. m_pActiveRead->DecRef();
  443. m_pActiveRead = NULL;
  444. }
  445. DecRef();
  446. goto Exit;
  447. }
  448. //**********************************************************************
  449. //**********************************************************************
  450. // ------------------------------
  451. // CDataPort::SendData - send data
  452. //
  453. // Entry: Pointer to write buffer
  454. //
  455. // Exit: Nothing
  456. // ------------------------------
  457. #undef DPF_MODNAME
  458. #define DPF_MODNAME "CDataPort::SendData"
  459. void CDataPort::SendData( CModemWriteIOData *const pWriteIOData )
  460. {
  461. // CModemWriteIOData *pActiveSend;
  462. UINT_PTR uIndex;
  463. DWORD dwByteCount;
  464. BOOL fWriteFileReturn;
  465. DNASSERT( m_EndpointRefCount != 0 );
  466. DNASSERT( pWriteIOData->m_DataBuffer.MessageHeader.SerialSignature == SERIAL_HEADER_START );
  467. DNASSERT( ( pWriteIOData->m_DataBuffer.MessageHeader.MessageTypeToken == SERIAL_DATA_USER_DATA ) ||
  468. ( ( pWriteIOData->m_DataBuffer.MessageHeader.MessageTypeToken & ~( ENUM_RTT_MASK ) ) == SERIAL_DATA_ENUM_QUERY ) ||
  469. ( ( pWriteIOData->m_DataBuffer.MessageHeader.MessageTypeToken & ~( ENUM_RTT_MASK ) )== SERIAL_DATA_ENUM_RESPONSE ) );
  470. //
  471. // check for command cancellation
  472. //
  473. if ( pWriteIOData->m_pCommand != NULL )
  474. {
  475. pWriteIOData->m_pCommand->Lock();
  476. switch ( pWriteIOData->m_pCommand->GetState() )
  477. {
  478. //
  479. // command pending, mark as uninterruptable and exit
  480. //
  481. case COMMAND_STATE_PENDING:
  482. {
  483. pWriteIOData->m_pCommand->SetState( COMMAND_STATE_INPROGRESS_CANNOT_CANCEL );
  484. pWriteIOData->m_pCommand->Unlock();
  485. break;
  486. }
  487. //
  488. // command is being cancelled, indicate command failure
  489. //
  490. case COMMAND_STATE_CANCELLING:
  491. {
  492. DNASSERT( FALSE );
  493. break;
  494. }
  495. //
  496. // other
  497. //
  498. default:
  499. {
  500. DNASSERT( FALSE );
  501. break;
  502. }
  503. }
  504. }
  505. //
  506. // flatten the buffer so it will send faster (no thread transitions from
  507. // send complete to sending the next chunk).
  508. //
  509. dwByteCount = sizeof( pWriteIOData->m_DataBuffer.MessageHeader );
  510. for ( uIndex = 0; uIndex < pWriteIOData->m_uBufferCount; uIndex++ )
  511. {
  512. memcpy( &pWriteIOData->m_DataBuffer.Data[ dwByteCount ],
  513. pWriteIOData->m_pBuffers[ uIndex ].pBufferData,
  514. pWriteIOData->m_pBuffers[ uIndex ].dwBufferSize );
  515. dwByteCount += pWriteIOData->m_pBuffers[ uIndex ].dwBufferSize;
  516. }
  517. DNASSERT( dwByteCount <= MAX_MESSAGE_SIZE );
  518. DNASSERT( dwByteCount < 65536 );
  519. DBG_CASSERT( sizeof( pWriteIOData->m_DataBuffer.MessageHeader.wMessageSize ) == sizeof( WORD ) );
  520. pWriteIOData->m_DataBuffer.MessageHeader.wMessageSize = static_cast<WORD>( dwByteCount - sizeof( pWriteIOData->m_DataBuffer.MessageHeader ) );
  521. DBG_CASSERT( sizeof( pWriteIOData->m_DataBuffer.MessageHeader.wMessageCRC ) == sizeof( WORD ) );
  522. pWriteIOData->m_DataBuffer.MessageHeader.wMessageCRC = static_cast<WORD>( GenerateCRC( &pWriteIOData->m_DataBuffer.Data[ sizeof( pWriteIOData->m_DataBuffer.MessageHeader ) ], pWriteIOData->m_DataBuffer.MessageHeader.wMessageSize ) );
  523. DBG_CASSERT( sizeof( pWriteIOData->m_DataBuffer.MessageHeader.wHeaderCRC ) == sizeof( WORD ) );
  524. DBG_CASSERT( sizeof( &pWriteIOData->m_DataBuffer.MessageHeader ) == sizeof( BYTE* ) );
  525. pWriteIOData->m_DataBuffer.MessageHeader.wHeaderCRC = static_cast<WORD>( GenerateCRC( reinterpret_cast<BYTE*>( &pWriteIOData->m_DataBuffer.MessageHeader ),
  526. ( sizeof( pWriteIOData->m_DataBuffer.MessageHeader) - sizeof( pWriteIOData->m_DataBuffer.MessageHeader.wHeaderCRC ) ) ) );
  527. DPFX(DPFPREP, 7, "(0x%p) Writing %u bytes (WriteData 0x%p, command = 0x%p, buffer = 0x%p).",
  528. this, dwByteCount, pWriteIOData, pWriteIOData->m_pCommand, &(pWriteIOData->m_DataBuffer) );
  529. AddRef();
  530. #ifdef WIN95
  531. m_pSPData->GetThreadPool()->LockWriteData();
  532. DNASSERT( pWriteIOData->Win9xOperationPending() == FALSE );
  533. pWriteIOData->SetWin9xOperationPending( TRUE );
  534. #endif // WIN95
  535. DNASSERT( pWriteIOData->jkm_dwOverlappedBytesSent == 0 );
  536. pWriteIOData->SetDataPort( this );
  537. fWriteFileReturn = WriteFile( HANDLE_FROM_DNHANDLE(m_hFile), // file handle
  538. &pWriteIOData->m_DataBuffer, // buffer to send
  539. dwByteCount, // bytes to send
  540. &pWriteIOData->jkm_dwImmediateBytesSent, // pointer to bytes written
  541. pWriteIOData->Overlap() ); // pointer to overlapped structure
  542. if ( fWriteFileReturn == FALSE )
  543. {
  544. DWORD dwError;
  545. //
  546. // send didn't complete immediately, find out why
  547. //
  548. dwError = GetLastError();
  549. switch ( dwError )
  550. {
  551. //
  552. // Write is queued, no problem. Wait for asynchronous notification.
  553. //
  554. case ERROR_IO_PENDING:
  555. {
  556. break;
  557. }
  558. //
  559. // Other problem, stop if not 'known' to see if there's a better
  560. // error return.
  561. //
  562. default:
  563. {
  564. DPFX(DPFPREP, 0, "Problem with WriteFile!" );
  565. DisplayErrorCode( 0, dwError );
  566. pWriteIOData->jkm_hSendResult = DPNERR_NOCONNECTION;
  567. switch ( dwError )
  568. {
  569. case ERROR_INVALID_HANDLE:
  570. {
  571. break;
  572. }
  573. default:
  574. {
  575. DNASSERT( FALSE );
  576. break;
  577. }
  578. }
  579. //
  580. // fail the write
  581. //
  582. pWriteIOData->DataPort()->SendComplete( pWriteIOData, pWriteIOData->jkm_hSendResult );
  583. break;
  584. }
  585. }
  586. }
  587. else
  588. {
  589. //
  590. // Send completed immediately. Wait for the asynchronous notification.
  591. //
  592. }
  593. //Exit:
  594. #ifdef WIN95
  595. m_pSPData->GetThreadPool()->UnlockWriteData();
  596. #endif // WIN95
  597. // SendData( NULL );
  598. return;
  599. }
  600. //**********************************************************************
  601. //**********************************************************************
  602. // ------------------------------
  603. // CDataPort::SendComplete - send has completed
  604. //
  605. // Entry: Pointer to write data
  606. // Send result
  607. //
  608. // Exit: Nothing
  609. // ------------------------------
  610. #undef DPF_MODNAME
  611. #define DPF_MODNAME "CDataPort::SendComplete"
  612. void CDataPort::SendComplete( CModemWriteIOData *const pWriteIOData, const HRESULT hSendResult )
  613. {
  614. HRESULT hr;
  615. DNASSERT( pWriteIOData != NULL );
  616. #ifdef WIN95
  617. DNASSERT( pWriteIOData->Win9xOperationPending() == FALSE );
  618. #endif // WIN95
  619. switch ( pWriteIOData->m_SendCompleteAction )
  620. {
  621. case SEND_COMPLETE_ACTION_COMPLETE_COMMAND:
  622. {
  623. DPFX(DPFPREP, 8, "Data port 0x%p completing send command 0x%p, hr = 0x%lx, context = 0x%p to interface 0x%p.",
  624. this, pWriteIOData->m_pCommand, hSendResult,
  625. pWriteIOData->m_pCommand->GetUserContext(),
  626. m_pSPData->DP8SPCallbackInterface());
  627. hr = IDP8SPCallback_CommandComplete( m_pSPData->DP8SPCallbackInterface(), // pointer to callback interface
  628. pWriteIOData->m_pCommand, // command handle
  629. hSendResult, // error code
  630. pWriteIOData->m_pCommand->GetUserContext() // user context
  631. );
  632. DPFX(DPFPREP, 8, "Data port 0x%p returning from command complete [0x%lx].", this, hr);
  633. break;
  634. }
  635. case SEND_COMPLETE_ACTION_NONE:
  636. {
  637. if (pWriteIOData->m_pCommand != NULL)
  638. {
  639. DPFX(DPFPREP, 8, "Data port 0x%p not completing send command 0x%p, hr = 0x%lx, context = 0x%p.",
  640. this, pWriteIOData->m_pCommand, hSendResult, pWriteIOData->m_pCommand->GetUserContext() );
  641. }
  642. else
  643. {
  644. DPFX(DPFPREP, 8, "Data port 0x%p not completing NULL send command, hr = 0x%lx",
  645. this, hSendResult );
  646. }
  647. break;
  648. }
  649. default:
  650. {
  651. DNASSERT( FALSE );
  652. break;
  653. }
  654. }
  655. m_pSPData->GetThreadPool()->ReturnWriteIOData( pWriteIOData );
  656. DecRef();
  657. }
  658. //**********************************************************************
  659. //**********************************************************************
  660. // ------------------------------
  661. // CDataPort::ProcessReceivedData - process received data
  662. //
  663. // Entry: Count of bytes received
  664. // Error code
  665. //
  666. // Exit: Nothing
  667. // ------------------------------
  668. #undef DPF_MODNAME
  669. #define DPF_MODNAME "CDataPort::ProcessReceivedData"
  670. void CDataPort::ProcessReceivedData( const DWORD dwBytesReceived, const DWORD dwError )
  671. {
  672. DNASSERT( m_pActiveRead != NULL );
  673. DNASSERT( dwBytesReceived <= m_pActiveRead->m_dwBytesToRead );
  674. //
  675. // If this data port is not actively receiving, returnt the active read to
  676. // the pool. This happens on shutdown and when the modem disconnects.
  677. //
  678. if ( GetState() != DATA_PORT_STATE_RECEIVING )
  679. {
  680. DPFX(DPFPREP, 7, "Data port 0x%p not receiving, ignoring %u bytes received and err %u.",
  681. this, dwBytesReceived, dwError );
  682. if ( m_pActiveRead != NULL )
  683. {
  684. #ifdef WIN95
  685. m_pActiveRead->SetWin9xOperationPending( FALSE );
  686. #endif // WIN95
  687. m_pActiveRead->DecRef();
  688. m_pActiveRead = NULL;
  689. }
  690. goto Exit;
  691. }
  692. switch ( dwError )
  693. {
  694. //
  695. // ERROR_OPERATION_ABORTED = something stopped operation, stop and look.
  696. //
  697. case ERROR_OPERATION_ABORTED:
  698. {
  699. DPFX(DPFPREP, 8, "Operation aborted, data port 0x%p, bytes received = %u.",
  700. this, dwBytesReceived );
  701. break;
  702. }
  703. //
  704. // ERROR_SUCCESS = data was received (may be 0 bytes from a timeout)
  705. //
  706. case ERROR_SUCCESS:
  707. {
  708. break;
  709. }
  710. //
  711. // other
  712. //
  713. default:
  714. {
  715. DNASSERT( FALSE );
  716. DPFX(DPFPREP, 0, "Failed read!" );
  717. DisplayErrorCode( 0, dwError );
  718. break;
  719. }
  720. }
  721. m_pActiveRead->m_dwBytesToRead -= dwBytesReceived;
  722. if ( m_pActiveRead->m_dwBytesToRead != 0 )
  723. {
  724. DPFX(DPFPREP, 7, "Data port 0x%p got %u bytes but there are %u bytes remaining to be read.",
  725. this, dwBytesReceived, m_pActiveRead->m_dwBytesToRead );
  726. #ifdef WIN95
  727. m_pSPData->GetThreadPool()->ReinsertInReadList( m_pActiveRead );
  728. #endif // WIN95
  729. Receive();
  730. }
  731. else
  732. {
  733. //
  734. // all data has been read, attempt to process it
  735. //
  736. switch ( m_pActiveRead->m_ReadState )
  737. {
  738. //
  739. // Header. Check header integrity before proceeding. If the header
  740. // is bad, attempt to find another header signature and reread.
  741. //
  742. case READ_STATE_READ_HEADER:
  743. {
  744. WORD wCRC;
  745. DWORD dwCRCSize;
  746. DPFX(DPFPREP, 9, "Reading header.");
  747. DBG_CASSERT( OFFSETOF( MESSAGE_HEADER, SerialSignature ) == 0 );
  748. dwCRCSize = sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader ) - sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader.wHeaderCRC );
  749. wCRC = static_cast<WORD>( GenerateCRC( reinterpret_cast<BYTE*>( &m_pActiveRead->m_ReceiveBuffer.MessageHeader ), dwCRCSize ) );
  750. if ( ( m_pActiveRead->m_ReceiveBuffer.MessageHeader.SerialSignature != SERIAL_HEADER_START ) ||
  751. ( wCRC != m_pActiveRead->m_ReceiveBuffer.MessageHeader.wHeaderCRC ) )
  752. {
  753. DWORD dwIndex;
  754. DPFX(DPFPREP, 1, "Header failed signature or CRC check (%u != %u or %u != %u), searching for next header.",
  755. m_pActiveRead->m_ReceiveBuffer.MessageHeader.SerialSignature,
  756. SERIAL_HEADER_START, wCRC,
  757. m_pActiveRead->m_ReceiveBuffer.MessageHeader.wHeaderCRC);
  758. dwIndex = sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader.SerialSignature );
  759. while ( ( dwIndex < sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader ) ) &&
  760. ( m_pActiveRead->m_ReceiveBuffer.ReceivedData[ dwIndex ] != SERIAL_HEADER_START ) )
  761. {
  762. dwIndex++;
  763. }
  764. m_pActiveRead->m_dwBytesToRead = dwIndex;
  765. m_pActiveRead->m_dwReadOffset = sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader ) - dwIndex;
  766. memcpy( &m_pActiveRead->m_ReceiveBuffer.ReceivedData,
  767. &m_pActiveRead->m_ReceiveBuffer.ReceivedData[ dwIndex ],
  768. sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader ) - dwIndex );
  769. }
  770. else
  771. {
  772. m_pActiveRead->SetReadState( READ_STATE_READ_DATA );
  773. m_pActiveRead->m_dwBytesToRead = m_pActiveRead->m_ReceiveBuffer.MessageHeader.wMessageSize;
  774. m_pActiveRead->m_dwReadOffset = sizeof( m_pActiveRead->m_ReceiveBuffer.MessageHeader );
  775. }
  776. #ifdef WIN95
  777. m_pActiveRead->SetWin9xOperationPending( FALSE );
  778. #endif // WIN95
  779. m_pActiveRead->jkm_dwOverlappedBytesReceived = 0;
  780. #ifdef WIN95
  781. m_pSPData->GetThreadPool()->ReinsertInReadList( m_pActiveRead );
  782. #endif // WIN95
  783. Receive();
  784. break;
  785. }
  786. //
  787. // Reading data. Regardless of the validity of the data, start reading
  788. // another frame before processing the current data. If the data is
  789. // valid, send it to a higher layer.
  790. //
  791. case READ_STATE_READ_DATA:
  792. {
  793. WORD wCRC;
  794. CModemReadIOData *pTempRead;
  795. pTempRead = m_pActiveRead;
  796. m_pActiveRead = NULL;
  797. Receive();
  798. DPFX(DPFPREP, 7, "Reading regular data.");
  799. DNASSERT( pTempRead->m_SPReceivedBuffer.BufferDesc.pBufferData == &pTempRead->m_ReceiveBuffer.ReceivedData[ sizeof( pTempRead->m_ReceiveBuffer.MessageHeader ) ] );
  800. wCRC = static_cast<WORD>( GenerateCRC( &pTempRead->m_ReceiveBuffer.ReceivedData[ sizeof( pTempRead->m_ReceiveBuffer.MessageHeader ) ],
  801. pTempRead->m_ReceiveBuffer.MessageHeader.wMessageSize ) );
  802. if ( wCRC == pTempRead->m_ReceiveBuffer.MessageHeader.wMessageCRC )
  803. {
  804. pTempRead->m_SPReceivedBuffer.BufferDesc.dwBufferSize = pTempRead->m_ReceiveBuffer.MessageHeader.wMessageSize;
  805. Lock();
  806. switch ( pTempRead->m_ReceiveBuffer.MessageHeader.MessageTypeToken & ~( ENUM_RTT_MASK ) )
  807. {
  808. //
  809. // User data. Send the data up the connection if there is
  810. // one, otherwise pass it up the listen.
  811. //
  812. case SERIAL_DATA_USER_DATA:
  813. {
  814. if ( m_hConnectEndpoint != 0 )
  815. {
  816. CModemEndpoint *pEndpoint;
  817. pEndpoint = m_pSPData->EndpointFromHandle( m_hConnectEndpoint );
  818. Unlock();
  819. if ( pEndpoint != NULL )
  820. {
  821. pEndpoint->ProcessUserData( pTempRead );
  822. pEndpoint->DecCommandRef();
  823. }
  824. }
  825. else
  826. {
  827. if ( m_hListenEndpoint != 0 )
  828. {
  829. CModemEndpoint *pEndpoint;
  830. pEndpoint = m_pSPData->EndpointFromHandle( m_hListenEndpoint );
  831. Unlock();
  832. if ( pEndpoint != NULL )
  833. {
  834. pEndpoint->ProcessUserDataOnListen( pTempRead );
  835. pEndpoint->DecCommandRef();
  836. }
  837. }
  838. else
  839. {
  840. //
  841. // no endpoint to handle data, drop it
  842. //
  843. Unlock();
  844. }
  845. }
  846. break;
  847. }
  848. //
  849. // Enum query. Send it up the listen.
  850. //
  851. case SERIAL_DATA_ENUM_QUERY:
  852. {
  853. if ( m_hListenEndpoint != 0 )
  854. {
  855. CModemEndpoint *pEndpoint;
  856. pEndpoint = m_pSPData->EndpointFromHandle( m_hListenEndpoint );
  857. Unlock();
  858. if ( pEndpoint != NULL )
  859. {
  860. pEndpoint->ProcessEnumData( &pTempRead->m_SPReceivedBuffer,
  861. pTempRead->m_ReceiveBuffer.MessageHeader.MessageTypeToken & ENUM_RTT_MASK );
  862. pEndpoint->DecCommandRef();
  863. }
  864. }
  865. else
  866. {
  867. //
  868. // no endpoint to handle data, drop it
  869. //
  870. Unlock();
  871. }
  872. break;
  873. }
  874. //
  875. // Enum response. Send it up the enum.
  876. //
  877. case SERIAL_DATA_ENUM_RESPONSE:
  878. {
  879. if ( m_hEnumEndpoint != 0 )
  880. {
  881. CModemEndpoint *pEndpoint;
  882. pEndpoint = m_pSPData->EndpointFromHandle( m_hEnumEndpoint );
  883. Unlock();
  884. if ( pEndpoint != NULL )
  885. {
  886. pEndpoint->ProcessEnumResponseData( &pTempRead->m_SPReceivedBuffer,
  887. pTempRead->m_ReceiveBuffer.MessageHeader.MessageTypeToken & ENUM_RTT_MASK );
  888. pEndpoint->DecCommandRef();
  889. }
  890. }
  891. else
  892. {
  893. //
  894. // no endpoint to handle data, drop it
  895. //
  896. Unlock();
  897. }
  898. break;
  899. }
  900. //
  901. // way busted message!
  902. //
  903. default:
  904. {
  905. Unlock();
  906. DNASSERT( FALSE );
  907. break;
  908. }
  909. }
  910. }
  911. else
  912. {
  913. DPFX(DPFPREP, 1, "Data failed CRC check (%u != %u).",
  914. wCRC, pTempRead->m_ReceiveBuffer.MessageHeader.wMessageCRC);
  915. }
  916. pTempRead->DecRef();
  917. break;
  918. }
  919. //
  920. // other state
  921. //
  922. default:
  923. {
  924. DNASSERT( FALSE );
  925. break;
  926. }
  927. }
  928. }
  929. Exit:
  930. DecRef();
  931. return;
  932. }
  933. //**********************************************************************
  934. //**********************************************************************
  935. // ------------------------------
  936. // CDataPort::EnumAdapters - enumerate adapters
  937. //
  938. // Entry: Pointer to enum adapters data
  939. //
  940. // Exit: Error code
  941. // ------------------------------
  942. #undef DPF_MODNAME
  943. #define DPF_MODNAME "CDataPort::EnumAdapters"
  944. HRESULT CDataPort::EnumAdapters( SPENUMADAPTERSDATA *const pEnumAdaptersData ) const
  945. {
  946. if (m_fModem)
  947. {
  948. HRESULT hr;
  949. #ifndef UNICODE
  950. HRESULT hTempResult;
  951. #endif // ! UNICODE
  952. DWORD dwRequiredSize;
  953. DWORD dwDetectedTAPIDeviceCount;
  954. DWORD dwModemNameDataSize;
  955. MODEM_NAME_DATA *pModemNameData;
  956. UINT_PTR uIndex;
  957. WCHAR *pOutputName;
  958. DWORD dwRemainingStringSize;
  959. DWORD dwConvertedStringSize;
  960. DNASSERT( pEnumAdaptersData != NULL );
  961. DNASSERT( ( pEnumAdaptersData->pAdapterData != NULL ) || ( pEnumAdaptersData->dwAdapterDataSize == 0 ) );
  962. //
  963. // initialize
  964. //
  965. hr = DPN_OK;
  966. dwRequiredSize = 0;
  967. dwModemNameDataSize = 0;
  968. pModemNameData = NULL;
  969. pEnumAdaptersData->dwAdapterCount = 0;
  970. hr = GenerateAvailableModemList( GetSPData()->GetThreadPool()->GetTAPIInfo(),
  971. &dwDetectedTAPIDeviceCount,
  972. pModemNameData,
  973. &dwModemNameDataSize );
  974. switch ( hr )
  975. {
  976. //
  977. // there are no modems!
  978. //
  979. case DPN_OK:
  980. {
  981. goto ExitMODEM;
  982. break;
  983. }
  984. //
  985. // buffer was too small (expected return), keep processing
  986. //
  987. case DPNERR_BUFFERTOOSMALL:
  988. {
  989. break;
  990. }
  991. //
  992. // other
  993. //
  994. default:
  995. {
  996. DPFX(DPFPREP, 0, "EnumAdapters: Failed to enumerate modems!" );
  997. DisplayDNError( 0, hr );
  998. goto FailureMODEM;
  999. break;
  1000. }
  1001. }
  1002. pModemNameData = static_cast<MODEM_NAME_DATA*>( DNMalloc( dwModemNameDataSize ) );
  1003. if ( pModemNameData == NULL )
  1004. {
  1005. DPFX(DPFPREP, 0, "Failed to allocate temp buffer to enumerate modems!" );
  1006. DisplayDNError( 0, hr );
  1007. }
  1008. hr = GenerateAvailableModemList( GetSPData()->GetThreadPool()->GetTAPIInfo(),
  1009. &dwDetectedTAPIDeviceCount,
  1010. pModemNameData,
  1011. &dwModemNameDataSize );
  1012. DNASSERT( hr == DPN_OK );
  1013. //
  1014. // compute required size, check for the need to add 'all adapters'
  1015. //
  1016. dwRequiredSize += sizeof( *pEnumAdaptersData->pAdapterData ) * dwDetectedTAPIDeviceCount;
  1017. uIndex = dwDetectedTAPIDeviceCount;
  1018. while ( uIndex != 0 )
  1019. {
  1020. uIndex--;
  1021. //
  1022. // account for unicode conversion
  1023. //
  1024. dwRequiredSize += pModemNameData[ uIndex ].dwModemNameSize * ( sizeof( *pEnumAdaptersData->pAdapterData->pwszName ) / sizeof( *pModemNameData[ uIndex ].pModemName ) );
  1025. }
  1026. //
  1027. // check required size
  1028. //
  1029. if ( pEnumAdaptersData->dwAdapterDataSize < dwRequiredSize )
  1030. {
  1031. pEnumAdaptersData->dwAdapterDataSize = dwRequiredSize;
  1032. hr = DPNERR_BUFFERTOOSMALL;
  1033. DPFX(DPFPREP, 0, "EnumAdapters: Insufficient buffer to enumerate adapters!" );
  1034. goto FailureMODEM;
  1035. }
  1036. //
  1037. // copy information into user buffer
  1038. //
  1039. DEBUG_ONLY( memset( pEnumAdaptersData->pAdapterData, 0xAA, dwRequiredSize ) );
  1040. DBG_CASSERT( sizeof( pOutputName ) == sizeof( &pEnumAdaptersData->pAdapterData[ dwDetectedTAPIDeviceCount ] ) );
  1041. pOutputName = reinterpret_cast<WCHAR*>( &pEnumAdaptersData->pAdapterData[ dwDetectedTAPIDeviceCount ] );
  1042. //
  1043. // compute number of WCHAR characters we have remaining in the buffer to output
  1044. // devices names into
  1045. //
  1046. dwRemainingStringSize = dwRequiredSize;
  1047. dwRemainingStringSize -= ( sizeof( *pEnumAdaptersData->pAdapterData ) * dwDetectedTAPIDeviceCount );
  1048. dwRemainingStringSize /= sizeof( *pEnumAdaptersData->pAdapterData->pwszName );
  1049. uIndex = dwDetectedTAPIDeviceCount;
  1050. while ( uIndex > 0 )
  1051. {
  1052. uIndex--;
  1053. pEnumAdaptersData->pAdapterData[ uIndex ].dwFlags = 0;
  1054. pEnumAdaptersData->pAdapterData[ uIndex ].pwszName = pOutputName;
  1055. pEnumAdaptersData->pAdapterData[ uIndex ].dwReserved = 0;
  1056. pEnumAdaptersData->pAdapterData[ uIndex ].pvReserved = NULL;
  1057. DeviceIDToGuid( &pEnumAdaptersData->pAdapterData[ uIndex ].guid,
  1058. pModemNameData[ uIndex ].dwModemID,
  1059. &g_ModemSPEncryptionGuid );
  1060. dwConvertedStringSize = dwRemainingStringSize;
  1061. #ifdef UNICODE
  1062. wcscpy(pOutputName, pModemNameData[ uIndex ].pModemName);
  1063. dwConvertedStringSize = wcslen(pOutputName) + 1;
  1064. #else
  1065. hTempResult = AnsiToWide( pModemNameData[ uIndex ].pModemName, -1, pOutputName, &dwConvertedStringSize );
  1066. DNASSERT( hTempResult == DPN_OK );
  1067. DNASSERT( dwConvertedStringSize <= dwRemainingStringSize );
  1068. #endif // UNICODE
  1069. dwRemainingStringSize -= dwConvertedStringSize;
  1070. pOutputName = &pOutputName[ dwConvertedStringSize ];
  1071. }
  1072. pEnumAdaptersData->dwAdapterCount = dwDetectedTAPIDeviceCount;
  1073. pEnumAdaptersData->dwAdapterDataSize = dwRequiredSize;
  1074. ExitMODEM:
  1075. if ( pModemNameData != NULL )
  1076. {
  1077. DNFree( pModemNameData );
  1078. pModemNameData = NULL;
  1079. }
  1080. return hr;
  1081. FailureMODEM:
  1082. goto ExitMODEM;
  1083. }
  1084. else
  1085. {
  1086. HRESULT hr;
  1087. #ifndef UNICODE
  1088. HRESULT hTempResult;
  1089. #endif // ! UNICODE
  1090. BOOL fPortAvailable[ MAX_DATA_PORTS ];
  1091. DWORD dwValidPortCount;
  1092. WCHAR *pWorkingString;
  1093. INT_PTR iIdx;
  1094. INT_PTR iOutputIdx;
  1095. DWORD dwRequiredDataSize = 0;
  1096. DWORD dwConvertedStringSize;
  1097. DWORD dwRemainingStringSize;
  1098. DEBUG_ONLY( DNASSERT( m_fInitialized != FALSE ) );
  1099. DNASSERT( pEnumAdaptersData != NULL );
  1100. DNASSERT( ( pEnumAdaptersData->pAdapterData != NULL ) || ( pEnumAdaptersData->dwAdapterDataSize == 0 ) );
  1101. //
  1102. // initialize
  1103. //
  1104. hr = DPN_OK;
  1105. hr = GenerateAvailableComPortList( fPortAvailable, LENGTHOF( fPortAvailable ) - 1, &dwValidPortCount );
  1106. if ( hr != DPN_OK )
  1107. {
  1108. DPFX(DPFPREP, 0, "Failed to generate list of available comports!" );
  1109. DisplayDNError( 0, hr );
  1110. goto FailureCOM;
  1111. }
  1112. dwRequiredDataSize = sizeof( *pEnumAdaptersData->pAdapterData ) * dwValidPortCount;
  1113. iIdx = LENGTHOF( fPortAvailable );
  1114. while ( iIdx > 0 )
  1115. {
  1116. iIdx--;
  1117. //
  1118. // compute exact size based on the com port number
  1119. //
  1120. if ( fPortAvailable[ iIdx ] != FALSE )
  1121. {
  1122. if ( iIdx > 100 )
  1123. {
  1124. dwRequiredDataSize += sizeof( *pEnumAdaptersData->pAdapterData->pwszName ) * 7;
  1125. }
  1126. else
  1127. {
  1128. if ( iIdx > 10 )
  1129. {
  1130. dwRequiredDataSize += sizeof( *pEnumAdaptersData->pAdapterData->pwszName ) * 6;
  1131. }
  1132. else
  1133. {
  1134. dwRequiredDataSize += sizeof( *pEnumAdaptersData->pAdapterData->pwszName ) * 5;
  1135. }
  1136. }
  1137. }
  1138. }
  1139. if ( pEnumAdaptersData->dwAdapterDataSize < dwRequiredDataSize )
  1140. {
  1141. hr = DPNERR_BUFFERTOOSMALL;
  1142. pEnumAdaptersData->dwAdapterDataSize = dwRequiredDataSize;
  1143. DPFX(DPFPREP, 8, "Buffer too small when enumerating comport adapters!" );
  1144. goto ExitCOM;
  1145. }
  1146. //
  1147. // if there are no adapters, bail
  1148. //
  1149. if ( dwValidPortCount == 0 )
  1150. {
  1151. // debug me!
  1152. DNASSERT( FALSE );
  1153. DNASSERT( dwRequiredDataSize == 0 );
  1154. DNASSERT( pEnumAdaptersData->dwAdapterCount == 0 );
  1155. goto ExitCOM;
  1156. }
  1157. DNASSERT( dwValidPortCount >= 1 );
  1158. dwRemainingStringSize = ( dwRequiredDataSize - ( ( sizeof( *pEnumAdaptersData->pAdapterData ) ) * dwValidPortCount ) ) / sizeof( *pEnumAdaptersData->pAdapterData->pwszName );
  1159. //
  1160. // we've got enough space, start building structures
  1161. //
  1162. DEBUG_ONLY( memset( pEnumAdaptersData->pAdapterData, 0xAA, dwRequiredDataSize ) );
  1163. pEnumAdaptersData->dwAdapterCount = dwValidPortCount;
  1164. DBG_CASSERT( sizeof( &pEnumAdaptersData->pAdapterData[ dwValidPortCount ] ) == sizeof( WCHAR* ) );
  1165. pWorkingString = reinterpret_cast<WCHAR*>( &pEnumAdaptersData->pAdapterData[ dwValidPortCount ] );
  1166. iIdx = 1;
  1167. iOutputIdx = 0;
  1168. while ( iIdx < MAX_DATA_PORTS )
  1169. {
  1170. //
  1171. // convert to guid if it's valid
  1172. //
  1173. if ( fPortAvailable[ iIdx ] != FALSE )
  1174. {
  1175. TCHAR TempBuffer[ (COM_PORT_STRING_LENGTH + 1) ];
  1176. //
  1177. // convert device ID to a string and check for local buffer overrun
  1178. //
  1179. DEBUG_ONLY( TempBuffer[ LENGTHOF( TempBuffer ) - 1 ] = 0x5a );
  1180. ComDeviceIDToString( TempBuffer, iIdx );
  1181. DEBUG_ONLY( DNASSERT( TempBuffer[ LENGTHOF( TempBuffer ) - 1 ] == 0x5a ) );
  1182. #ifdef UNICODE
  1183. dwConvertedStringSize = lstrlen(TempBuffer) + 1;
  1184. lstrcpy(pWorkingString, TempBuffer);
  1185. #else
  1186. dwConvertedStringSize = dwRemainingStringSize;
  1187. hTempResult = AnsiToWide( TempBuffer, -1, pWorkingString, &dwConvertedStringSize );
  1188. DNASSERT( hTempResult == DPN_OK );
  1189. #endif // UNICODE
  1190. DNASSERT( dwRemainingStringSize >= dwConvertedStringSize );
  1191. dwRemainingStringSize -= dwConvertedStringSize;
  1192. pEnumAdaptersData->pAdapterData[ iOutputIdx ].dwFlags = 0;
  1193. pEnumAdaptersData->pAdapterData[ iOutputIdx ].pvReserved = NULL;
  1194. pEnumAdaptersData->pAdapterData[ iOutputIdx ].dwReserved = NULL;
  1195. DeviceIDToGuid( &pEnumAdaptersData->pAdapterData[ iOutputIdx ].guid, iIdx, &g_SerialSPEncryptionGuid );
  1196. pEnumAdaptersData->pAdapterData[ iOutputIdx ].pwszName = pWorkingString;
  1197. pWorkingString = &pWorkingString[ dwConvertedStringSize ];
  1198. iOutputIdx++;
  1199. DEBUG_ONLY( dwValidPortCount-- );
  1200. }
  1201. iIdx++;
  1202. }
  1203. DEBUG_ONLY( DNASSERT( dwValidPortCount == 0 ) );
  1204. DNASSERT( dwRemainingStringSize == 0 );
  1205. ExitCOM:
  1206. //
  1207. // set size of output data
  1208. //
  1209. pEnumAdaptersData->dwAdapterDataSize = dwRequiredDataSize;
  1210. return hr;
  1211. FailureCOM:
  1212. goto ExitCOM;
  1213. }
  1214. }
  1215. //**********************************************************************
  1216. //**********************************************************************
  1217. // ------------------------------
  1218. // CDataPort::GetLocalAdapterDP8Address - get the IDirectPlay8 address for this
  1219. // adapter
  1220. //
  1221. // Entry: Adapter type
  1222. //
  1223. // Exit: Pointer to address (may be null)
  1224. // ------------------------------
  1225. #undef DPF_MODNAME
  1226. #define DPF_MODNAME "CDataPort::GetLocalAdapterDP8Address"
  1227. IDirectPlay8Address *CDataPort::GetLocalAdapterDP8Address( const ADDRESS_TYPE AddressType ) const
  1228. {
  1229. IDirectPlay8Address *pAddress;
  1230. HRESULT hr;
  1231. DNASSERT ( ( AddressType == ADDRESS_TYPE_LOCAL_ADAPTER ) ||
  1232. ( AddressType == ADDRESS_TYPE_LOCAL_ADAPTER_HOST_FORMAT ) );
  1233. //
  1234. // initialize
  1235. //
  1236. pAddress = NULL;
  1237. hr = COM_CoCreateInstance( CLSID_DirectPlay8Address,
  1238. NULL,
  1239. CLSCTX_INPROC_SERVER,
  1240. IID_IDirectPlay8Address,
  1241. reinterpret_cast<void**>( &pAddress ), FALSE );
  1242. if ( hr != DPN_OK )
  1243. {
  1244. DNASSERT( pAddress == NULL );
  1245. DPFX(DPFPREP, 0, "GetLocalAdapterDP8Address: Failed to create Address when converting data port to address!" );
  1246. goto Failure;
  1247. }
  1248. //
  1249. // set the SP guid
  1250. //
  1251. hr = IDirectPlay8Address_SetSP( pAddress, &CLSID_DP8SP_MODEM );
  1252. if ( hr != DPN_OK )
  1253. {
  1254. DPFX(DPFPREP, 0, "GetLocalAdapterDP8Address: Failed to set service provider GUID!" );
  1255. DisplayDNError( 0, hr );
  1256. goto Failure;
  1257. }
  1258. //
  1259. // If this machine is in host form, return nothing because there isn't a
  1260. // local phone number associated with this modem. Otherwise returnt the
  1261. // device GUID.
  1262. //
  1263. if ( AddressType == ADDRESS_TYPE_LOCAL_ADAPTER )
  1264. {
  1265. GUID DeviceGuid;
  1266. DeviceIDToGuid( &DeviceGuid, GetDeviceID(), &g_ModemSPEncryptionGuid );
  1267. hr = IDirectPlay8Address_SetDevice( pAddress, &DeviceGuid );
  1268. if ( hr != DPN_OK )
  1269. {
  1270. DPFX(DPFPREP, 0, "GetLocalAdapterDP8Address: Failed to add device GUID!" );
  1271. DisplayDNError( 0, hr );
  1272. goto Failure;
  1273. }
  1274. }
  1275. Exit:
  1276. return pAddress;
  1277. Failure:
  1278. if ( pAddress != NULL )
  1279. {
  1280. IDirectPlay8Address_Release( pAddress );
  1281. pAddress = NULL;
  1282. }
  1283. goto Exit;
  1284. }
  1285. //**********************************************************************
  1286. //**********************************************************************
  1287. // ------------------------------
  1288. // CDataPort::BindToNetwork - bind this data port to the network
  1289. //
  1290. // Entry: Device ID
  1291. // Pointer to device context
  1292. //
  1293. // Exit: Error code
  1294. // ------------------------------
  1295. #undef DPF_MODNAME
  1296. #define DPF_MODNAME "CDataPort::BindToNetwork"
  1297. HRESULT CDataPort::BindToNetwork( const DWORD dwDeviceID, const void *const pDeviceContext )
  1298. {
  1299. if (m_fModem)
  1300. {
  1301. HRESULT hr;
  1302. LONG lTapiReturn;
  1303. const TAPI_INFO *pTapiInfo;
  1304. LINEEXTENSIONID LineExtensionID;
  1305. DNASSERT( pDeviceContext == NULL );
  1306. DNASSERT( GetModemState() == MODEM_STATE_UNKNOWN );
  1307. //
  1308. // initialize
  1309. //
  1310. hr = DPN_OK;
  1311. hr = SetDeviceID( dwDeviceID );
  1312. DNASSERT( hr == DPN_OK );
  1313. pTapiInfo = GetSPData()->GetThreadPool()->GetTAPIInfo();
  1314. DNASSERT( pTapiInfo != NULL );
  1315. memset( &LineExtensionID, 0x00, sizeof( LineExtensionID ) );
  1316. //
  1317. // grab the modem
  1318. //
  1319. DNASSERT( GetNegotiatedAPIVersion() == 0 );
  1320. DPFX(DPFPREP, 5, "lineNegotiateAPIVersion" );
  1321. lTapiReturn = p_lineNegotiateAPIVersion( pTapiInfo->hApplicationInstance, // TAPI application instance
  1322. TAPIIDFromModemID( GetDeviceID() ), // TAPI ID for modem
  1323. 0,
  1324. pTapiInfo->dwVersion, // min API version
  1325. &m_dwNegotiatedAPIVersion, // negotiated version
  1326. &LineExtensionID // line extension ID
  1327. );
  1328. if ( lTapiReturn != LINEERR_NONE )
  1329. {
  1330. DPFX(DPFPREP, 0, "Failed to negotiate modem version!" );
  1331. DisplayTAPIError( 0, lTapiReturn );
  1332. hr = DPNERR_NOCONNECTION;
  1333. goto FailureMODEM;
  1334. }
  1335. DNASSERT( GetNegotiatedAPIVersion() != 0 );
  1336. DNASSERT( GetLineHandle() == NULL );
  1337. DBG_CASSERT( sizeof( HANDLE ) == sizeof( DWORD_PTR ) );
  1338. DPFX(DPFPREP, 5, "lineOpen %d", TAPIIDFromModemID( GetDeviceID() ) );
  1339. lTapiReturn = p_lineOpen( pTapiInfo->hApplicationInstance, // TAPI application instance
  1340. TAPIIDFromModemID( GetDeviceID() ), // TAPI ID for modem
  1341. &m_hLine, // pointer to line handle
  1342. GetNegotiatedAPIVersion(), // API version
  1343. 0, // extension version (none)
  1344. (DWORD_PTR)( GetHandle() ), // callback context
  1345. LINECALLPRIVILEGE_OWNER, // priveleges (full ownership)
  1346. LINEMEDIAMODE_DATAMODEM, // media mode
  1347. NULL // call parameters (none)
  1348. );
  1349. if ( lTapiReturn != LINEERR_NONE )
  1350. {
  1351. DPFX(DPFPREP, 0, "Failed to open modem!" );
  1352. DisplayTAPIError( 0, lTapiReturn );
  1353. if ( lTapiReturn == LINEERR_RESOURCEUNAVAIL )
  1354. {
  1355. hr = DPNERR_OUTOFMEMORY;
  1356. }
  1357. else
  1358. {
  1359. hr = DPNERR_NOCONNECTION;
  1360. }
  1361. goto FailureMODEM;
  1362. }
  1363. DPFX(DPFPREP, 5, "\nTAPI line opened: 0x%x", GetLineHandle() );
  1364. SetModemState( MODEM_STATE_INITIALIZED );
  1365. ExitMODEM:
  1366. return hr;
  1367. FailureMODEM:
  1368. SetDeviceID( INVALID_DEVICE_ID );
  1369. SetNegotiatedAPIVersion( 0 );
  1370. DNASSERT( GetLineHandle() == NULL );
  1371. goto ExitMODEM;
  1372. }
  1373. else
  1374. {
  1375. HRESULT hr;
  1376. const CComPortData *pDataPortData;
  1377. DNASSERT( pDeviceContext != NULL );
  1378. //
  1379. // initialize
  1380. //
  1381. hr = DPN_OK;
  1382. pDataPortData = static_cast<const CComPortData*>( pDeviceContext );
  1383. m_ComPortData.Copy( pDataPortData );
  1384. //
  1385. // open port
  1386. //
  1387. DNASSERT( m_hFile == DNINVALID_HANDLE_VALUE );
  1388. m_hFile = DNCreateFile( m_ComPortData.ComPortName(), // comm port
  1389. GENERIC_READ | GENERIC_WRITE, // read/write access
  1390. 0, // don't share file with others
  1391. NULL, // default sercurity descriptor
  1392. OPEN_EXISTING, // comm port must exist to be opened
  1393. FILE_FLAG_OVERLAPPED, // use overlapped I/O
  1394. NULL // no handle for template file
  1395. );
  1396. if ( m_hFile == DNINVALID_HANDLE_VALUE )
  1397. {
  1398. DWORD dwError;
  1399. hr = DPNERR_NOCONNECTION;
  1400. dwError = GetLastError();
  1401. DPFX(DPFPREP, 0, "CreateFile() failed!" );
  1402. DisplayErrorCode( 0, dwError );
  1403. goto FailureCOM;
  1404. }
  1405. //
  1406. // bind to completion port for NT
  1407. //
  1408. #ifdef WINNT
  1409. HANDLE hCompletionPort;
  1410. hCompletionPort = CreateIoCompletionPort( HANDLE_FROM_DNHANDLE(m_hFile), // current file handle
  1411. GetSPData()->GetThreadPool()->GetIOCompletionPort(), // handle of completion port
  1412. IO_COMPLETION_KEY_IO_COMPLETE, // completion key
  1413. 0 // number of concurrent threads (default to number of processors)
  1414. );
  1415. if ( hCompletionPort == NULL )
  1416. {
  1417. DWORD dwError;
  1418. hr = DPNERR_OUTOFMEMORY;
  1419. dwError = GetLastError();
  1420. DPFX(DPFPREP, 0, "Cannot bind comport to completion port!" );
  1421. DisplayErrorCode( 0, dwError );
  1422. goto FailureCOM;
  1423. }
  1424. DNASSERT( hCompletionPort == GetSPData()->GetThreadPool()->GetIOCompletionPort() );
  1425. #endif // WINNT
  1426. //
  1427. // set bit rate, etc.
  1428. //
  1429. hr = SetPortState();
  1430. if ( hr != DPN_OK )
  1431. {
  1432. DPFX(DPFPREP, 0, "Problem with SetPortState" );
  1433. DisplayDNError( 0, hr );
  1434. goto FailureCOM;
  1435. }
  1436. //
  1437. // set general comminications paramters (timeouts, etc.)
  1438. //
  1439. hr = SetPortCommunicationParameters();
  1440. if ( hr != DPN_OK )
  1441. {
  1442. DPFX(DPFPREP, 0, "Failed to set communication paramters!" );
  1443. DisplayDNError( 0, hr );
  1444. goto FailureCOM;
  1445. }
  1446. //
  1447. // start receiving
  1448. //
  1449. hr = StartReceiving();
  1450. if ( hr != DPN_OK )
  1451. {
  1452. DPFX(DPFPREP, 0, "Failed to start receiving!" );
  1453. DisplayDNError( 0, hr );
  1454. goto FailureCOM;
  1455. }
  1456. ExitCOM:
  1457. if ( hr != DPN_OK )
  1458. {
  1459. DPFX(DPFPREP, 0, "Problem with CDataPort::Open" );
  1460. DisplayDNError( 0, hr );
  1461. }
  1462. return hr;
  1463. FailureCOM:
  1464. if ( m_hFile != DNINVALID_HANDLE_VALUE )
  1465. {
  1466. DNCloseHandle( m_hFile );
  1467. m_hFile = DNINVALID_HANDLE_VALUE;
  1468. }
  1469. // Close();
  1470. goto ExitCOM;
  1471. }
  1472. }
  1473. //**********************************************************************
  1474. //**********************************************************************
  1475. // ------------------------------
  1476. // CDataPort::UnbindFromNetwork - unbind this data port from the network
  1477. //
  1478. // Entry: Nothing
  1479. //
  1480. // Exit: Nothing
  1481. // ------------------------------
  1482. #undef DPF_MODNAME
  1483. #define DPF_MODNAME "CDataPort::UnbindFromNetwork"
  1484. void CDataPort::UnbindFromNetwork( void )
  1485. {
  1486. DPFX(DPFPREP, 6, "(0x%p) Enter", this);
  1487. if (m_fModem)
  1488. {
  1489. if ( GetHandle() != 0 )
  1490. {
  1491. GetSPData()->GetThreadPool()->CloseDataPortHandle( this );
  1492. DNASSERT( GetHandle() == 0 );
  1493. }
  1494. if ( GetCallHandle() != NULL )
  1495. {
  1496. LONG lTapiResult;
  1497. DPFX(DPFPREP, 5, "lineDrop: 0x%x", GetCallHandle() );
  1498. lTapiResult = p_lineDrop( GetCallHandle(), NULL, 0 );
  1499. if ( lTapiResult < 0 )
  1500. {
  1501. DPFX(DPFPREP, 0, "Problem dropping line!" );
  1502. DisplayTAPIError( 0, lTapiResult );
  1503. }
  1504. DPFX(DPFPREP, 5, "lineDeallocateCall (call handle=0x%x)", GetCallHandle() );
  1505. lTapiResult = p_lineDeallocateCall( GetCallHandle() );
  1506. if ( lTapiResult != LINEERR_NONE )
  1507. {
  1508. DPFX(DPFPREP, 0, "Problem deallocating call!" );
  1509. DisplayTAPIError( 0, lTapiResult );
  1510. }
  1511. }
  1512. if ( GetLineHandle() != NULL )
  1513. {
  1514. LONG lTapiResult;
  1515. DPFX(DPFPREP, 5, "lineClose: 0x%x", GetLineHandle() );
  1516. lTapiResult = p_lineClose( GetLineHandle() );
  1517. if ( lTapiResult != LINEERR_NONE )
  1518. {
  1519. DPFX(DPFPREP, 0, "Problem closing line!" );
  1520. DisplayTAPIError( 0, lTapiResult );
  1521. }
  1522. }
  1523. SetCallHandle( NULL );
  1524. if ( GetFileHandle() != DNINVALID_HANDLE_VALUE )
  1525. {
  1526. DPFX(DPFPREP, 5, "Closing file handle when unbinding from network!" );
  1527. if ( DNCloseHandle( m_hFile ) == FALSE )
  1528. {
  1529. DWORD dwError;
  1530. dwError = GetLastError();
  1531. DPFX(DPFPREP, 0, "Failed to close file handle!" );
  1532. DisplayErrorCode( 0, dwError );
  1533. }
  1534. m_hFile = DNINVALID_HANDLE_VALUE;
  1535. }
  1536. SetActiveLineCommand( INVALID_TAPI_COMMAND );
  1537. SetDeviceID( INVALID_DEVICE_ID );
  1538. SetNegotiatedAPIVersion( 0 );
  1539. SetLineHandle( NULL );
  1540. SetModemState( MODEM_STATE_UNKNOWN );
  1541. }
  1542. else
  1543. {
  1544. #ifdef WIN95
  1545. CModemReadIOData * pReadData;
  1546. #endif // WIN95
  1547. DNASSERT( GetState() == DATA_PORT_STATE_UNBOUND );
  1548. if ( GetHandle() != 0 )
  1549. {
  1550. GetSPData()->GetThreadPool()->CloseDataPortHandle( this );
  1551. DNASSERT( GetHandle() == 0 );
  1552. }
  1553. //
  1554. // if there's a com file, purge all communications and close it
  1555. //
  1556. if ( m_hFile != DNINVALID_HANDLE_VALUE )
  1557. {
  1558. DPFX(DPFPREP, 6, "Flushing and closing COM port file handle 0x%p.", m_hFile);
  1559. //
  1560. // wait until all writes have completed
  1561. //
  1562. if ( FlushFileBuffers( HANDLE_FROM_DNHANDLE(m_hFile) ) == FALSE )
  1563. {
  1564. DWORD dwError;
  1565. dwError = GetLastError();
  1566. DPFX(DPFPREP, 0, "Problem with FlushFileBuffers() when closing com port!" );
  1567. DisplayErrorCode( 0, dwError );
  1568. }
  1569. //
  1570. // force all communication to complete
  1571. //
  1572. if ( PurgeComm( HANDLE_FROM_DNHANDLE(m_hFile), ( PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ) == FALSE )
  1573. {
  1574. DWORD dwError;
  1575. dwError = GetLastError();
  1576. DPFX(DPFPREP, 0, "Problem with PurgeComm() when closing com port!" );
  1577. DisplayErrorCode( 0, dwError );
  1578. }
  1579. #ifdef WIN95
  1580. pReadData = this->GetActiveRead();
  1581. //
  1582. // if there is a pending read, wait until it completes
  1583. //
  1584. if ( pReadData != NULL )
  1585. {
  1586. //
  1587. // pull it out of the list so the regular receive thread doesn't catch the completion
  1588. //
  1589. GetSPData()->GetThreadPool()->LockReadData();
  1590. pReadData->m_OutstandingReadListLinkage.RemoveFromList();
  1591. GetSPData()->GetThreadPool()->UnlockReadData();
  1592. if ( pReadData->Win9xOperationPending() != FALSE )
  1593. {
  1594. DWORD dwAttempt;
  1595. dwAttempt = 0;
  1596. WaitAgain:
  1597. DPFX(DPFPREP, 1, "Checking if read 0x%p has completed.", pReadData );
  1598. if ( GetOverlappedResult( HANDLE_FROM_DNHANDLE(m_hFile),
  1599. pReadData->Overlap(),
  1600. &pReadData->jkm_dwOverlappedBytesReceived,
  1601. FALSE
  1602. ) != FALSE )
  1603. {
  1604. DBG_CASSERT( ERROR_SUCCESS == 0 );
  1605. pReadData->m_dwWin9xReceiveErrorReturn = ERROR_SUCCESS;
  1606. }
  1607. else
  1608. {
  1609. DWORD dwError;
  1610. //
  1611. // other error, stop if not 'known'
  1612. //
  1613. dwError = GetLastError();
  1614. switch( dwError )
  1615. {
  1616. //
  1617. // ERROR_IO_INCOMPLETE = treat as I/O complete. Event isn't
  1618. // signalled, but that's expected because
  1619. // it's cleared before checking for I/O
  1620. //
  1621. case ERROR_IO_INCOMPLETE:
  1622. {
  1623. pReadData->jkm_dwOverlappedBytesReceived = pReadData->m_dwBytesToRead;
  1624. pReadData->m_dwWin9xReceiveErrorReturn = ERROR_SUCCESS;
  1625. break;
  1626. }
  1627. //
  1628. // ERROR_IO_PENDING = io still pending
  1629. //
  1630. case ERROR_IO_PENDING:
  1631. {
  1632. dwAttempt++;
  1633. if (dwAttempt <= 6)
  1634. {
  1635. DPFX(DPFPREP, 1, "Read data 0x%p has not completed yet, waiting for %u ms.",
  1636. pReadData, (dwAttempt * 100));
  1637. SleepEx(dwAttempt, TRUE);
  1638. goto WaitAgain;
  1639. }
  1640. DPFX(DPFPREP, 0, "Read data 0x%p still not marked as completed, ignoring.",
  1641. pReadData);
  1642. break;
  1643. }
  1644. //
  1645. // ERROR_OPERATION_ABORTED = operation was cancelled (COM port closed)
  1646. // ERROR_INVALID_HANDLE = operation was cancelled (COM port closed)
  1647. //
  1648. case ERROR_OPERATION_ABORTED:
  1649. case ERROR_INVALID_HANDLE:
  1650. {
  1651. break;
  1652. }
  1653. default:
  1654. {
  1655. DisplayErrorCode( 0, dwError );
  1656. DNASSERT( FALSE );
  1657. break;
  1658. }
  1659. }
  1660. pReadData->m_dwWin9xReceiveErrorReturn = dwError;
  1661. }
  1662. DNASSERT( pReadData->Win9xOperationPending() != FALSE );
  1663. pReadData->SetWin9xOperationPending( FALSE );
  1664. DNASSERT( pReadData->DataPort() == this );
  1665. this->ProcessReceivedData( pReadData->jkm_dwOverlappedBytesReceived, pReadData->m_dwWin9xReceiveErrorReturn );
  1666. }
  1667. }
  1668. else
  1669. {
  1670. //
  1671. // it's not pending Win9x style, ignore it and hope a receive
  1672. // thread picked up the completion
  1673. //
  1674. DPFX(DPFPREP, 8, "Read data 0x%p not pending Win9x style, assuming receive thread picked up completion." );
  1675. }
  1676. #endif // WIN95
  1677. if ( DNCloseHandle( m_hFile ) == FALSE )
  1678. {
  1679. DWORD dwError;
  1680. dwError = GetLastError();
  1681. DPFX(DPFPREP, 0, "Problem with CloseHandle(): 0x%x", dwError );
  1682. }
  1683. m_hFile = DNINVALID_HANDLE_VALUE;
  1684. }
  1685. SetLinkDirection( LINK_DIRECTION_UNKNOWN );
  1686. }
  1687. DPFX(DPFPREP, 6, "(0x%p) Leave", this);
  1688. }
  1689. //**********************************************************************
  1690. //**********************************************************************
  1691. // ------------------------------
  1692. // CDataPort::BindEndpoint - bind endpoint to this data port
  1693. //
  1694. // Entry: Pointer to endpoint
  1695. // Endpoint type
  1696. //
  1697. // Exit: Error code
  1698. // ------------------------------
  1699. #undef DPF_MODNAME
  1700. #define DPF_MODNAME "CDataPort::BindEndpoint"
  1701. HRESULT CDataPort::BindEndpoint( CModemEndpoint *const pEndpoint, const ENDPOINT_TYPE EndpointType )
  1702. {
  1703. HRESULT hr;
  1704. IDirectPlay8Address *pDeviceAddress;
  1705. IDirectPlay8Address *pHostAddress;
  1706. DPFX(DPFPREP, 6, "(0x%p) Parameters: (0x%p, %u)", this, pEndpoint, EndpointType);
  1707. DNASSERT( pEndpoint != NULL );
  1708. //
  1709. // initialize
  1710. //
  1711. hr = DPN_OK;
  1712. pDeviceAddress = NULL;
  1713. pHostAddress = NULL;
  1714. Lock();
  1715. if (m_fModem)
  1716. {
  1717. //
  1718. // we're only allowed one endpoint of any given type so determine which
  1719. // type and then bind the endpoint
  1720. //
  1721. switch ( EndpointType )
  1722. {
  1723. case ENDPOINT_TYPE_ENUM:
  1724. case ENDPOINT_TYPE_CONNECT:
  1725. case ENDPOINT_TYPE_CONNECT_ON_LISTEN:
  1726. {
  1727. CModemEndpoint *pModemEndpoint;
  1728. LONG lTapiReturn;
  1729. LINECALLPARAMS LineCallParams;
  1730. pModemEndpoint = static_cast<CModemEndpoint*>( pEndpoint );
  1731. switch ( EndpointType )
  1732. {
  1733. //
  1734. // reject for duplicated endpoints
  1735. //
  1736. case ENDPOINT_TYPE_CONNECT:
  1737. case ENDPOINT_TYPE_CONNECT_ON_LISTEN:
  1738. {
  1739. if ( m_hConnectEndpoint != 0 )
  1740. {
  1741. hr = DPNERR_ALREADYINITIALIZED;
  1742. DPFX(DPFPREP, 0, "Attempted to bind connect endpoint when one already exists.!" );
  1743. goto Failure;
  1744. }
  1745. m_hConnectEndpoint = pEndpoint->GetHandle();
  1746. if ( EndpointType == ENDPOINT_TYPE_CONNECT )
  1747. {
  1748. SPIE_CONNECTADDRESSINFO ConnectAddressInfo;
  1749. HRESULT hTempResult;
  1750. //
  1751. // set addresses in addressing information
  1752. //
  1753. pDeviceAddress = GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  1754. pHostAddress = pEndpoint->GetRemoteHostDP8Address();
  1755. memset( &ConnectAddressInfo, 0x00, sizeof( ConnectAddressInfo ) );
  1756. ConnectAddressInfo.pDeviceAddress = pDeviceAddress;
  1757. ConnectAddressInfo.pHostAddress = pHostAddress;
  1758. ConnectAddressInfo.hCommandStatus = DPN_OK;
  1759. ConnectAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  1760. if ( ( ConnectAddressInfo.pDeviceAddress == NULL ) ||
  1761. ( ConnectAddressInfo.pHostAddress == NULL ) )
  1762. {
  1763. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial connect addressing!" );
  1764. hr = DPNERR_OUTOFMEMORY;
  1765. goto Failure;
  1766. }
  1767. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(), // interface
  1768. SPEV_CONNECTADDRESSINFO, // event type
  1769. &ConnectAddressInfo // pointer to data
  1770. );
  1771. DNASSERT( hTempResult == DPN_OK );
  1772. }
  1773. break;
  1774. }
  1775. case ENDPOINT_TYPE_ENUM:
  1776. {
  1777. SPIE_ENUMADDRESSINFO EnumAddressInfo;
  1778. HRESULT hTempResult;
  1779. if ( m_hEnumEndpoint != 0 )
  1780. {
  1781. hr = DPNERR_ALREADYINITIALIZED;
  1782. DPFX(DPFPREP, 0, "Attempted to bind enum endpoint when one already exists!" );
  1783. goto Failure;
  1784. }
  1785. m_hEnumEndpoint = pEndpoint->GetHandle();
  1786. //
  1787. // indicate addressing to a higher layer
  1788. //
  1789. pDeviceAddress = GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  1790. pHostAddress = pEndpoint->GetRemoteHostDP8Address();
  1791. memset( &EnumAddressInfo, 0x00, sizeof( EnumAddressInfo ) );
  1792. EnumAddressInfo.pDeviceAddress = pDeviceAddress;
  1793. EnumAddressInfo.pHostAddress = pHostAddress;
  1794. EnumAddressInfo.hCommandStatus = DPN_OK;
  1795. EnumAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  1796. if ( ( EnumAddressInfo.pDeviceAddress == NULL ) ||
  1797. ( EnumAddressInfo.pHostAddress == NULL ) )
  1798. {
  1799. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial enum addressing!" );
  1800. hr = DPNERR_OUTOFMEMORY;
  1801. goto Failure;
  1802. }
  1803. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(),
  1804. SPEV_ENUMADDRESSINFO,
  1805. &EnumAddressInfo
  1806. );
  1807. DNASSERT( hTempResult == DPN_OK );
  1808. break;
  1809. }
  1810. //
  1811. // shouldn't be here
  1812. //
  1813. default:
  1814. {
  1815. DNASSERT( FALSE );
  1816. break;
  1817. }
  1818. }
  1819. //
  1820. // an outgoing endpoint was bound, attempt the outgoing
  1821. // connection. If it fails make sure that the above binding is
  1822. // undone.
  1823. //
  1824. switch ( GetModemState() )
  1825. {
  1826. case MODEM_STATE_OUTGOING_CONNECTED:
  1827. case MODEM_STATE_INCOMING_CONNECTED:
  1828. {
  1829. break;
  1830. }
  1831. case MODEM_STATE_INITIALIZED:
  1832. {
  1833. DNASSERT( GetCallHandle() == NULL );
  1834. memset( &LineCallParams, 0x00, sizeof( LineCallParams ) );
  1835. LineCallParams.dwTotalSize = sizeof( LineCallParams );
  1836. LineCallParams.dwBearerMode = LINEBEARERMODE_VOICE;
  1837. LineCallParams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
  1838. DNASSERT( GetActiveLineCommand() == INVALID_TAPI_COMMAND );
  1839. DPFX(DPFPREP, 5, "lineMakeCall" );
  1840. lTapiReturn = p_lineMakeCall( GetLineHandle(), // line handle
  1841. &m_hCall, // pointer to call destination
  1842. pModemEndpoint->GetPhoneNumber(), // destination address (phone number)
  1843. 0, // country code (default)
  1844. &LineCallParams // pointer to call params
  1845. );
  1846. if ( lTapiReturn > 0 )
  1847. {
  1848. DPFX(DPFPREP, 5, "TAPI making call (handle=0x%x), command ID: %d", GetCallHandle(), lTapiReturn );
  1849. SetModemState( MODEM_STATE_WAITING_FOR_OUTGOING_CONNECT );
  1850. SetActiveLineCommand( lTapiReturn );
  1851. }
  1852. else
  1853. {
  1854. DPFX(DPFPREP, 0, "Problem with lineMakeCall" );
  1855. DisplayTAPIError( 0, lTapiReturn );
  1856. hr = DPNERR_NOCONNECTION;
  1857. switch ( EndpointType )
  1858. {
  1859. case ENDPOINT_TYPE_CONNECT:
  1860. case ENDPOINT_TYPE_CONNECT_ON_LISTEN:
  1861. {
  1862. DNASSERT( m_hConnectEndpoint != 0 );
  1863. m_hConnectEndpoint = 0;
  1864. break;
  1865. }
  1866. case ENDPOINT_TYPE_ENUM:
  1867. {
  1868. DNASSERT( m_hEnumEndpoint != 0 );
  1869. m_hEnumEndpoint = 0;
  1870. break;
  1871. }
  1872. default:
  1873. {
  1874. DNASSERT( FALSE );
  1875. break;
  1876. }
  1877. }
  1878. goto Failure;
  1879. }
  1880. break;
  1881. }
  1882. default:
  1883. {
  1884. DNASSERT( FALSE );
  1885. break;
  1886. }
  1887. }
  1888. break;
  1889. }
  1890. case ENDPOINT_TYPE_LISTEN:
  1891. {
  1892. SPIE_LISTENADDRESSINFO ListenAddressInfo;
  1893. HRESULT hTempResult;
  1894. if ( ( GetModemState() == MODEM_STATE_CLOSING_INCOMING_CONNECTION ) ||
  1895. ( m_hListenEndpoint != 0 ) )
  1896. {
  1897. hr = DPNERR_ALREADYINITIALIZED;
  1898. DPFX(DPFPREP, 0, "Attempted to bind listen endpoint when one already exists!" );
  1899. goto Failure;
  1900. }
  1901. m_hListenEndpoint = pEndpoint->GetHandle();
  1902. //
  1903. // set addressing information
  1904. //
  1905. pDeviceAddress = GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  1906. DNASSERT( pHostAddress == NULL );
  1907. memset( &ListenAddressInfo, 0x00, sizeof( ListenAddressInfo ) );
  1908. ListenAddressInfo.pDeviceAddress = pDeviceAddress;
  1909. ListenAddressInfo.hCommandStatus = DPN_OK;
  1910. ListenAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  1911. if ( ListenAddressInfo.pDeviceAddress == NULL )
  1912. {
  1913. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial listen addressing!" );
  1914. hr = DPNERR_OUTOFMEMORY;
  1915. goto Failure;
  1916. }
  1917. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(), // interface
  1918. SPEV_LISTENADDRESSINFO, // event type
  1919. &ListenAddressInfo // pointer to data
  1920. );
  1921. DNASSERT( hTempResult == DPN_OK );
  1922. break;
  1923. }
  1924. //
  1925. // invalid case, we should never be here
  1926. //
  1927. default:
  1928. {
  1929. DNASSERT( FALSE );
  1930. break;
  1931. }
  1932. }
  1933. //
  1934. // add these references before the lock is released to prevent them from
  1935. // being immediately cleaned
  1936. //
  1937. pEndpoint->SetDataPort( this );
  1938. pEndpoint->AddRef();
  1939. if ( ( GetModemState() == MODEM_STATE_OUTGOING_CONNECTED ) &&
  1940. ( ( EndpointType == ENDPOINT_TYPE_CONNECT ) ||
  1941. ( EndpointType == ENDPOINT_TYPE_ENUM ) ) )
  1942. {
  1943. pEndpoint->OutgoingConnectionEstablished( DPN_OK );
  1944. }
  1945. }
  1946. else
  1947. {
  1948. //
  1949. // we're only allowed one endpoint of any given type so determine which
  1950. // type end then bind the endpoint
  1951. //
  1952. switch ( EndpointType )
  1953. {
  1954. case ENDPOINT_TYPE_CONNECT:
  1955. case ENDPOINT_TYPE_CONNECT_ON_LISTEN:
  1956. {
  1957. if ( m_hConnectEndpoint != 0 )
  1958. {
  1959. hr = DPNERR_ALREADYINITIALIZED;
  1960. DPFX(DPFPREP, 0, "Attempted to bind connect endpoint when one already exists!" );
  1961. goto Failure;
  1962. }
  1963. m_hConnectEndpoint = pEndpoint->GetHandle();
  1964. if ( EndpointType == ENDPOINT_TYPE_CONNECT )
  1965. {
  1966. SPIE_CONNECTADDRESSINFO ConnectAddressInfo;
  1967. HRESULT hTempResult;
  1968. //
  1969. // set addresses in addressing information
  1970. //
  1971. pDeviceAddress = ComPortData()->DP8AddressFromComPortData( ADDRESS_TYPE_LOCAL_ADAPTER );
  1972. pHostAddress = ComPortData()->DP8AddressFromComPortData( ADDRESS_TYPE_REMOTE_HOST );
  1973. memset( &ConnectAddressInfo, 0x00, sizeof( ConnectAddressInfo ) );
  1974. ConnectAddressInfo.pDeviceAddress = pDeviceAddress;
  1975. ConnectAddressInfo.pHostAddress = pHostAddress;
  1976. ConnectAddressInfo.hCommandStatus = DPN_OK;
  1977. ConnectAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  1978. if ( ( ConnectAddressInfo.pDeviceAddress == NULL ) ||
  1979. ( ConnectAddressInfo.pHostAddress == NULL ) )
  1980. {
  1981. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial connect addressing!" );
  1982. hr = DPNERR_OUTOFMEMORY;
  1983. goto Failure;
  1984. }
  1985. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(), // interface
  1986. SPEV_CONNECTADDRESSINFO, // event type
  1987. &ConnectAddressInfo // pointer to data
  1988. );
  1989. DNASSERT( hTempResult == DPN_OK );
  1990. }
  1991. break;
  1992. }
  1993. case ENDPOINT_TYPE_LISTEN:
  1994. {
  1995. SPIE_LISTENADDRESSINFO ListenAddressInfo;
  1996. HRESULT hTempResult;
  1997. if ( m_hListenEndpoint != 0 )
  1998. {
  1999. hr = DPNERR_ALREADYINITIALIZED;
  2000. DPFX(DPFPREP, 0, "Attempted to bind listen endpoint when one already exists!" );
  2001. goto Failure;
  2002. }
  2003. m_hListenEndpoint = pEndpoint->GetHandle();
  2004. //
  2005. // set addressing information
  2006. //
  2007. pDeviceAddress = ComPortData()->DP8AddressFromComPortData( ADDRESS_TYPE_LOCAL_ADAPTER );
  2008. DNASSERT( pHostAddress == NULL );
  2009. memset( &ListenAddressInfo, 0x00, sizeof( ListenAddressInfo ) );
  2010. ListenAddressInfo.pDeviceAddress = pDeviceAddress;
  2011. ListenAddressInfo.hCommandStatus = DPN_OK;
  2012. ListenAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  2013. if ( ListenAddressInfo.pDeviceAddress == NULL )
  2014. {
  2015. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial listen addressing!" );
  2016. hr = DPNERR_OUTOFMEMORY;
  2017. goto Failure;
  2018. }
  2019. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(), // interface
  2020. SPEV_LISTENADDRESSINFO, // event type
  2021. &ListenAddressInfo // pointer to data
  2022. );
  2023. DNASSERT( hTempResult == DPN_OK );
  2024. break;
  2025. }
  2026. case ENDPOINT_TYPE_ENUM:
  2027. {
  2028. SPIE_ENUMADDRESSINFO EnumAddressInfo;
  2029. HRESULT hTempResult;
  2030. if ( m_hEnumEndpoint != 0 )
  2031. {
  2032. hr = DPNERR_ALREADYINITIALIZED;
  2033. DPFX(DPFPREP, 0, "Attempted to bind enum endpoint when one already exists!" );
  2034. goto Exit;
  2035. }
  2036. m_hEnumEndpoint = pEndpoint->GetHandle();
  2037. //
  2038. // indicate addressing to a higher layer
  2039. //
  2040. pDeviceAddress = ComPortData()->DP8AddressFromComPortData( ADDRESS_TYPE_LOCAL_ADAPTER );
  2041. pHostAddress = ComPortData()->DP8AddressFromComPortData( ADDRESS_TYPE_REMOTE_HOST );
  2042. memset( &EnumAddressInfo, 0x00, sizeof( EnumAddressInfo ) );
  2043. EnumAddressInfo.pDeviceAddress = pDeviceAddress;
  2044. EnumAddressInfo.pHostAddress = pHostAddress;
  2045. EnumAddressInfo.hCommandStatus = DPN_OK;
  2046. EnumAddressInfo.pCommandContext = pEndpoint->GetCommandData()->GetUserContext();
  2047. if ( ( EnumAddressInfo.pDeviceAddress == NULL ) ||
  2048. ( EnumAddressInfo.pHostAddress == NULL ) )
  2049. {
  2050. DPFX(DPFPREP, 0, "Failed to build addresses to indicate serial enum addressing!" );
  2051. hr = DPNERR_OUTOFMEMORY;
  2052. goto Failure;
  2053. }
  2054. hTempResult = IDP8SPCallback_IndicateEvent( GetSPData()->DP8SPCallbackInterface(),
  2055. SPEV_ENUMADDRESSINFO,
  2056. &EnumAddressInfo
  2057. );
  2058. DNASSERT( hTempResult == DPN_OK );
  2059. break;
  2060. }
  2061. //
  2062. // invalid case, we should never be here
  2063. //
  2064. default:
  2065. {
  2066. DNASSERT( FALSE );
  2067. break;
  2068. }
  2069. }
  2070. //
  2071. // add these references before the lock is released to prevent them from
  2072. // being immediately cleaned
  2073. //
  2074. pEndpoint->SetDataPort( this );
  2075. pEndpoint->AddRef();
  2076. //
  2077. // if this was a connect or enum, indicate that the outgoing connection is
  2078. // ready.
  2079. //
  2080. if ( ( EndpointType == ENDPOINT_TYPE_CONNECT ) ||
  2081. ( EndpointType == ENDPOINT_TYPE_ENUM ) )
  2082. {
  2083. pEndpoint->OutgoingConnectionEstablished( DPN_OK );
  2084. }
  2085. }
  2086. Unlock();
  2087. Exit:
  2088. if ( pHostAddress != NULL )
  2089. {
  2090. IDirectPlay8Address_Release( pHostAddress );
  2091. pHostAddress = NULL;
  2092. }
  2093. if ( pDeviceAddress != NULL )
  2094. {
  2095. IDirectPlay8Address_Release( pDeviceAddress );
  2096. pDeviceAddress = NULL;
  2097. }
  2098. DPFX(DPFPREP, 6, "(0x%p) Returning [0x%lx]", this, hr);
  2099. return hr;
  2100. Failure:
  2101. Unlock();
  2102. goto Exit;
  2103. }
  2104. //**********************************************************************
  2105. //**********************************************************************
  2106. // ------------------------------
  2107. // CDataPort::UnbindEndpoint - unbind endpoint from this data port
  2108. //
  2109. // Entry: Pointer to endpoint
  2110. // Endpoint type
  2111. //
  2112. // Exit: Nothing
  2113. // ------------------------------
  2114. #undef DPF_MODNAME
  2115. #define DPF_MODNAME "CDataPort::UnbindEndpoint"
  2116. void CDataPort::UnbindEndpoint( CModemEndpoint *const pEndpoint, const ENDPOINT_TYPE EndpointType )
  2117. {
  2118. DNASSERT( pEndpoint != NULL );
  2119. Lock();
  2120. DNASSERT( pEndpoint->GetDataPort() == this );
  2121. switch ( EndpointType )
  2122. {
  2123. case ENDPOINT_TYPE_CONNECT_ON_LISTEN:
  2124. case ENDPOINT_TYPE_CONNECT:
  2125. {
  2126. DNASSERT( m_hConnectEndpoint != 0 );
  2127. m_hConnectEndpoint = 0;
  2128. break;
  2129. }
  2130. case ENDPOINT_TYPE_LISTEN:
  2131. {
  2132. DNASSERT( m_hListenEndpoint != 0 );
  2133. m_hListenEndpoint = 0;
  2134. break;
  2135. }
  2136. case ENDPOINT_TYPE_ENUM:
  2137. {
  2138. DNASSERT( m_hEnumEndpoint != 0 );
  2139. m_hEnumEndpoint = 0;
  2140. break;
  2141. }
  2142. default:
  2143. {
  2144. DNASSERT( FALSE );
  2145. break;
  2146. }
  2147. }
  2148. Unlock();
  2149. pEndpoint->SetDataPort( NULL );
  2150. pEndpoint->DecRef();
  2151. }
  2152. //**********************************************************************
  2153. //**********************************************************************
  2154. // ------------------------------
  2155. // CDataPort::BindComPort - bind com port to network
  2156. //
  2157. // Entry: Nothing
  2158. //
  2159. // Exit: Error code
  2160. // ------------------------------
  2161. #undef DPF_MODNAME
  2162. #define DPF_MODNAME "CDataPort::BindComPort"
  2163. HRESULT CDataPort::BindComPort( void )
  2164. {
  2165. HRESULT hr;
  2166. VARSTRING *pTempInfo;
  2167. LONG lTapiError;
  2168. DWORD dwSizeNeeded;
  2169. //
  2170. // In the case of host migration, there is an outstanding read pending that
  2171. // needs to be cleaned up. Unfortunately, there is no mechanism in Win32
  2172. // to cancel just this little I/O operation. Release the read ref count on
  2173. // this CDataPort and reissue the read.....
  2174. //
  2175. if ( GetActiveRead() != NULL )
  2176. {
  2177. #ifdef WIN95
  2178. GetActiveRead()->SetWin9xOperationPending( FALSE );
  2179. #endif // WIN95
  2180. DecRef();
  2181. }
  2182. //
  2183. // initialize
  2184. //
  2185. hr = DPN_OK;
  2186. pTempInfo = NULL;
  2187. //
  2188. // get file handle for modem device
  2189. //
  2190. pTempInfo = static_cast<VARSTRING*>( DNMalloc( sizeof( *pTempInfo ) ) );
  2191. if ( pTempInfo == NULL )
  2192. {
  2193. hr = DPNERR_OUTOFMEMORY;
  2194. DPFX(DPFPREP, 0, "Out of memory allocating for lineGetID!" );
  2195. goto Failure;
  2196. }
  2197. pTempInfo->dwTotalSize = sizeof( *pTempInfo );
  2198. pTempInfo->dwNeededSize = pTempInfo->dwTotalSize;
  2199. pTempInfo->dwStringFormat = STRINGFORMAT_BINARY;
  2200. lTapiError = LINEERR_STRUCTURETOOSMALL;
  2201. while ( lTapiError == LINEERR_STRUCTURETOOSMALL )
  2202. {
  2203. DNASSERT( pTempInfo != NULL );
  2204. dwSizeNeeded = pTempInfo->dwNeededSize;
  2205. DNFree( pTempInfo );
  2206. pTempInfo = static_cast<VARSTRING*>( DNMalloc( dwSizeNeeded ) );
  2207. if ( pTempInfo == NULL )
  2208. {
  2209. hr = DPNERR_OUTOFMEMORY;
  2210. DPFX(DPFPREP, 0, "Out of memory reallocating for lineGetID!" );
  2211. goto Failure;
  2212. }
  2213. pTempInfo->dwTotalSize = dwSizeNeeded;
  2214. DPFX(DPFPREP, 5, "lineGetID (call handle=0x%x)", GetCallHandle() );
  2215. lTapiError = p_lineGetID( NULL, // line handle
  2216. 0, // address ID
  2217. m_hCall, // call handle
  2218. LINECALLSELECT_CALL, // use call handle
  2219. pTempInfo, // pointer to variable information
  2220. TEXT("comm/datamodem") // request comm/modem ID information
  2221. );
  2222. if ( ( lTapiError == LINEERR_NONE ) &&
  2223. ( pTempInfo->dwTotalSize < pTempInfo->dwNeededSize ) )
  2224. {
  2225. lTapiError = LINEERR_STRUCTURETOOSMALL;
  2226. }
  2227. }
  2228. if ( lTapiError != LINEERR_NONE )
  2229. {
  2230. hr = DPNERR_GENERIC;
  2231. DPFX(DPFPREP, 0, "Problem with lineGetID" );
  2232. DisplayTAPIError( 0, lTapiError );
  2233. goto Failure;
  2234. }
  2235. DNASSERT( pTempInfo->dwStringSize != 0 );
  2236. DNASSERT( pTempInfo->dwStringFormat == STRINGFORMAT_BINARY );
  2237. m_hFile = MAKE_DNHANDLE(*( (HANDLE*) ( ( (BYTE*) pTempInfo ) + pTempInfo->dwStringOffset ) ));
  2238. if ( m_hFile == NULL )
  2239. {
  2240. hr = DPNERR_GENERIC;
  2241. DPFX(DPFPREP, 0, "problem getting Com file handle!" );
  2242. DNASSERT( FALSE );
  2243. goto Failure;
  2244. }
  2245. hr = SetPortCommunicationParameters();
  2246. if ( hr != DPN_OK )
  2247. {
  2248. DPFX(DPFPREP, 0, "Failed to set communication parameters!" );
  2249. DisplayDNError( 0, hr );
  2250. goto Failure;
  2251. }
  2252. //
  2253. // bind to completion port for NT
  2254. //
  2255. #ifdef WINNT
  2256. HANDLE hCompletionPort;
  2257. hCompletionPort = CreateIoCompletionPort( HANDLE_FROM_DNHANDLE(m_hFile), // current file handle
  2258. GetSPData()->GetThreadPool()->GetIOCompletionPort(), // handle of completion port
  2259. IO_COMPLETION_KEY_IO_COMPLETE, // completion key
  2260. 0 // number of concurrent threads (default to number of processors)
  2261. );
  2262. if ( hCompletionPort == NULL )
  2263. {
  2264. hr = DPNERR_OUTOFMEMORY;
  2265. DPFX(DPFPREP, 0, "Cannot bind comport to completion port!" );
  2266. DisplayErrorCode( 0, GetLastError() );
  2267. goto Failure;
  2268. }
  2269. #endif // WINNT
  2270. hr = StartReceiving();
  2271. if ( hr != DPN_OK )
  2272. {
  2273. DPFX(DPFPREP, 0, "Failed to start receiving!" );
  2274. DisplayDNError( 0, hr );
  2275. goto Failure;
  2276. }
  2277. Exit:
  2278. if ( pTempInfo != NULL )
  2279. {
  2280. DNFree( pTempInfo );
  2281. pTempInfo = NULL;
  2282. }
  2283. return hr;
  2284. Failure:
  2285. goto Exit;
  2286. }
  2287. //**********************************************************************
  2288. //**********************************************************************
  2289. // ------------------------------
  2290. // CDataPort::ProcessTAPIMessage - process a TAPI message
  2291. //
  2292. // Entry: Pointer to message information
  2293. //
  2294. // Exit: Nothing
  2295. // ------------------------------
  2296. #undef DPF_MODNAME
  2297. #define DPF_MODNAME "CDataPort::ProcessTAPIMessage"
  2298. void CDataPort::ProcessTAPIMessage( const LINEMESSAGE *const pLineMessage )
  2299. {
  2300. DPFX(DPFPREP, 1, "(0x%p) Processing TAPI message %u:", this, pLineMessage->dwMessageID );
  2301. DisplayTAPIMessage( 1, pLineMessage );
  2302. Lock();
  2303. switch ( pLineMessage->dwMessageID )
  2304. {
  2305. //
  2306. // call information about the specified call has changed
  2307. //
  2308. case LINE_CALLINFO:
  2309. {
  2310. DPFX(DPFPREP, 3, "Call info type 0x%lx changed, ignoring.",
  2311. pLineMessage->dwParam1);
  2312. break;
  2313. }
  2314. //
  2315. // command reply
  2316. //
  2317. case LINE_REPLY:
  2318. {
  2319. DNASSERT( pLineMessage->hDevice == 0 );
  2320. SetActiveLineCommand( INVALID_TAPI_COMMAND );
  2321. //
  2322. // Can't ASSERT that there's a call handle because the command
  2323. // may have failed and been cleaned up from the NT completion
  2324. // port, just ASSERT our state. Can't ASSERT modem state because
  2325. // TAPI events may race off the completion port on NT. Can't ASSERT
  2326. // command because it may have already been cleaned.
  2327. //
  2328. break;
  2329. }
  2330. //
  2331. // new call, make sure we're listening for a call and that there's an
  2332. // active 'listen' before accepting.
  2333. //
  2334. case LINE_APPNEWCALL:
  2335. {
  2336. DNASSERT( GetCallHandle() == NULL );
  2337. DBG_CASSERT( sizeof( m_hLine ) == sizeof( pLineMessage->hDevice ) );
  2338. DNASSERT( GetLineHandle() == pLineMessage->hDevice );
  2339. DNASSERT( pLineMessage->dwParam3 == LINECALLPRIVILEGE_OWNER );
  2340. if ( m_hListenEndpoint != 0 )
  2341. {
  2342. LONG lTapiReturn;
  2343. DPFX(DPFPREP, 5, "lineAnswer (call handle=0x%x)", pLineMessage->dwParam2 );
  2344. lTapiReturn = p_lineAnswer( static_cast<HCALL>( pLineMessage->dwParam2 ), // call to be answered
  2345. NULL, // user information to be sent to remote party (none)
  2346. 0 // size of user data to send
  2347. );
  2348. if ( lTapiReturn > 0 )
  2349. {
  2350. DPFX(DPFPREP, 8, "Accepted call, id: %d", lTapiReturn );
  2351. SetCallHandle( static_cast<HCALL>( pLineMessage->dwParam2 ) );
  2352. SetModemState( MODEM_STATE_WAITING_FOR_INCOMING_CONNECT );
  2353. SetActiveLineCommand( lTapiReturn );
  2354. }
  2355. else
  2356. {
  2357. DPFX(DPFPREP, 0, "Failed to answer call!" );
  2358. DisplayTAPIError( 0, lTapiReturn );
  2359. }
  2360. }
  2361. break;
  2362. }
  2363. //
  2364. // call state
  2365. //
  2366. case LINE_CALLSTATE:
  2367. {
  2368. //
  2369. // if there's state information, make sure we own the call
  2370. //
  2371. DNASSERT( ( pLineMessage->dwParam3 == 0 ) ||
  2372. ( pLineMessage->dwParam3 == LINECALLPRIVILEGE_OWNER ) );
  2373. //
  2374. // validate input, but note that it's possible that TAPI messages got processed
  2375. // out of order so we might not have seen a call handle yet
  2376. //
  2377. DBG_CASSERT( sizeof( m_hCall ) == sizeof( pLineMessage->hDevice ) );
  2378. DNASSERT( ( m_hCall == pLineMessage->hDevice ) || ( m_hCall == NULL ) );
  2379. //
  2380. // what's the sub-state?
  2381. //
  2382. switch ( pLineMessage->dwParam1 )
  2383. {
  2384. //
  2385. // modem has connected
  2386. //
  2387. case LINECALLSTATE_CONNECTED:
  2388. {
  2389. DNASSERT( ( pLineMessage->dwParam2 == 0 ) ||
  2390. ( pLineMessage->dwParam2 == LINECONNECTEDMODE_ACTIVE ) );
  2391. DNASSERT( ( GetModemState() == MODEM_STATE_WAITING_FOR_INCOMING_CONNECT ) ||
  2392. ( GetModemState() == MODEM_STATE_WAITING_FOR_OUTGOING_CONNECT ) );
  2393. if ( GetModemState() == MODEM_STATE_WAITING_FOR_OUTGOING_CONNECT )
  2394. {
  2395. HRESULT hr;
  2396. hr = BindComPort();
  2397. if ( hr != DPN_OK )
  2398. {
  2399. DPFX(DPFPREP, 0, "Failed to bind modem communication port!" );
  2400. DisplayDNError( 0, hr );
  2401. DNASSERT( FALSE );
  2402. }
  2403. SetModemState( MODEM_STATE_OUTGOING_CONNECTED );
  2404. if ( m_hConnectEndpoint != 0 )
  2405. {
  2406. CModemEndpoint *pEndpoint;
  2407. pEndpoint = GetSPData()->EndpointFromHandle( m_hConnectEndpoint );
  2408. if ( pEndpoint != NULL )
  2409. {
  2410. pEndpoint->OutgoingConnectionEstablished( DPN_OK );
  2411. pEndpoint->DecCommandRef();
  2412. }
  2413. }
  2414. if ( m_hEnumEndpoint != 0 )
  2415. {
  2416. CModemEndpoint *pEndpoint;
  2417. pEndpoint = GetSPData()->EndpointFromHandle( m_hEnumEndpoint );
  2418. if ( pEndpoint != NULL )
  2419. {
  2420. pEndpoint->OutgoingConnectionEstablished( DPN_OK );
  2421. pEndpoint->DecCommandRef();
  2422. }
  2423. }
  2424. }
  2425. else
  2426. {
  2427. HRESULT hr;
  2428. hr = BindComPort();
  2429. if ( hr != DPN_OK )
  2430. {
  2431. DPFX(DPFPREP, 0, "Failed to bind modem communication port!" );
  2432. DisplayDNError( 0, hr );
  2433. DNASSERT( FALSE );
  2434. }
  2435. SetModemState( MODEM_STATE_INCOMING_CONNECTED );
  2436. }
  2437. break;
  2438. }
  2439. //
  2440. // modems disconnected
  2441. //
  2442. case LINECALLSTATE_DISCONNECTED:
  2443. {
  2444. LONG lTapiReturn;
  2445. switch( pLineMessage->dwParam2 )
  2446. {
  2447. case LINEDISCONNECTMODE_NORMAL:
  2448. case LINEDISCONNECTMODE_BUSY:
  2449. case LINEDISCONNECTMODE_NOANSWER:
  2450. case LINEDISCONNECTMODE_NODIALTONE:
  2451. case LINEDISCONNECTMODE_UNAVAIL:
  2452. {
  2453. break;
  2454. }
  2455. //
  2456. // stop and look
  2457. //
  2458. default:
  2459. {
  2460. DNASSERT( FALSE );
  2461. break;
  2462. }
  2463. }
  2464. CancelOutgoingConnections();
  2465. //
  2466. // reset modem port to initialized state and indicate that
  2467. // it is no longer receiving data
  2468. //
  2469. SetModemState( MODEM_STATE_INITIALIZED );
  2470. DPFX(DPFPREP, 5, "Closing file handle on DISCONNECT notification." );
  2471. if ( DNCloseHandle( GetFileHandle() ) == FALSE )
  2472. {
  2473. DWORD dwError;
  2474. dwError = GetLastError();
  2475. DPFX(DPFPREP, 0, "Problem closing file handle when restarting modem on host!" );
  2476. DisplayErrorCode( 0, dwError );
  2477. }
  2478. m_hFile = DNINVALID_HANDLE_VALUE;
  2479. SetActiveLineCommand( INVALID_TAPI_COMMAND );
  2480. //
  2481. // if there is an active listen, release this call so TAPI
  2482. // can indicate future incoming calls.
  2483. //
  2484. if ( m_hListenEndpoint != 0 )
  2485. {
  2486. SetState( DATA_PORT_STATE_INITIALIZED );
  2487. DPFX(DPFPREP, 5, "lineDeallocateCall listen (call handle=0x%x)", GetCallHandle() );
  2488. lTapiReturn = p_lineDeallocateCall( GetCallHandle() );
  2489. if ( lTapiReturn != LINEERR_NONE )
  2490. {
  2491. DPFX(DPFPREP, 0, "Failed to release call (listen)!" );
  2492. DisplayTAPIError( 0, lTapiReturn );
  2493. DNASSERT( FALSE );
  2494. }
  2495. SetCallHandle( NULL );
  2496. DNASSERT( GetFileHandle() == DNINVALID_HANDLE_VALUE );
  2497. }
  2498. else
  2499. {
  2500. //
  2501. // Deallocate the call if there is one..
  2502. //
  2503. if (GetCallHandle() != NULL)
  2504. {
  2505. DNASSERT(( m_hEnumEndpoint != 0 ) || ( m_hConnectEndpoint != 0 ));
  2506. DPFX(DPFPREP, 5, "lineDeallocateCall non-listen (call handle=0x%x)", GetCallHandle() );
  2507. lTapiReturn = p_lineDeallocateCall( GetCallHandle() );
  2508. if ( lTapiReturn != LINEERR_NONE )
  2509. {
  2510. DPFX(DPFPREP, 0, "Failed to release call (non-listen)!" );
  2511. DisplayTAPIError( 0, lTapiReturn );
  2512. DNASSERT( FALSE );
  2513. }
  2514. SetCallHandle( NULL );
  2515. }
  2516. else
  2517. {
  2518. DPFX(DPFPREP, 5, "No call handle." );
  2519. DNASSERT( m_hEnumEndpoint == 0 );
  2520. DNASSERT( m_hConnectEndpoint == 0 );
  2521. }
  2522. SetModemState( MODEM_STATE_UNKNOWN );
  2523. }
  2524. break;
  2525. }
  2526. //
  2527. // call is officially ours. Can't ASSERT any state here because
  2528. // messages might have been reversed by the NT completion threads
  2529. // so LINE_APPNEWCALL may not yet have been processed. It's also
  2530. // possible that we're in disconnect cleanup as someone is calling
  2531. // and LINECALLSTATE_OFFERING is coming in before LINE_APPNEWCALL.
  2532. //
  2533. case LINECALLSTATE_OFFERING:
  2534. {
  2535. break;
  2536. }
  2537. //
  2538. // call has been accepted, waiting for modems to connect
  2539. //
  2540. case LINECALLSTATE_ACCEPTED:
  2541. {
  2542. DNASSERT( GetModemState() == MODEM_STATE_WAITING_FOR_INCOMING_CONNECT );
  2543. break;
  2544. }
  2545. //
  2546. // we're dialing
  2547. //
  2548. case LINECALLSTATE_DIALING:
  2549. case LINECALLSTATE_DIALTONE:
  2550. {
  2551. DNASSERT( GetModemState() == MODEM_STATE_WAITING_FOR_OUTGOING_CONNECT );
  2552. break;
  2553. }
  2554. //
  2555. // we're done dialing, waiting for modems to connect
  2556. //
  2557. case LINECALLSTATE_PROCEEDING:
  2558. {
  2559. DNASSERT( GetModemState() == MODEM_STATE_WAITING_FOR_OUTGOING_CONNECT );
  2560. break;
  2561. }
  2562. //
  2563. // line is idle, most likely from a modem hanging up during negotiation
  2564. //
  2565. case LINECALLSTATE_IDLE:
  2566. {
  2567. break;
  2568. }
  2569. //
  2570. // other state, stop and look
  2571. //
  2572. default:
  2573. {
  2574. DNASSERT( FALSE );
  2575. break;
  2576. }
  2577. }
  2578. break;
  2579. }
  2580. //
  2581. // TAPI line was closed
  2582. //
  2583. case LINE_CLOSE:
  2584. {
  2585. CancelOutgoingConnections();
  2586. break;
  2587. }
  2588. //
  2589. // unhandled message
  2590. //
  2591. default:
  2592. {
  2593. DNASSERT( FALSE );
  2594. break;
  2595. }
  2596. }
  2597. Unlock();
  2598. return;
  2599. }
  2600. //**********************************************************************
  2601. //**********************************************************************
  2602. // ------------------------------
  2603. // CDataPort::CancelOutgoingConnections - cancel any outgoing connection attempts
  2604. //
  2605. // Entry: Nothing
  2606. //
  2607. // Exit: Nothing
  2608. // ------------------------------
  2609. #undef DPF_MODNAME
  2610. #define DPF_MODNAME "CDataPort::CancelOutgoingConnections"
  2611. void CDataPort::CancelOutgoingConnections( void )
  2612. {
  2613. DPFX(DPFPREP, 6, "(0x%p) Enter", this );
  2614. //
  2615. // if there is an outstanding enum, stop it
  2616. //
  2617. if ( m_hEnumEndpoint != 0 )
  2618. {
  2619. CModemEndpoint *pEndpoint;
  2620. pEndpoint = GetSPData()->EndpointFromHandle( m_hEnumEndpoint );
  2621. if ( pEndpoint != NULL )
  2622. {
  2623. CModemCommandData *pCommandData;
  2624. pCommandData = pEndpoint->GetCommandData();
  2625. pCommandData->Lock();
  2626. if ( pCommandData->GetState() != COMMAND_STATE_INPROGRESS )
  2627. {
  2628. DNASSERT( pCommandData->GetState() == COMMAND_STATE_CANCELLING );
  2629. pCommandData->Unlock();
  2630. }
  2631. else
  2632. {
  2633. pCommandData->SetState( COMMAND_STATE_CANCELLING );
  2634. pCommandData->Unlock();
  2635. pEndpoint->Lock();
  2636. pEndpoint->SetState( ENDPOINT_STATE_DISCONNECTING );
  2637. pEndpoint->Unlock();
  2638. pEndpoint->StopEnumCommand( DPNERR_NOCONNECTION );
  2639. }
  2640. pEndpoint->DecCommandRef();
  2641. }
  2642. }
  2643. //
  2644. // if there is an outstanding connect, disconnect it
  2645. //
  2646. if ( m_hConnectEndpoint != 0 )
  2647. {
  2648. CModemEndpoint *pEndpoint;
  2649. DPNHANDLE hOldHandleValue;
  2650. hOldHandleValue = m_hConnectEndpoint;
  2651. pEndpoint = GetSPData()->GetEndpointAndCloseHandle( hOldHandleValue );
  2652. if ( pEndpoint != NULL )
  2653. {
  2654. HRESULT hTempResult;
  2655. hTempResult = pEndpoint->Disconnect( hOldHandleValue );
  2656. pEndpoint->DecRef();
  2657. }
  2658. }
  2659. DPFX(DPFPREP, 6, "(0x%p) Leave", this );
  2660. }
  2661. //**********************************************************************
  2662. //**********************************************************************
  2663. // ------------------------------
  2664. // CDataPort::PoolAllocFunction - called when new pool item is allocated
  2665. //
  2666. // Entry: Pointer to context
  2667. //
  2668. // Exit: Boolean inidcating success
  2669. // TRUE = success
  2670. // FALSE = failure
  2671. // ------------------------------
  2672. #undef DPF_MODNAME
  2673. #define DPF_MODNAME "CDataPort::PoolAllocFunction"
  2674. BOOL CDataPort::PoolAllocFunction( void* pvItem, void* pvContext )
  2675. {
  2676. CDataPort* pDataPort = (CDataPort*)pvItem;
  2677. DATA_PORT_POOL_CONTEXT* pDataPortContext = (DATA_PORT_POOL_CONTEXT*)pvContext;
  2678. DNASSERT( pDataPortContext != NULL );
  2679. pDataPort->m_fModem = (pDataPortContext->pSPData->GetType() == TYPE_MODEM);
  2680. pDataPort->m_ModemState = MODEM_STATE_UNKNOWN;
  2681. pDataPort->m_dwDeviceID = INVALID_DEVICE_ID;
  2682. pDataPort->m_dwNegotiatedAPIVersion = 0;
  2683. pDataPort->m_hLine = NULL;
  2684. pDataPort->m_hCall = NULL;
  2685. pDataPort->m_lActiveLineCommand = INVALID_TAPI_COMMAND;
  2686. // Initialize Base Class members
  2687. pDataPort->m_EndpointRefCount = 0;
  2688. pDataPort->m_State = DATA_PORT_STATE_UNKNOWN;
  2689. pDataPort->m_Handle = 0;
  2690. pDataPort->m_pSPData = NULL;
  2691. pDataPort->m_pActiveRead = NULL;
  2692. pDataPort->m_LinkDirection = LINK_DIRECTION_UNKNOWN;
  2693. pDataPort->m_hFile = DNINVALID_HANDLE_VALUE;
  2694. pDataPort->m_hListenEndpoint = 0;
  2695. pDataPort->m_hConnectEndpoint = 0;
  2696. pDataPort->m_hEnumEndpoint = 0;
  2697. pDataPort->m_iRefCount = 0;
  2698. pDataPort->m_ActiveListLinkage.Initialize();
  2699. DEBUG_ONLY( pDataPort->m_fInitialized = FALSE );
  2700. //
  2701. // Attempt to create critical section, recursion count needs to be non-zero
  2702. // to handle endpoint cleanup when a modem operation fails.
  2703. //
  2704. if ( DNInitializeCriticalSection( &pDataPort->m_Lock ) == FALSE )
  2705. {
  2706. DPFX(DPFPREP, 0, "Failed to initialized critical section on DataPort!" );
  2707. return FALSE;
  2708. }
  2709. DebugSetCriticalSectionRecursionCount( &pDataPort->m_Lock, 1 );
  2710. DebugSetCriticalSectionGroup( &pDataPort->m_Lock, &g_blDPNModemCritSecsHeld ); // separate dpnmodem CSes from the rest of DPlay's CSes
  2711. return TRUE;
  2712. }
  2713. //**********************************************************************
  2714. //**********************************************************************
  2715. // ------------------------------
  2716. // CDataPort::PoolInitFunction - called when new pool item is removed from pool
  2717. //
  2718. // Entry: Pointer to context
  2719. //
  2720. // Exit: Boolean inidcating success
  2721. // TRUE = success
  2722. // FALSE = failure
  2723. // ------------------------------
  2724. #undef DPF_MODNAME
  2725. #define DPF_MODNAME "CDataPort::PoolInitFunction"
  2726. void CDataPort::PoolInitFunction( void* pvItem, void* pvContext )
  2727. {
  2728. CDataPort* pDataPort = (CDataPort*)pvItem;
  2729. DATA_PORT_POOL_CONTEXT* pDataPortContext = (DATA_PORT_POOL_CONTEXT*)pvContext;
  2730. #ifdef DBG
  2731. DNASSERT( pDataPortContext != NULL );
  2732. DNASSERT( pDataPort->GetActiveRead() == NULL );
  2733. DNASSERT( pDataPort->GetHandle() == 0 );
  2734. DNASSERT( pDataPortContext->pSPData != NULL );
  2735. DNASSERT( pDataPort->m_fInitialized == FALSE );
  2736. DNASSERT( pDataPort->m_pSPData == NULL );
  2737. #endif // DBG
  2738. pDataPort->m_pSPData = pDataPortContext->pSPData;
  2739. DNASSERT( pDataPort->m_ActiveListLinkage.IsEmpty() );
  2740. DNASSERT( pDataPort->m_hListenEndpoint == 0 );
  2741. DNASSERT( pDataPort->m_hConnectEndpoint == 0 );
  2742. DNASSERT( pDataPort->m_hEnumEndpoint == 0 );
  2743. pDataPort->SetState( DATA_PORT_STATE_INITIALIZED );
  2744. DEBUG_ONLY( pDataPort->m_fInitialized = TRUE );
  2745. DNASSERT(pDataPort->m_iRefCount == 0);
  2746. pDataPort->m_iRefCount = 1;
  2747. }
  2748. //**********************************************************************
  2749. //**********************************************************************
  2750. // ------------------------------
  2751. // CDataPort::PoolReleaseFunction - called when new pool item is returned to pool
  2752. //
  2753. // Entry: Nothing
  2754. //
  2755. // Exit: Nothing
  2756. // ------------------------------
  2757. #undef DPF_MODNAME
  2758. #define DPF_MODNAME "CDataPort::PoolReleaseFunction"
  2759. void CDataPort::PoolReleaseFunction( void* pvItem )
  2760. {
  2761. CDataPort* pDataPort = (CDataPort*)pvItem;
  2762. pDataPort->m_pSPData = NULL;
  2763. DNASSERT( pDataPort->m_ActiveListLinkage.IsEmpty() );
  2764. DNASSERT( pDataPort->m_hFile == DNINVALID_HANDLE_VALUE );
  2765. DNASSERT( pDataPort->m_hListenEndpoint == 0 );
  2766. DNASSERT( pDataPort->m_hConnectEndpoint == 0 );
  2767. DNASSERT( pDataPort->m_hEnumEndpoint == 0 );
  2768. pDataPort->SetState( DATA_PORT_STATE_UNKNOWN );
  2769. DEBUG_ONLY( pDataPort->m_fInitialized = FALSE );
  2770. pDataPort->m_ComPortData.Reset();
  2771. DNASSERT( pDataPort->GetActiveRead() == NULL );
  2772. DNASSERT( pDataPort->GetHandle() == 0 );
  2773. DNASSERT( pDataPort->GetModemState() == MODEM_STATE_UNKNOWN );
  2774. DNASSERT( pDataPort->GetDeviceID() == INVALID_DEVICE_ID );
  2775. DNASSERT( pDataPort->GetNegotiatedAPIVersion() == 0 );
  2776. DNASSERT( pDataPort->GetLineHandle() == NULL );
  2777. DNASSERT( pDataPort->GetCallHandle() == NULL );
  2778. DNASSERT( pDataPort->GetActiveLineCommand() == INVALID_TAPI_COMMAND );
  2779. DNASSERT( pDataPort->m_EndpointRefCount == 0 );
  2780. DNASSERT( pDataPort->GetState() == DATA_PORT_STATE_UNKNOWN );
  2781. DNASSERT( pDataPort->GetSPData() == NULL );
  2782. DNASSERT( pDataPort->m_ActiveListLinkage.IsEmpty() != FALSE );
  2783. DNASSERT( pDataPort->m_LinkDirection == LINK_DIRECTION_UNKNOWN );
  2784. DNASSERT( pDataPort->m_hFile == DNINVALID_HANDLE_VALUE );
  2785. DNASSERT( pDataPort->m_hListenEndpoint == 0 );
  2786. DNASSERT( pDataPort->m_hConnectEndpoint == 0 );
  2787. DNASSERT( pDataPort->m_hEnumEndpoint == 0 );
  2788. DNASSERT( pDataPort->m_iRefCount == 0 );
  2789. }
  2790. //**********************************************************************
  2791. //**********************************************************************
  2792. // ------------------------------
  2793. // CDataPort::PoolDeallocFunction - called when new pool item is deallocated
  2794. //
  2795. // Entry: Nothing
  2796. //
  2797. // Exit: Nothing
  2798. // ------------------------------
  2799. #undef DPF_MODNAME
  2800. #define DPF_MODNAME "CDataPort::PoolDeallocFunction"
  2801. void CDataPort::PoolDeallocFunction( void* pvItem )
  2802. {
  2803. CDataPort* pDataPort = (CDataPort*)pvItem;
  2804. DNDeleteCriticalSection( &pDataPort->m_Lock );
  2805. DNASSERT( pDataPort->GetModemState() == MODEM_STATE_UNKNOWN );
  2806. DNASSERT( pDataPort->GetDeviceID() == INVALID_DEVICE_ID );
  2807. DNASSERT( pDataPort->GetNegotiatedAPIVersion() == 0 );
  2808. DNASSERT( pDataPort->GetLineHandle() == NULL );
  2809. DNASSERT( pDataPort->GetCallHandle() == NULL );
  2810. DNASSERT( pDataPort->GetActiveLineCommand() == INVALID_TAPI_COMMAND );
  2811. // Deinit Base Class members
  2812. DEBUG_ONLY( DNASSERT( pDataPort->m_fInitialized == FALSE ) );
  2813. DNASSERT( pDataPort->m_EndpointRefCount == 0 );
  2814. DNASSERT( pDataPort->GetState() == DATA_PORT_STATE_UNKNOWN );
  2815. DNASSERT( pDataPort->GetHandle() == 0 );
  2816. DNASSERT( pDataPort->GetSPData() == NULL );
  2817. DNASSERT( pDataPort->m_pActiveRead == NULL );
  2818. DNASSERT( pDataPort->m_ActiveListLinkage.IsEmpty() != FALSE );
  2819. DNASSERT( pDataPort->m_LinkDirection == LINK_DIRECTION_UNKNOWN );
  2820. DNASSERT( pDataPort->m_hFile == DNINVALID_HANDLE_VALUE );
  2821. DNASSERT( pDataPort->m_hListenEndpoint == 0 );
  2822. DNASSERT( pDataPort->m_hConnectEndpoint == 0 );
  2823. DNASSERT( pDataPort->m_hEnumEndpoint == 0 );
  2824. DNASSERT( pDataPort->m_iRefCount == 0 );
  2825. }
  2826. //**********************************************************************
  2827. //**********************************************************************
  2828. // ------------------------------
  2829. // CDataPort::SetPortState - set communications port state
  2830. // description
  2831. //
  2832. // Entry: Nothing
  2833. //
  2834. // Exit: Error code
  2835. // ------------------------------
  2836. #undef DPF_MODNAME
  2837. #define DPF_MODNAME "CDataPort::SetPortState"
  2838. HRESULT CDataPort::SetPortState( void )
  2839. {
  2840. DCB Dcb;
  2841. HRESULT hr;
  2842. DNASSERT( m_hFile != DNINVALID_HANDLE_VALUE );
  2843. //
  2844. // initialize
  2845. //
  2846. hr = DPN_OK;
  2847. memset( &Dcb, 0x00, sizeof( Dcb ) );
  2848. Dcb.DCBlength = sizeof( Dcb );
  2849. //
  2850. // set parameters
  2851. //
  2852. Dcb.BaudRate = GetBaudRate(); // current baud rate
  2853. Dcb.fBinary = TRUE; // binary mode, no EOF check (MUST BE TRUE FOR WIN32!)
  2854. //
  2855. // parity
  2856. //
  2857. if ( GetParity() != NOPARITY )
  2858. {
  2859. Dcb.fParity = TRUE;
  2860. }
  2861. else
  2862. {
  2863. Dcb.fParity = FALSE;
  2864. }
  2865. //
  2866. // are we using RTS?
  2867. //
  2868. if ( ( GetFlowControl() == FLOW_RTS ) ||
  2869. ( GetFlowControl() == FLOW_RTSDTR ) )
  2870. {
  2871. Dcb.fOutxCtsFlow = TRUE; // allow RTS/CTS
  2872. Dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; // handshake with RTS/CTS
  2873. }
  2874. else
  2875. {
  2876. Dcb.fOutxCtsFlow = FALSE; // disable RTS/CTS
  2877. Dcb.fRtsControl = RTS_CONTROL_ENABLE; // always be transmit ready
  2878. }
  2879. //
  2880. // are we using DTR?
  2881. //
  2882. if ( ( GetFlowControl() == FLOW_DTR ) ||
  2883. ( GetFlowControl() == FLOW_RTSDTR ) )
  2884. {
  2885. Dcb.fOutxDsrFlow = TRUE; // allow DTR/DSR
  2886. Dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; // handshake with DTR/DSR
  2887. }
  2888. else
  2889. {
  2890. Dcb.fOutxDsrFlow = FALSE; // disable DTR/DSR
  2891. Dcb.fDtrControl = DTR_CONTROL_ENABLE; // always be ready
  2892. }
  2893. //
  2894. // DSR sensitivity
  2895. //
  2896. Dcb.fDsrSensitivity = FALSE; // TRUE = incoming data dropped if DTR is not set
  2897. //
  2898. // continue sending after Xoff
  2899. //
  2900. Dcb.fTXContinueOnXoff= FALSE; // TRUE = continue to send data after XOFF has been received
  2901. // and there's room in the buffer
  2902. //
  2903. // are we using Xon/Xoff?
  2904. //
  2905. if ( GetFlowControl() == FLOW_XONXOFF )
  2906. {
  2907. Dcb.fOutX = TRUE;
  2908. Dcb.fInX = TRUE;
  2909. }
  2910. else
  2911. {
  2912. // disable Xon/Xoff
  2913. Dcb.fOutX = FALSE;
  2914. Dcb.fInX = FALSE;
  2915. }
  2916. //
  2917. // replace erroneous bytes with 'Error Byte'
  2918. //
  2919. Dcb.fErrorChar = FALSE; // TRUE = replace bytes with parity errors with
  2920. // an error character
  2921. //
  2922. // drop NULL characters
  2923. //
  2924. Dcb.fNull = FALSE; // TRUE = remove NULLs from input stream
  2925. //
  2926. // stop on error
  2927. //
  2928. Dcb.fAbortOnError = FALSE; // TRUE = abort reads/writes on error
  2929. //
  2930. // reserved, set to zero!
  2931. //
  2932. Dcb.fDummy2 = NULL; // reserved
  2933. //
  2934. // reserved
  2935. //
  2936. Dcb.wReserved = NULL; // not currently used
  2937. //
  2938. // buffer size before sending Xon/Xoff
  2939. //
  2940. Dcb.XonLim = XON_LIMIT; // transmit XON threshold
  2941. Dcb.XoffLim = XOFF_LIMIT; // transmit XOFF threshold
  2942. //
  2943. // size of a 'byte'
  2944. //
  2945. Dcb.ByteSize = BITS_PER_BYTE; // number of bits/byte, 4-8
  2946. //
  2947. // set parity type
  2948. //
  2949. DNASSERT( GetParity() < 256 );
  2950. Dcb.Parity = static_cast<BYTE>( GetParity() );
  2951. //
  2952. // stop bits
  2953. //
  2954. DNASSERT( GetStopBits() < 256 );
  2955. Dcb.StopBits = static_cast<BYTE>( GetStopBits() ); // 0,1,2 = 1, 1.5, 2
  2956. //
  2957. // Xon/Xoff characters
  2958. //
  2959. Dcb.XonChar = ASCII_XON; // Tx and Rx XON character
  2960. Dcb.XoffChar = ASCII_XOFF; // Tx and Rx XOFF character
  2961. //
  2962. // error replacement character
  2963. //
  2964. Dcb.ErrorChar = NULL_TOKEN; // error replacement character
  2965. //
  2966. // EOF character
  2967. //
  2968. Dcb.EofChar = NULL_TOKEN; // end of input character
  2969. //
  2970. // event signal character
  2971. //
  2972. Dcb.EvtChar = NULL_TOKEN; // event character
  2973. Dcb.wReserved1 = 0; // reserved; do not use
  2974. //
  2975. // set the state of the communication port
  2976. //
  2977. if ( SetCommState( HANDLE_FROM_DNHANDLE(m_hFile), &Dcb ) == FALSE )
  2978. {
  2979. DWORD dwError;
  2980. hr = DPNERR_GENERIC;
  2981. dwError = GetLastError();
  2982. DPFX(DPFPREP, 0, "SetCommState failed!" );
  2983. DisplayErrorCode( 0, dwError );
  2984. goto Exit;
  2985. }
  2986. Exit:
  2987. return hr;
  2988. }
  2989. //**********************************************************************