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.

3160 lines
83 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Endpoint.cpp
  6. * Content: DNSerial communications endpoint base class
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 01/20/99 jtk Created
  13. * 05/12/99 jtk Derived from modem endpoint class
  14. ***************************************************************************/
  15. #include "dnmdmi.h"
  16. //**********************************************************************
  17. // Constant definitions
  18. //**********************************************************************
  19. #define DEFAULT_TAPI_DEV_CAPS_SIZE 1024
  20. //**********************************************************************
  21. // Macro definitions
  22. //**********************************************************************
  23. //**********************************************************************
  24. // Structure definitions
  25. //**********************************************************************
  26. //**********************************************************************
  27. // Variable definitions
  28. //**********************************************************************
  29. //**********************************************************************
  30. // Function prototypes
  31. //**********************************************************************
  32. //**********************************************************************
  33. // Function definitions
  34. //**********************************************************************
  35. //**********************************************************************
  36. // ------------------------------
  37. // CModemEndpoint::CopyConnectData - copy data for connect command
  38. //
  39. // Entry: Pointer to job information
  40. //
  41. // Exit: Nothing
  42. //
  43. // Note: Since we've already initialized the local adapter, and we've either
  44. // completely parsed the host address (or are about to display a dialog
  45. // asking for more information), the address information doesn't need
  46. // to be copied.
  47. // ------------------------------
  48. #undef DPF_MODNAME
  49. #define DPF_MODNAME "CModemEndpoint::CopyConnectData"
  50. void CModemEndpoint::CopyConnectData( const SPCONNECTDATA *const pConnectData )
  51. {
  52. DNASSERT( GetType() == ENDPOINT_TYPE_CONNECT );
  53. DNASSERT( pConnectData != NULL );
  54. DNASSERT( pConnectData->hCommand != NULL );
  55. DNASSERT( pConnectData->dwCommandDescriptor != NULL_DESCRIPTOR );
  56. DNASSERT( m_Flags.fCommandPending == FALSE );
  57. DNASSERT( m_pCommandHandle == NULL );
  58. DBG_CASSERT( sizeof( m_CurrentCommandParameters.ConnectData ) == sizeof( *pConnectData ) );
  59. memcpy( &m_CurrentCommandParameters.ConnectData, pConnectData, sizeof( m_CurrentCommandParameters.ConnectData ) );
  60. m_CurrentCommandParameters.ConnectData.pAddressHost = NULL;
  61. m_CurrentCommandParameters.ConnectData.pAddressDeviceInfo = NULL;
  62. m_Flags.fCommandPending = TRUE;
  63. m_pCommandHandle = static_cast<CModemCommandData*>( m_CurrentCommandParameters.ConnectData.hCommand );
  64. m_pCommandHandle->SetUserContext( pConnectData->pvContext );
  65. SetState( ENDPOINT_STATE_ATTEMPTING_CONNECT );
  66. };
  67. //**********************************************************************
  68. //**********************************************************************
  69. // ------------------------------
  70. // CModemEndpoint::ConnectJobCallback - asynchronous callback wrapper from work thread
  71. //
  72. // Entry: Pointer to job information
  73. //
  74. // Exit: Nothing
  75. // ------------------------------
  76. #undef DPF_MODNAME
  77. #define DPF_MODNAME "CModemEndpoint::ConnectJobCallback"
  78. void CModemEndpoint::ConnectJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  79. {
  80. HRESULT hr;
  81. CModemEndpoint *pThisEndpoint;
  82. DNASSERT( pDelayedCommand != NULL );
  83. //
  84. // initialize
  85. //
  86. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  87. DNASSERT( pThisEndpoint->m_Flags.fCommandPending != FALSE );
  88. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  89. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.ConnectData.hCommand == pThisEndpoint->m_pCommandHandle );
  90. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.ConnectData.dwCommandDescriptor != NULL_DESCRIPTOR );
  91. hr = pThisEndpoint->CompleteConnect();
  92. if ( hr != DPN_OK )
  93. {
  94. DPFX(DPFPREP, 0, "Problem completing connect in job callback!" );
  95. DisplayDNError( 0, hr );
  96. goto Exit;
  97. }
  98. //
  99. // Don't do anything here because it's possible that this object was returned
  100. // to the pool!!!
  101. //
  102. Exit:
  103. pThisEndpoint->DecRef();
  104. return;
  105. }
  106. //**********************************************************************
  107. //**********************************************************************
  108. // ------------------------------
  109. // CModemEndpoint::CancelConnectJobCallback - cancel for connect job
  110. //
  111. // Entry: Pointer to job information
  112. //
  113. // Exit: Nothing
  114. // ------------------------------
  115. #undef DPF_MODNAME
  116. #define DPF_MODNAME "CModemEndpoint::CancelConnectJobCallback"
  117. void CModemEndpoint::CancelConnectJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  118. {
  119. CModemEndpoint *pThisEndpoint;
  120. DNASSERT( pDelayedCommand != NULL );
  121. //
  122. // initialize
  123. //
  124. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  125. DNASSERT( pThisEndpoint != NULL );
  126. DNASSERT( pThisEndpoint->m_State == ENDPOINT_STATE_ATTEMPTING_CONNECT );
  127. //
  128. // we're cancelling this command, set the command state to 'cancel'
  129. //
  130. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  131. pThisEndpoint->m_pCommandHandle->Lock();
  132. DNASSERT( ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_PENDING ) ||
  133. ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_CANCELLING ) );
  134. pThisEndpoint->m_pCommandHandle->SetState( COMMAND_STATE_CANCELLING );
  135. pThisEndpoint->m_pCommandHandle->Unlock();
  136. pThisEndpoint->Close( DPNERR_USERCANCEL );
  137. pThisEndpoint->GetSPData()->CloseEndpointHandle( pThisEndpoint );
  138. pThisEndpoint->DecRef();
  139. }
  140. //**********************************************************************
  141. //**********************************************************************
  142. // ------------------------------
  143. // CModemEndpoint::CompleteConnect - complete connection
  144. //
  145. // Entry: Nothing
  146. //
  147. // Exit: Error code
  148. // ------------------------------
  149. HRESULT CModemEndpoint::CompleteConnect( void )
  150. {
  151. HRESULT hr;
  152. //
  153. // initialize
  154. //
  155. hr = DPN_OK;
  156. DNASSERT( GetState() == ENDPOINT_STATE_ATTEMPTING_CONNECT );
  157. DNASSERT( m_Flags.fCommandPending != FALSE );
  158. DNASSERT( m_pCommandHandle != NULL );
  159. DNASSERT( m_CurrentCommandParameters.ConnectData.hCommand == m_pCommandHandle );
  160. DNASSERT( m_CurrentCommandParameters.ConnectData.dwCommandDescriptor != NULL_DESCRIPTOR );
  161. //
  162. // check for user cancelling command
  163. //
  164. m_pCommandHandle->Lock();
  165. DNASSERT( m_pCommandHandle->GetType() == COMMAND_TYPE_CONNECT );
  166. switch ( m_pCommandHandle->GetState() )
  167. {
  168. //
  169. // Command is still pending, don't mark it as uninterruptable because
  170. // it might be cancelled before indicating the final connect.
  171. //
  172. case COMMAND_STATE_PENDING:
  173. {
  174. DNASSERT( hr == DPN_OK );
  175. break;
  176. }
  177. //
  178. // command has been cancelled
  179. //
  180. case COMMAND_STATE_CANCELLING:
  181. {
  182. hr = DPNERR_USERCANCEL;
  183. DPFX(DPFPREP, 0, "User cancelled connect!" );
  184. break;
  185. }
  186. //
  187. // other state
  188. //
  189. default:
  190. {
  191. DNASSERT( FALSE );
  192. break;
  193. }
  194. }
  195. m_pCommandHandle->Unlock();
  196. if ( hr != DPN_OK )
  197. {
  198. goto Failure;
  199. }
  200. //
  201. // find a dataport to bind with
  202. //
  203. hr = m_pSPData->BindEndpoint( this, GetDeviceID(), GetDeviceContext() );
  204. if ( hr != DPN_OK )
  205. {
  206. DPFX(DPFPREP, 0, "Failed to bind to data port in connect!" );
  207. DisplayDNError( 0, hr );
  208. goto Failure;
  209. }
  210. //
  211. // The connect sequence will complete when the CDataPort indicates that the
  212. // outbound connection has been established.
  213. //
  214. Exit:
  215. return hr;
  216. Failure:
  217. Close( hr );
  218. m_pSPData->CloseEndpointHandle( this );
  219. goto Exit;
  220. }
  221. //**********************************************************************
  222. //**********************************************************************
  223. // ------------------------------
  224. // CModemEndpoint::Disconnect - disconnect this endpoint
  225. //
  226. // Entry: Old handle value
  227. //
  228. // Exit: Error code
  229. // ------------------------------
  230. #undef DPF_MODNAME
  231. #define DPF_MODNAME "CModemEndpoint::Disconnect"
  232. HRESULT CModemEndpoint::Disconnect( const DPNHANDLE hOldEndpointHandle )
  233. {
  234. HRESULT hr;
  235. DPFX(DPFPREP, 6, "(0x%p) Parameters: (0x%p)", this, hOldEndpointHandle );
  236. AssertCriticalSectionIsTakenByThisThread( &m_Lock, FALSE );
  237. //
  238. // initialize
  239. //
  240. hr = DPN_OK;
  241. Lock();
  242. switch ( GetState() )
  243. {
  244. //
  245. // connected endpoint
  246. //
  247. case ENDPOINT_STATE_CONNECT_CONNECTED:
  248. {
  249. DNASSERT( m_Flags.fCommandPending == FALSE );
  250. DNASSERT( m_pCommandHandle == NULL );
  251. SetState( ENDPOINT_STATE_DISCONNECTING );
  252. AddRef();
  253. //
  254. // Unlock this endpoint before calling to a higher level. The endpoint
  255. // has already been labeled as DISCONNECTING so nothing will happen to it.
  256. //
  257. Unlock();
  258. //
  259. // Note the old endpoint handle so it can be used in the disconnect
  260. // indication that will be given just before this endpoint is returned
  261. // to the pool. Need to release the reference that was added for the
  262. // connection at this point or the endpoint will never be returned to
  263. // the pool.
  264. //
  265. SetDisconnectIndicationHandle( hOldEndpointHandle );
  266. DecRef();
  267. Close( DPN_OK );
  268. //
  269. // close outstanding reference for this command
  270. //
  271. DecCommandRef();
  272. DecRef();
  273. break;
  274. }
  275. //
  276. // endpoint waiting for the modem to pick up on the other end
  277. //
  278. case ENDPOINT_STATE_ATTEMPTING_CONNECT:
  279. {
  280. SetState( ENDPOINT_STATE_DISCONNECTING );
  281. AddRef();
  282. Unlock();
  283. Close( DPNERR_NOCONNECTION );
  284. //
  285. // close outstanding reference for this command
  286. //
  287. DecCommandRef();
  288. DecRef();
  289. break;
  290. }
  291. //
  292. // some other endpoint state
  293. //
  294. default:
  295. {
  296. hr = DPNERR_INVALIDENDPOINT;
  297. DPFX(DPFPREP, 0, "Attempted to disconnect endpoint that's not connected!" );
  298. switch ( m_State )
  299. {
  300. case ENDPOINT_STATE_UNINITIALIZED:
  301. {
  302. DPFX(DPFPREP, 0, "ENDPOINT_STATE_UNINITIALIZED" );
  303. break;
  304. }
  305. case ENDPOINT_STATE_ATTEMPTING_LISTEN:
  306. {
  307. DPFX(DPFPREP, 0, "ENDPOINT_STATE_ATTEMPTING_LISTEN" );
  308. break;
  309. }
  310. case ENDPOINT_STATE_ENUM:
  311. {
  312. DPFX(DPFPREP, 0, "ENDPOINT_STATE_ENUM" );
  313. break;
  314. }
  315. case ENDPOINT_STATE_DISCONNECTING:
  316. {
  317. DPFX(DPFPREP, 0, "ENDPOINT_STATE_DISCONNECTING" );
  318. break;
  319. }
  320. default:
  321. {
  322. DNASSERT( FALSE );
  323. break;
  324. }
  325. }
  326. Unlock();
  327. DNASSERT( FALSE );
  328. goto Failure;
  329. break;
  330. }
  331. }
  332. Exit:
  333. DPFX(DPFPREP, 6, "(0x%p) Returning [0x%lx]", this, hr );
  334. return hr;
  335. Failure:
  336. // nothing to do
  337. goto Exit;
  338. }
  339. //**********************************************************************
  340. //**********************************************************************
  341. // ------------------------------
  342. // CModemEndpoint::StopEnumCommand - stop an enum job
  343. //
  344. // Entry: Error code for completing command
  345. //
  346. // Exit: Nothing
  347. // ------------------------------
  348. #undef DPF_MODNAME
  349. #define DPF_MODNAME "CModemEndpoint::StopEnumCommand"
  350. void CModemEndpoint::StopEnumCommand( const HRESULT hCommandResult )
  351. {
  352. Lock();
  353. DNASSERT( GetState() == ENDPOINT_STATE_DISCONNECTING );
  354. if ( m_hActiveDialogHandle != NULL )
  355. {
  356. StopSettingsDialog( m_hActiveDialogHandle );
  357. Unlock();
  358. }
  359. else
  360. {
  361. BOOL fStoppedJob;
  362. Unlock();
  363. fStoppedJob = m_pSPData->GetThreadPool()->StopTimerJob( m_pCommandHandle, hCommandResult );
  364. if ( ! fStoppedJob )
  365. {
  366. DPFX(DPFPREP, 1, "Unable to stop timer job (context 0x%p) manually setting result to 0x%lx.",
  367. m_pCommandHandle, hCommandResult);
  368. //
  369. // Set the command result so it can be returned when the endpoint
  370. // reference count is zero.
  371. //
  372. SetCommandResult( hCommandResult );
  373. }
  374. }
  375. m_pSPData->CloseEndpointHandle( this );
  376. }
  377. //**********************************************************************
  378. //**********************************************************************
  379. // ------------------------------
  380. // CModemEndpoint::SetState - set state of this endpoint
  381. //
  382. // Entry: New state
  383. //
  384. // Exit: Nothing
  385. // ------------------------------
  386. #undef DPF_MODNAME
  387. #define DPF_MODNAME "CModemEndpoint::SetState"
  388. void CModemEndpoint::SetState( const ENDPOINT_STATE EndpointState )
  389. {
  390. DNASSERT( ( GetState() == ENDPOINT_STATE_UNINITIALIZED ) ||
  391. ( EndpointState == ENDPOINT_STATE_UNINITIALIZED ) ||
  392. ( ( m_State== ENDPOINT_STATE_ATTEMPTING_LISTEN ) && ( EndpointState == ENDPOINT_STATE_LISTENING ) ) ||
  393. ( ( m_State == ENDPOINT_STATE_LISTENING ) && ( EndpointState == ENDPOINT_STATE_DISCONNECTING ) ) ||
  394. ( ( m_State == ENDPOINT_STATE_ATTEMPTING_ENUM ) && ( EndpointState == ENDPOINT_STATE_ENUM ) ) ||
  395. ( ( m_State == ENDPOINT_STATE_ENUM ) && ( EndpointState == ENDPOINT_STATE_DISCONNECTING ) ) ||
  396. ( ( m_State == ENDPOINT_STATE_ATTEMPTING_ENUM ) && ( EndpointState == ENDPOINT_STATE_DISCONNECTING ) ) ||
  397. ( ( m_State == ENDPOINT_STATE_ATTEMPTING_CONNECT ) && ( EndpointState == ENDPOINT_STATE_DISCONNECTING ) ) ||
  398. ( ( m_State == ENDPOINT_STATE_CONNECT_CONNECTED ) && ( EndpointState == ENDPOINT_STATE_DISCONNECTING ) ) );
  399. m_State = EndpointState;
  400. }
  401. //**********************************************************************
  402. //**********************************************************************
  403. // ------------------------------
  404. // CModemEndpoint::CopyListenData - copy data for listen command
  405. //
  406. // Entry: Pointer to job information
  407. //
  408. // Exit: Nothing
  409. //
  410. // Note: Since we've already initialized the local adapter, and we've either
  411. // completely parsed the host address (or are about to display a dialog
  412. // asking for more information), the address information doesn't need
  413. // to be copied.
  414. // ------------------------------
  415. #undef DPF_MODNAME
  416. #define DPF_MODNAME "CModemEndpoint::CopyListenData"
  417. void CModemEndpoint::CopyListenData( const SPLISTENDATA *const pListenData )
  418. {
  419. DNASSERT( GetType() == ENDPOINT_TYPE_LISTEN );
  420. DNASSERT( pListenData != NULL );
  421. DNASSERT( pListenData->hCommand != NULL );
  422. DNASSERT( pListenData->dwCommandDescriptor != NULL_DESCRIPTOR );
  423. DNASSERT( m_Flags.fCommandPending == FALSE );
  424. DNASSERT( m_pCommandHandle == NULL );
  425. DNASSERT( m_Flags.fListenStatusNeedsToBeIndicated == FALSE );
  426. DBG_CASSERT( sizeof( m_CurrentCommandParameters.ListenData ) == sizeof( *pListenData ) );
  427. memcpy( &m_CurrentCommandParameters.ListenData, pListenData, sizeof( m_CurrentCommandParameters.ListenData ) );
  428. DEBUG_ONLY( m_CurrentCommandParameters.ListenData.pAddressDeviceInfo = NULL );
  429. m_Flags.fCommandPending = TRUE;
  430. m_Flags.fListenStatusNeedsToBeIndicated = TRUE;
  431. m_pCommandHandle = static_cast<CModemCommandData*>( m_CurrentCommandParameters.ListenData.hCommand );
  432. m_pCommandHandle->SetUserContext( pListenData->pvContext );
  433. SetState( ENDPOINT_STATE_ATTEMPTING_LISTEN );
  434. }
  435. //**********************************************************************
  436. //**********************************************************************
  437. // ------------------------------
  438. // CModemEndpoint::ListenJobCallback - asynchronous callback wrapper for work thread
  439. //
  440. // Entry: Pointer to job information
  441. //
  442. // Exit: Nothing
  443. // ------------------------------
  444. #undef DPF_MODNAME
  445. #define DPF_MODNAME "CModemEndpoint::ListenJobCallback"
  446. void CModemEndpoint::ListenJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  447. {
  448. HRESULT hr;
  449. CModemEndpoint *pThisEndpoint;
  450. DNASSERT( pDelayedCommand != NULL );
  451. // initialize
  452. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  453. DNASSERT( pThisEndpoint->GetState() == ENDPOINT_STATE_ATTEMPTING_LISTEN );
  454. DNASSERT( pThisEndpoint->m_Flags.fCommandPending != NULL );
  455. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  456. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.ListenData.hCommand == pThisEndpoint->m_pCommandHandle );
  457. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.ListenData.dwCommandDescriptor != NULL_DESCRIPTOR );
  458. hr = pThisEndpoint->CompleteListen();
  459. if ( hr != DPN_OK )
  460. {
  461. DPFX(DPFPREP, 0, "Problem completing listen in job callback!" );
  462. DisplayDNError( 0, hr );
  463. goto Exit;
  464. }
  465. Exit:
  466. pThisEndpoint->DecRef();
  467. //
  468. // Don't do anything here because it's possible that this object was returned
  469. // to the pool!!!!
  470. //
  471. return;
  472. }
  473. //**********************************************************************
  474. //**********************************************************************
  475. // ------------------------------
  476. // CModemEndpoint::CancelListenJobCallback - cancel for listen job
  477. //
  478. // Entry: Pointer to job information
  479. //
  480. // Exit: Nothing
  481. // ------------------------------
  482. #undef DPF_MODNAME
  483. #define DPF_MODNAME "CModemEndpoint::CancelListenJobCallback"
  484. void CModemEndpoint::CancelListenJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  485. {
  486. CModemEndpoint *pThisEndpoint;
  487. DNASSERT( pDelayedCommand != NULL );
  488. //
  489. // initialize
  490. //
  491. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  492. DNASSERT( pThisEndpoint != NULL );
  493. DNASSERT( pThisEndpoint->m_State == ENDPOINT_STATE_ATTEMPTING_LISTEN );
  494. //
  495. // we're cancelling this command, set the command state to 'cancel'
  496. //
  497. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  498. pThisEndpoint->m_pCommandHandle->Lock();
  499. DNASSERT( ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_PENDING ) ||
  500. ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_CANCELLING ) );
  501. pThisEndpoint->m_pCommandHandle->SetState( COMMAND_STATE_CANCELLING );
  502. pThisEndpoint->m_pCommandHandle->Unlock();
  503. pThisEndpoint->Close( DPNERR_USERCANCEL );
  504. pThisEndpoint->GetSPData()->CloseEndpointHandle( pThisEndpoint );
  505. pThisEndpoint->DecRef();
  506. }
  507. //**********************************************************************
  508. //**********************************************************************
  509. // ------------------------------
  510. // CModemEndpoint::CompleteListen - complete listen process
  511. //
  512. // Entry: Nothing
  513. //
  514. // Exit: Error code
  515. // ------------------------------
  516. HRESULT CModemEndpoint::CompleteListen( void )
  517. {
  518. HRESULT hr;
  519. BOOL fEndpointLocked;
  520. SPIE_LISTENSTATUS ListenStatus;
  521. HRESULT hTempResult;
  522. DNASSERT( GetState() == ENDPOINT_STATE_ATTEMPTING_LISTEN );
  523. //
  524. // initialize
  525. //
  526. hr = DPN_OK;
  527. fEndpointLocked = FALSE;
  528. DNASSERT( GetState() == ENDPOINT_STATE_ATTEMPTING_LISTEN );
  529. DNASSERT( m_Flags.fCommandPending != FALSE );
  530. DNASSERT( m_pCommandHandle != NULL );
  531. DNASSERT( m_pCommandHandle->GetEndpoint() == this );
  532. DNASSERT( m_CurrentCommandParameters.ListenData.hCommand == m_pCommandHandle );
  533. DNASSERT( m_CurrentCommandParameters.ListenData.dwCommandDescriptor != NULL_DESCRIPTOR );
  534. //
  535. // check for user cancelling command
  536. //
  537. Lock();
  538. fEndpointLocked = TRUE;
  539. m_pCommandHandle->Lock();
  540. DNASSERT( m_pCommandHandle->GetType() == COMMAND_TYPE_LISTEN );
  541. switch ( m_pCommandHandle->GetState() )
  542. {
  543. //
  544. // command is pending, mark as in-progress and cancellable
  545. //
  546. case COMMAND_STATE_PENDING:
  547. {
  548. m_pCommandHandle->SetState( COMMAND_STATE_INPROGRESS );
  549. DNASSERT( hr == DPN_OK );
  550. break;
  551. }
  552. //
  553. // command has been cancelled
  554. //
  555. case COMMAND_STATE_CANCELLING:
  556. {
  557. hr = DPNERR_USERCANCEL;
  558. DPFX(DPFPREP, 0, "User cancelled listen!" );
  559. Unlock();
  560. fEndpointLocked = FALSE;
  561. break;
  562. }
  563. //
  564. // other state
  565. //
  566. default:
  567. {
  568. DNASSERT( FALSE );
  569. Unlock();
  570. fEndpointLocked = FALSE;
  571. break;
  572. }
  573. }
  574. m_pCommandHandle->Unlock();
  575. if ( hr != DPN_OK )
  576. {
  577. goto Failure;
  578. }
  579. //
  580. // find a dataport to bind with
  581. //
  582. hr = m_pSPData->BindEndpoint( this, GetDeviceID(), GetDeviceContext() );
  583. if ( hr != DPN_OK )
  584. {
  585. DPFX(DPFPREP, 0, "Failed to bind endpoint for serial listen!" );
  586. DisplayDNError( 0, hr );
  587. goto Failure;
  588. }
  589. //
  590. // We're done and everyone's happy. Listen commands never
  591. // complete until cancelled by the user. Don't complete
  592. // the command at this point.
  593. //
  594. SetState( ENDPOINT_STATE_LISTENING );
  595. DNASSERT( m_Flags.fCommandPending != FALSE );
  596. DNASSERT( m_pCommandHandle != NULL );
  597. Exit:
  598. if ( fEndpointLocked != FALSE )
  599. {
  600. Unlock();
  601. fEndpointLocked = FALSE;
  602. }
  603. if ( m_Flags.fListenStatusNeedsToBeIndicated != FALSE )
  604. {
  605. m_Flags.fListenStatusNeedsToBeIndicated = FALSE;
  606. memset( &ListenStatus, 0x00, sizeof( ListenStatus ) );
  607. ListenStatus.hResult = hr;
  608. DNASSERT( m_pCommandHandle == m_CurrentCommandParameters.ListenData.hCommand );
  609. ListenStatus.hCommand = m_CurrentCommandParameters.ListenData.hCommand;
  610. ListenStatus.pUserContext = m_CurrentCommandParameters.ListenData.pvContext;
  611. ListenStatus.hEndpoint = (HANDLE)(DWORD_PTR)GetHandle();
  612. DeviceIDToGuid( &ListenStatus.ListenAdapter, GetDeviceID(), GetEncryptionGuid() );
  613. hTempResult = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // pointer to DPlay callbacks
  614. SPEV_LISTENSTATUS, // data type
  615. &ListenStatus // pointer to data
  616. );
  617. DNASSERT( hTempResult == DPN_OK );
  618. }
  619. return hr;
  620. Failure:
  621. //
  622. // we've failed to complete the listen, clean up and return this
  623. // endpoint to the pool
  624. //
  625. Close( hr );
  626. m_pSPData->CloseEndpointHandle( this );
  627. goto Exit;
  628. }
  629. //**********************************************************************
  630. //**********************************************************************
  631. // ------------------------------
  632. // CModemEndpoint::CopyEnumQueryData - copy data for enum query command
  633. //
  634. // Entry: Pointer to command data
  635. //
  636. // Exit: Nothing
  637. //
  638. // Note: Since we've already initialized the local adapter, and we've either
  639. // completely parsed the host address (or are about to display a dialog
  640. // asking for more information), the address information doesn't need
  641. // to be copied.
  642. // ------------------------------
  643. #undef DPF_MODNAME
  644. #define DPF_MODNAME "CModemEndpoint::CopyEnumQueryData"
  645. void CModemEndpoint::CopyEnumQueryData( const SPENUMQUERYDATA *const pEnumQueryData )
  646. {
  647. DNASSERT( GetType() == ENDPOINT_TYPE_ENUM );
  648. DNASSERT( pEnumQueryData != NULL );
  649. DNASSERT( pEnumQueryData->hCommand != NULL );
  650. DNASSERT( pEnumQueryData->dwCommandDescriptor != NULL_DESCRIPTOR );
  651. DNASSERT( m_Flags.fCommandPending == FALSE );
  652. DNASSERT( m_pCommandHandle == NULL );
  653. DBG_CASSERT( sizeof( m_CurrentCommandParameters.EnumQueryData ) == sizeof( *pEnumQueryData ) );
  654. memcpy( &m_CurrentCommandParameters.EnumQueryData, pEnumQueryData, sizeof( m_CurrentCommandParameters.EnumQueryData ) );
  655. m_CurrentCommandParameters.EnumQueryData.pAddressHost = NULL;
  656. m_CurrentCommandParameters.EnumQueryData.pAddressDeviceInfo = NULL;
  657. m_Flags.fCommandPending = TRUE;
  658. m_pCommandHandle = static_cast<CModemCommandData*>( m_CurrentCommandParameters.EnumQueryData.hCommand );
  659. m_pCommandHandle->SetUserContext( pEnumQueryData->pvContext );
  660. SetState( ENDPOINT_STATE_ATTEMPTING_ENUM );
  661. }
  662. //**********************************************************************
  663. //**********************************************************************
  664. // ------------------------------
  665. // CModemEndpoint::EnumQueryJobCallback - asynchronous callback wrapper for work thread
  666. //
  667. // Entry: Pointer to job information
  668. //
  669. // Exit: Nothing
  670. // ------------------------------
  671. #undef DPF_MODNAME
  672. #define DPF_MODNAME "CModemEndpoint::EnumQueryJobCallback"
  673. void CModemEndpoint::EnumQueryJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  674. {
  675. HRESULT hr;
  676. CModemEndpoint *pThisEndpoint;
  677. DNASSERT( pDelayedCommand != NULL );
  678. //
  679. // initialize
  680. //
  681. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  682. DNASSERT( pThisEndpoint->m_Flags.fCommandPending != FALSE );
  683. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  684. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.EnumQueryData.hCommand == pThisEndpoint->m_pCommandHandle );
  685. DNASSERT( pThisEndpoint->m_CurrentCommandParameters.EnumQueryData.dwCommandDescriptor != NULL_DESCRIPTOR );
  686. hr = pThisEndpoint->CompleteEnumQuery();
  687. if ( hr != DPN_OK )
  688. {
  689. DPFX(DPFPREP, 0, "Problem completing enum query in job callback!" );
  690. DisplayDNError( 0, hr );
  691. goto Exit;
  692. }
  693. //
  694. // Don't do anything here because it's possible that this object was returned to the pool!!!!
  695. //
  696. Exit:
  697. pThisEndpoint->DecRef();
  698. return;
  699. }
  700. //**********************************************************************
  701. //**********************************************************************
  702. // ------------------------------
  703. // CModemEndpoint::CancelEnumQueryJobCallback - cancel for enum query job
  704. //
  705. // Entry: Pointer to job information
  706. //
  707. // Exit: Nothing
  708. // ------------------------------
  709. #undef DPF_MODNAME
  710. #define DPF_MODNAME "CModemEndpoint::CancelEnumQueryJobCallback"
  711. void CModemEndpoint::CancelEnumQueryJobCallback( THREAD_POOL_JOB *const pDelayedCommand )
  712. {
  713. CModemEndpoint *pThisEndpoint;
  714. DNASSERT( pDelayedCommand != NULL );
  715. //
  716. // initialize
  717. //
  718. pThisEndpoint = static_cast<CModemEndpoint*>( pDelayedCommand->JobData.JobDelayedCommand.pContext );
  719. DNASSERT( pThisEndpoint != NULL );
  720. DNASSERT( pThisEndpoint->m_State == ENDPOINT_STATE_ATTEMPTING_ENUM );
  721. //
  722. // we're cancelling this command, set the command state to 'cancel'
  723. //
  724. DNASSERT( pThisEndpoint->m_pCommandHandle != NULL );
  725. pThisEndpoint->m_pCommandHandle->Lock();
  726. DNASSERT( ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_INPROGRESS ) ||
  727. ( pThisEndpoint->m_pCommandHandle->GetState() == COMMAND_STATE_CANCELLING ) );
  728. pThisEndpoint->m_pCommandHandle->SetState( COMMAND_STATE_CANCELLING );
  729. pThisEndpoint->m_pCommandHandle->Unlock();
  730. pThisEndpoint->Close( DPNERR_USERCANCEL );
  731. pThisEndpoint->GetSPData()->CloseEndpointHandle( pThisEndpoint );
  732. pThisEndpoint->DecRef();
  733. }
  734. //**********************************************************************
  735. //**********************************************************************
  736. // ------------------------------
  737. // CModemEndpoint::CompleteEnumQuery - complete enum query process
  738. //
  739. // Entry: Nothing
  740. //
  741. // Exit: Error code
  742. // ------------------------------
  743. HRESULT CModemEndpoint::CompleteEnumQuery( void )
  744. {
  745. HRESULT hr;
  746. BOOL fEndpointLocked;
  747. BOOL fEndpointBound;
  748. CDataPort *pDataPort;
  749. //
  750. // initialize
  751. //
  752. hr = DPN_OK;
  753. fEndpointLocked = FALSE;
  754. fEndpointBound = FALSE;
  755. pDataPort = NULL;
  756. DNASSERT( GetState() == ENDPOINT_STATE_ATTEMPTING_ENUM );
  757. DNASSERT( m_Flags.fCommandPending != FALSE );
  758. DNASSERT( m_pCommandHandle != NULL );
  759. DNASSERT( m_pCommandHandle->GetEndpoint() == this );
  760. DNASSERT( m_CurrentCommandParameters.EnumQueryData.hCommand == m_pCommandHandle );
  761. DNASSERT( m_CurrentCommandParameters.EnumQueryData.dwCommandDescriptor != NULL_DESCRIPTOR );
  762. //
  763. // check for user cancelling command
  764. //
  765. Lock();
  766. fEndpointLocked = TRUE;
  767. m_pCommandHandle->Lock();
  768. DNASSERT( m_pCommandHandle->GetType() == COMMAND_TYPE_ENUM_QUERY );
  769. switch ( m_pCommandHandle->GetState() )
  770. {
  771. //
  772. // command is still in progress
  773. //
  774. case COMMAND_STATE_INPROGRESS:
  775. {
  776. DNASSERT( hr == DPN_OK );
  777. break;
  778. }
  779. //
  780. // command has been cancelled
  781. //
  782. case COMMAND_STATE_CANCELLING:
  783. {
  784. hr = DPNERR_USERCANCEL;
  785. DPFX(DPFPREP, 0, "User cancelled enum query!" );
  786. Unlock();
  787. fEndpointLocked = FALSE;
  788. break;
  789. }
  790. //
  791. // other state
  792. //
  793. default:
  794. {
  795. DNASSERT( FALSE );
  796. Unlock();
  797. fEndpointLocked = FALSE;
  798. break;
  799. }
  800. }
  801. m_pCommandHandle->Unlock();
  802. if ( hr != DPN_OK )
  803. {
  804. goto Failure;
  805. }
  806. //
  807. // find a dataport to bind with
  808. //
  809. hr = m_pSPData->BindEndpoint( this, GetDeviceID(), GetDeviceContext() );
  810. if ( hr != DPN_OK )
  811. {
  812. DPFX(DPFPREP, 0, "Failed to bind to data port for EnumQuery!" );
  813. DisplayDNError( 0, hr );
  814. goto Failure;
  815. }
  816. fEndpointBound = TRUE;
  817. SetState( ENDPOINT_STATE_ENUM );
  818. Exit:
  819. if ( fEndpointLocked != FALSE )
  820. {
  821. Unlock();
  822. fEndpointLocked = FALSE;
  823. }
  824. if ( pDataPort != NULL )
  825. {
  826. pDataPort->EndpointDecRef();
  827. pDataPort = NULL;
  828. }
  829. return hr;
  830. Failure:
  831. if ( fEndpointBound != FALSE )
  832. {
  833. DNASSERT( GetDataPort() != NULL );
  834. m_pSPData->UnbindEndpoint( this, GetType() );
  835. fEndpointBound = FALSE;
  836. }
  837. if ( fEndpointLocked != FALSE )
  838. {
  839. Unlock();
  840. fEndpointLocked = FALSE;
  841. }
  842. Close( hr );
  843. m_pSPData->CloseEndpointHandle( this );
  844. goto Exit;
  845. }
  846. //**********************************************************************
  847. //**********************************************************************
  848. // ------------------------------
  849. // CModemEndpoint::OutgoingConnectionEstablished - an outgoing connection was established
  850. //
  851. // Entry: Command result (DPN_OK == connection succeeded)
  852. //
  853. // Exit: Nothing
  854. // ------------------------------
  855. void CModemEndpoint::OutgoingConnectionEstablished( const HRESULT hCommandResult )
  856. {
  857. HRESULT hr;
  858. CModemCommandData *pCommandData;
  859. DPFX(DPFPREP, 6, "(0x%p) Parameters: (0x%lx)", this, hCommandResult);
  860. pCommandData = GetCommandData();
  861. DNASSERT( pCommandData != NULL );
  862. //
  863. // check for successful connection
  864. //
  865. if ( hCommandResult != DPN_OK )
  866. {
  867. DNASSERT( FALSE );
  868. hr = hCommandResult;
  869. goto Failure;
  870. }
  871. //
  872. // determine which type of outgoing connection this is and complete it
  873. //
  874. switch ( GetType() )
  875. {
  876. case ENDPOINT_TYPE_CONNECT:
  877. {
  878. BOOL fProceed;
  879. fProceed = TRUE;
  880. pCommandData->Lock();
  881. switch ( pCommandData->GetState() )
  882. {
  883. case COMMAND_STATE_PENDING:
  884. {
  885. pCommandData->SetState( COMMAND_STATE_INPROGRESS_CANNOT_CANCEL );
  886. DNASSERT( fProceed != FALSE );
  887. break;
  888. }
  889. case COMMAND_STATE_CANCELLING:
  890. {
  891. fProceed = FALSE;
  892. break;
  893. }
  894. default:
  895. {
  896. DNASSERT( FALSE );
  897. break;
  898. }
  899. }
  900. pCommandData->Unlock();
  901. if ( fProceed != FALSE )
  902. {
  903. SPIE_CONNECT ConnectIndicationData;
  904. //
  905. // Inform user of connection. Assume that the user will accept
  906. // and everything will succeed so we can set the user context
  907. // for the endpoint. If the connection fails, clear the user
  908. // endpoint context.
  909. //
  910. memset( &ConnectIndicationData, 0x00, sizeof( ConnectIndicationData ) );
  911. DBG_CASSERT( sizeof( ConnectIndicationData.hEndpoint ) == sizeof( HANDLE ) );
  912. ConnectIndicationData.hEndpoint = (HANDLE)(DWORD_PTR)GetHandle();
  913. ConnectIndicationData.pCommandContext = m_CurrentCommandParameters.ConnectData.pvContext;
  914. SetUserEndpointContext( ConnectIndicationData.pEndpointContext );
  915. hr = SignalConnect( &ConnectIndicationData );
  916. if ( hr != DPN_OK )
  917. {
  918. DNASSERT( hr == DPNERR_ABORTED );
  919. DPFX(DPFPREP, 0, "User refused connect in CompleteConnect!" );
  920. DisplayDNError( 0, hr );
  921. SetUserEndpointContext( NULL );
  922. goto Failure;
  923. }
  924. //
  925. // we're done and everyone's happy, complete the command, this
  926. // will clear all of our internal command data
  927. //
  928. CompletePendingCommand( hr );
  929. DNASSERT( m_Flags.fCommandPending == FALSE );
  930. DNASSERT( m_pCommandHandle == NULL );
  931. }
  932. break;
  933. }
  934. case ENDPOINT_TYPE_ENUM:
  935. {
  936. UINT_PTR uRetryCount;
  937. BOOL fRetryForever;
  938. DWORD dwRetryInterval;
  939. BOOL fWaitForever;
  940. DWORD dwIdleTimeout;
  941. //
  942. // check retry to determine if we're enumerating forever
  943. //
  944. switch ( m_CurrentCommandParameters.EnumQueryData.dwRetryCount )
  945. {
  946. //
  947. // let SP determine retry count
  948. //
  949. case 0:
  950. {
  951. uRetryCount = DEFAULT_ENUM_RETRY_COUNT;
  952. fRetryForever = FALSE;
  953. break;
  954. }
  955. //
  956. // retry forever
  957. //
  958. case INFINITE:
  959. {
  960. uRetryCount = 1;
  961. fRetryForever = TRUE;
  962. break;
  963. }
  964. //
  965. // other
  966. //
  967. default:
  968. {
  969. uRetryCount = m_CurrentCommandParameters.EnumQueryData.dwRetryCount;
  970. fRetryForever = FALSE;
  971. break;
  972. }
  973. }
  974. //
  975. // check interval for default
  976. //
  977. if ( m_CurrentCommandParameters.EnumQueryData.dwRetryInterval == 0 )
  978. {
  979. dwRetryInterval = DEFAULT_ENUM_RETRY_INTERVAL;
  980. }
  981. else
  982. {
  983. dwRetryInterval = m_CurrentCommandParameters.EnumQueryData.dwRetryInterval;
  984. }
  985. //
  986. // check timeout to see if we're waiting forever
  987. //
  988. switch ( m_CurrentCommandParameters.EnumQueryData.dwTimeout )
  989. {
  990. //
  991. // wait forever
  992. //
  993. case INFINITE:
  994. {
  995. fWaitForever = TRUE;
  996. dwIdleTimeout = -1;
  997. break;
  998. }
  999. //
  1000. // possible default
  1001. //
  1002. case 0:
  1003. {
  1004. fWaitForever = FALSE;
  1005. dwIdleTimeout = DEFAULT_ENUM_TIMEOUT;
  1006. break;
  1007. }
  1008. //
  1009. // other
  1010. //
  1011. default:
  1012. {
  1013. fWaitForever = FALSE;
  1014. dwIdleTimeout = m_CurrentCommandParameters.EnumQueryData.dwTimeout;
  1015. break;
  1016. }
  1017. }
  1018. m_dwEnumSendIndex = 0;
  1019. memset( m_dwEnumSendTimes, 0, sizeof( m_dwEnumSendTimes ) );
  1020. pCommandData->Lock();
  1021. if ( pCommandData->GetState() == COMMAND_STATE_INPROGRESS )
  1022. {
  1023. //
  1024. // add a reference for the timer job, must be cleaned on failure
  1025. //
  1026. AddRef();
  1027. hr = m_pSPData->GetThreadPool()->SubmitTimerJob( uRetryCount, // number of times to retry command
  1028. fRetryForever, // retry forever
  1029. dwRetryInterval, // retry interval
  1030. fWaitForever, // wait forever after all enums sent
  1031. dwIdleTimeout, // timeout to wait after command complete
  1032. CModemEndpoint::EnumTimerCallback, // function called when timer event fires
  1033. CModemEndpoint::EnumCompleteWrapper, // function called when timer event expires
  1034. m_pCommandHandle ); // context
  1035. if ( hr != DPN_OK )
  1036. {
  1037. pCommandData->Unlock();
  1038. DPFX(DPFPREP, 0, "Failed to spool enum job on work thread!" );
  1039. DisplayDNError( 0, hr );
  1040. DecRef();
  1041. goto Failure;
  1042. }
  1043. //
  1044. // if everything is a success, we should still have an active command
  1045. //
  1046. DNASSERT( m_Flags.fCommandPending != FALSE );
  1047. DNASSERT( m_pCommandHandle != NULL );
  1048. }
  1049. pCommandData->Unlock();
  1050. break;
  1051. }
  1052. default:
  1053. {
  1054. DNASSERT( FALSE );
  1055. break;
  1056. }
  1057. }
  1058. Exit:
  1059. DPFX(DPFPREP, 6, "(0x%p) Returning", this);
  1060. return;
  1061. Failure:
  1062. DNASSERT( FALSE );
  1063. Close( hr );
  1064. m_pSPData->CloseEndpointHandle( this );
  1065. goto Exit;
  1066. }
  1067. //**********************************************************************
  1068. //**********************************************************************
  1069. // ------------------------------
  1070. // CModemEndpoint::EnumCompleteWrapper - this enum has expired
  1071. //
  1072. // Entry: Error code
  1073. // Context (command pointer)
  1074. //
  1075. // Exit: Nothing
  1076. // ------------------------------
  1077. #undef DPF_MODNAME
  1078. #define DPF_MODNAME "CModemEndpoint::EnumCompleteWrapper"
  1079. void CModemEndpoint::EnumCompleteWrapper( const HRESULT hResult, void *const pContext )
  1080. {
  1081. CModemCommandData *pCommandData;
  1082. DNASSERT( pContext != NULL );
  1083. pCommandData = static_cast<CModemCommandData*>( pContext );
  1084. pCommandData->GetEndpoint()->EnumComplete( hResult );
  1085. pCommandData->GetEndpoint()->DecRef();
  1086. }
  1087. //**********************************************************************
  1088. //**********************************************************************
  1089. // ------------------------------
  1090. // CModemEndpoint::EnumTimerCallback - timed callback to send enum data
  1091. //
  1092. // Entry: Pointer to context
  1093. //
  1094. // Exit: Nothing
  1095. // ------------------------------
  1096. #undef DPF_MODNAME
  1097. #define DPF_MODNAME "CModemEndpoint::EnumTimerCallback"
  1098. void CModemEndpoint::EnumTimerCallback( void *const pContext )
  1099. {
  1100. CModemCommandData *pCommandData;
  1101. CModemEndpoint *pThisObject;
  1102. CModemWriteIOData *pWriteData;
  1103. DNASSERT( pContext != NULL );
  1104. //
  1105. // initialize
  1106. //
  1107. pCommandData = static_cast<CModemCommandData*>( pContext );
  1108. pThisObject = pCommandData->GetEndpoint();
  1109. pWriteData = NULL;
  1110. pThisObject->Lock();
  1111. switch ( pThisObject->m_State )
  1112. {
  1113. //
  1114. // we're enumerating (as expected)
  1115. //
  1116. case ENDPOINT_STATE_ENUM:
  1117. {
  1118. break;
  1119. }
  1120. //
  1121. // this endpoint is disconnecting, bail!
  1122. //
  1123. case ENDPOINT_STATE_DISCONNECTING:
  1124. {
  1125. pThisObject->Unlock();
  1126. goto Exit;
  1127. break;
  1128. }
  1129. //
  1130. // there's a problem
  1131. //
  1132. default:
  1133. {
  1134. DNASSERT( FALSE );
  1135. break;
  1136. }
  1137. }
  1138. pThisObject->Unlock();
  1139. //
  1140. // attempt to get a new IO buffer for this endpoint
  1141. //
  1142. pWriteData = pThisObject->m_pSPData->GetThreadPool()->CreateWriteIOData();
  1143. if ( pWriteData == NULL )
  1144. {
  1145. DPFX(DPFPREP, 0, "Failed to get write data for an enum!" );
  1146. goto Failure;
  1147. }
  1148. //
  1149. // Set all data for the write. Since this is an enum and we
  1150. // don't care about the outgoing data so don't send an indication
  1151. // when it completes.
  1152. //
  1153. DNASSERT( pThisObject->m_Flags.fCommandPending != FALSE );
  1154. DNASSERT( pThisObject->m_pCommandHandle != NULL );
  1155. DNASSERT( pThisObject->GetState() == ENDPOINT_STATE_ENUM );
  1156. pWriteData->m_pBuffers = pThisObject->m_CurrentCommandParameters.EnumQueryData.pBuffers;
  1157. pWriteData->m_uBufferCount = pThisObject->m_CurrentCommandParameters.EnumQueryData.dwBufferCount;
  1158. pWriteData->m_SendCompleteAction = SEND_COMPLETE_ACTION_NONE;
  1159. DNASSERT( pWriteData->m_pCommand != NULL );
  1160. DNASSERT( pWriteData->m_pCommand->GetUserContext() == NULL );
  1161. pWriteData->m_pCommand->SetState( COMMAND_STATE_PENDING );
  1162. DNASSERT( pThisObject->GetDataPort() != NULL );
  1163. pThisObject->m_dwEnumSendIndex++;
  1164. pThisObject->m_dwEnumSendTimes[ pThisObject->m_dwEnumSendIndex & ENUM_RTT_MASK ] = GETTIMESTAMP();
  1165. pThisObject->m_pDataPort->SendEnumQueryData( pWriteData,
  1166. ( pThisObject->m_dwEnumSendIndex & ENUM_RTT_MASK ) );
  1167. Exit:
  1168. return;
  1169. Failure:
  1170. // nothing to clean up at this time
  1171. goto Exit;
  1172. }
  1173. //**********************************************************************
  1174. //**********************************************************************
  1175. // ------------------------------
  1176. // CModemEndpoint::SignalConnect - note connection
  1177. //
  1178. // Entry: Pointer to connect data
  1179. //
  1180. // Exit: Error code
  1181. // ------------------------------
  1182. #undef DPF_MODNAME
  1183. #define DPF_MODNAME "CModemEndpoint::SignalConnect"
  1184. HRESULT CModemEndpoint::SignalConnect( SPIE_CONNECT *const pConnectData )
  1185. {
  1186. HRESULT hr;
  1187. DNASSERT( pConnectData != NULL );
  1188. DNASSERT( pConnectData->hEndpoint == (HANDLE)(DWORD_PTR)GetHandle() );
  1189. AssertCriticalSectionIsTakenByThisThread( &m_Lock, FALSE );
  1190. //
  1191. // initialize
  1192. //
  1193. hr = DPN_OK;
  1194. switch ( m_State )
  1195. {
  1196. //
  1197. // disconnecting, nothing to do
  1198. //
  1199. case ENDPOINT_STATE_DISCONNECTING:
  1200. {
  1201. goto Exit;
  1202. break;
  1203. }
  1204. //
  1205. // we're attempting to connect
  1206. //
  1207. case ENDPOINT_STATE_ATTEMPTING_CONNECT:
  1208. {
  1209. DNASSERT( m_Flags.fConnectIndicated == FALSE );
  1210. hr = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // interface
  1211. SPEV_CONNECT, // event type
  1212. pConnectData // pointer to data
  1213. );
  1214. switch ( hr )
  1215. {
  1216. //
  1217. // connection accepted
  1218. //
  1219. case DPN_OK:
  1220. {
  1221. //
  1222. // note that we're connected
  1223. //
  1224. SetUserEndpointContext( pConnectData->pEndpointContext );
  1225. m_Flags.fConnectIndicated = TRUE;
  1226. m_State = ENDPOINT_STATE_CONNECT_CONNECTED;
  1227. AddRef();
  1228. break;
  1229. }
  1230. //
  1231. // user aborted connection attempt, nothing to do, just pass
  1232. // the result on
  1233. //
  1234. case DPNERR_ABORTED:
  1235. {
  1236. DNASSERT( GetUserEndpointContext() == NULL );
  1237. break;
  1238. }
  1239. default:
  1240. {
  1241. DNASSERT( FALSE );
  1242. break;
  1243. }
  1244. }
  1245. break;
  1246. }
  1247. //
  1248. // states where we shouldn't be getting called
  1249. //
  1250. default:
  1251. {
  1252. DNASSERT( FALSE );
  1253. break;
  1254. }
  1255. }
  1256. Exit:
  1257. return hr;
  1258. }
  1259. //**********************************************************************
  1260. //**********************************************************************
  1261. // ------------------------------
  1262. // CModemEndpoint::SignalDisconnect - note disconnection
  1263. //
  1264. // Entry: Old endpoint handle
  1265. //
  1266. // Exit: Nothing
  1267. // ------------------------------
  1268. #undef DPF_MODNAME
  1269. #define DPF_MODNAME "CModemEndpoint::SignalDisconnect"
  1270. void CModemEndpoint::SignalDisconnect( const DPNHANDLE hOldEndpointHandle )
  1271. {
  1272. HRESULT hr;
  1273. SPIE_DISCONNECT DisconnectData;
  1274. // tell user that we're disconnecting
  1275. DNASSERT( m_Flags.fConnectIndicated != FALSE );
  1276. DBG_CASSERT( sizeof( DisconnectData.hEndpoint ) == sizeof( this ) );
  1277. DisconnectData.hEndpoint = (HANDLE)(DWORD_PTR)hOldEndpointHandle;
  1278. DisconnectData.pEndpointContext = GetUserEndpointContext();
  1279. m_Flags.fConnectIndicated = FALSE;
  1280. DNASSERT( m_pSPData != NULL );
  1281. hr = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // callback interface
  1282. SPEV_DISCONNECT, // event type
  1283. &DisconnectData // pointer to data
  1284. );
  1285. if ( hr != DPN_OK )
  1286. {
  1287. DPFX(DPFPREP, 0, "Problem with SignalDisconnect!" );
  1288. DisplayDNError( 0, hr );
  1289. DNASSERT( FALSE );
  1290. }
  1291. SetDisconnectIndicationHandle( 0 );
  1292. return;
  1293. }
  1294. //**********************************************************************
  1295. //**********************************************************************
  1296. // ------------------------------
  1297. // CModemEndpoint::CleanUpCommand - perform cleanup now that the command on this
  1298. // endpoint is essentially complete. There may be outstanding references,
  1299. // but nobody will be asking the endpoint to do anything else.
  1300. //
  1301. // Entry: Nothing
  1302. //
  1303. // Exit: Nothing
  1304. // ------------------------------
  1305. void CModemEndpoint::CleanUpCommand( void )
  1306. {
  1307. DPFX(DPFPREP, 6, "(0x%p) Enter", this );
  1308. if ( GetDataPort() != NULL )
  1309. {
  1310. DNASSERT( m_pSPData != NULL );
  1311. m_pSPData->UnbindEndpoint( this, GetType() );
  1312. }
  1313. //
  1314. // If we're bailing here it's because the UI didn't complete. There is no
  1315. // adapter guid to return because one may have not been specified. Return
  1316. // a bogus endpoint handle so it can't be queried for addressing data.
  1317. //
  1318. if ( m_Flags.fListenStatusNeedsToBeIndicated != FALSE )
  1319. {
  1320. HRESULT hTempResult;
  1321. SPIE_LISTENSTATUS ListenStatus;
  1322. memset( &ListenStatus, 0x00, sizeof( ListenStatus ) );
  1323. ListenStatus.hCommand = m_pCommandHandle;
  1324. ListenStatus.hEndpoint = 0;
  1325. ListenStatus.hResult = CommandResult();
  1326. memset( &ListenStatus.ListenAdapter, 0x00, sizeof( ListenStatus.ListenAdapter ) );
  1327. ListenStatus.pUserContext = m_pCommandHandle->GetUserContext();
  1328. hTempResult = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // pointer to DPlay callbacks
  1329. SPEV_LISTENSTATUS, // data type
  1330. &ListenStatus // pointer to data
  1331. );
  1332. DNASSERT( hTempResult == DPN_OK );
  1333. m_Flags.fListenStatusNeedsToBeIndicated = FALSE;
  1334. }
  1335. SetHandle( 0 );
  1336. SetState( ENDPOINT_STATE_UNINITIALIZED );
  1337. DPFX(DPFPREP, 6, "(0x%p) Leave", this );
  1338. }
  1339. //**********************************************************************
  1340. //**********************************************************************
  1341. // ------------------------------
  1342. // CModemEndpoint::ProcessEnumData - process received enum data
  1343. //
  1344. // Entry: Pointer to received data
  1345. // Enum RTT index
  1346. //
  1347. // Exit: Nothing
  1348. // ------------------------------
  1349. #undef DPF_MODNAME
  1350. #define DPF_MODNAME "CModemEndpoint::ProcessEnumData"
  1351. void CModemEndpoint::ProcessEnumData( SPRECEIVEDBUFFER *const pReceivedBuffer, const UINT_PTR uEnumRTTIndex )
  1352. {
  1353. DNASSERT( pReceivedBuffer != NULL );
  1354. AssertCriticalSectionIsTakenByThisThread( &m_Lock, FALSE );
  1355. //
  1356. // find out what state the endpoint is in before processing data
  1357. //
  1358. switch ( m_State )
  1359. {
  1360. //
  1361. // we're listening, this is the only way to detect enums
  1362. //
  1363. case ENDPOINT_STATE_LISTENING:
  1364. {
  1365. ENDPOINT_ENUM_QUERY_CONTEXT QueryContext;
  1366. HRESULT hr;
  1367. DNASSERT( m_pCommandHandle != NULL );
  1368. DEBUG_ONLY( memset( &QueryContext, 0x00, sizeof( QueryContext ) ) );
  1369. QueryContext.hEndpoint = (HANDLE)(DWORD_PTR)GetHandle();
  1370. QueryContext.uEnumRTTIndex = uEnumRTTIndex;
  1371. QueryContext.EnumQueryData.pReceivedData = pReceivedBuffer;
  1372. QueryContext.EnumQueryData.pUserContext = m_pCommandHandle->GetUserContext();
  1373. QueryContext.EnumQueryData.pAddressSender = GetRemoteHostDP8Address();
  1374. QueryContext.EnumQueryData.pAddressDevice = GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  1375. //
  1376. // attempt to build a DNAddress for the user, if we can't allocate
  1377. // the memory ignore this enum
  1378. //
  1379. if ( ( QueryContext.EnumQueryData.pAddressSender != NULL ) &&
  1380. ( QueryContext.EnumQueryData.pAddressDevice != NULL ) )
  1381. {
  1382. hr = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // pointer to DirectNet interface
  1383. SPEV_ENUMQUERY, // data type
  1384. &QueryContext.EnumQueryData // pointer to data
  1385. );
  1386. if ( hr != DPN_OK )
  1387. {
  1388. DPFX(DPFPREP, 0, "User returned unexpected error from enum query indication!" );
  1389. DisplayDNError( 0, hr );
  1390. DNASSERT( FALSE );
  1391. }
  1392. }
  1393. if ( QueryContext.EnumQueryData.pAddressSender != NULL )
  1394. {
  1395. IDirectPlay8Address_Release( QueryContext.EnumQueryData.pAddressSender );
  1396. QueryContext.EnumQueryData.pAddressSender = NULL;
  1397. }
  1398. if ( QueryContext.EnumQueryData.pAddressDevice )
  1399. {
  1400. IDirectPlay8Address_Release( QueryContext.EnumQueryData.pAddressDevice );
  1401. QueryContext.EnumQueryData.pAddressDevice = NULL;
  1402. }
  1403. break;
  1404. }
  1405. //
  1406. // we're disconnecting, ignore this message
  1407. //
  1408. case ENDPOINT_STATE_ATTEMPTING_LISTEN:
  1409. case ENDPOINT_STATE_DISCONNECTING:
  1410. {
  1411. break;
  1412. }
  1413. //
  1414. // other state
  1415. //
  1416. default:
  1417. {
  1418. DNASSERT( FALSE );
  1419. break;
  1420. }
  1421. }
  1422. }
  1423. //**********************************************************************
  1424. //**********************************************************************
  1425. // ------------------------------
  1426. // CModemEndpoint::ProcessEnumResponseData - process received enum response data
  1427. //
  1428. // Entry: Pointer to received data
  1429. // Pointer to address of sender
  1430. //
  1431. // Exit: Nothing
  1432. //
  1433. // Note: This function assumes that the endpoint has been locked.
  1434. // ------------------------------
  1435. #undef DPF_MODNAME
  1436. #define DPF_MODNAME "CModemEndpoint::ProcessEnumResponseData"
  1437. void CModemEndpoint::ProcessEnumResponseData( SPRECEIVEDBUFFER *const pReceivedBuffer, const UINT_PTR uRTTIndex )
  1438. {
  1439. DNASSERT( pReceivedBuffer != NULL );
  1440. AssertCriticalSectionIsTakenByThisThread( &m_Lock, FALSE );
  1441. //
  1442. // find out what state the endpoint is in before processing data
  1443. //
  1444. switch ( m_State )
  1445. {
  1446. //
  1447. // endpoint is enuming, it can handle enum responses
  1448. //
  1449. case ENDPOINT_STATE_ENUM:
  1450. {
  1451. SPIE_QUERYRESPONSE QueryResponseData;
  1452. HRESULT hr;
  1453. DNASSERT( m_pCommandHandle != NULL );
  1454. DEBUG_ONLY( memset( &QueryResponseData, 0x00, sizeof( QueryResponseData ) ) );
  1455. QueryResponseData.pReceivedData = pReceivedBuffer;
  1456. QueryResponseData.dwRoundTripTime = GETTIMESTAMP() - m_dwEnumSendTimes[ uRTTIndex ];
  1457. QueryResponseData.pUserContext = m_pCommandHandle->GetUserContext();
  1458. //
  1459. // attempt to build a DNAddress for the user, if we can't allocate
  1460. // the memory ignore this enum
  1461. //
  1462. QueryResponseData.pAddressSender = GetRemoteHostDP8Address();
  1463. QueryResponseData.pAddressDevice = GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  1464. if ( ( QueryResponseData.pAddressSender != NULL ) &&
  1465. ( QueryResponseData.pAddressDevice != NULL ) )
  1466. {
  1467. hr = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // pointer to DirectNet interface
  1468. SPEV_QUERYRESPONSE, // data type
  1469. &QueryResponseData // pointer to data
  1470. );
  1471. if ( hr != DPN_OK )
  1472. {
  1473. DPFX(DPFPREP, 0, "User returned unknown error when indicating query response!" );
  1474. DisplayDNError( 0, hr );
  1475. DNASSERT( FALSE );
  1476. }
  1477. }
  1478. if ( QueryResponseData.pAddressSender != NULL )
  1479. {
  1480. IDirectPlay8Address_Release( QueryResponseData.pAddressSender );
  1481. QueryResponseData.pAddressSender = NULL;
  1482. }
  1483. if ( QueryResponseData.pAddressDevice != NULL )
  1484. {
  1485. IDirectPlay8Address_Release( QueryResponseData.pAddressDevice );
  1486. QueryResponseData.pAddressDevice = NULL;
  1487. }
  1488. break;
  1489. }
  1490. //
  1491. // endpoint is disconnecting, ignore data
  1492. //
  1493. case ENDPOINT_STATE_DISCONNECTING:
  1494. {
  1495. break;
  1496. }
  1497. //
  1498. // other state
  1499. //
  1500. default:
  1501. {
  1502. DNASSERT( FALSE );
  1503. break;
  1504. }
  1505. }
  1506. }
  1507. //**********************************************************************
  1508. //**********************************************************************
  1509. // ------------------------------
  1510. // CModemEndpoint::ProcessUserData - process received user data
  1511. //
  1512. // Entry: Pointer to received data
  1513. //
  1514. // Exit: Nothing
  1515. // ------------------------------
  1516. #undef DPF_MODNAME
  1517. #define DPF_MODNAME "CModemEndpoint::ProcessUserData"
  1518. void CModemEndpoint::ProcessUserData( CModemReadIOData *const pReadData )
  1519. {
  1520. DNASSERT( pReadData != NULL );
  1521. switch ( m_State )
  1522. {
  1523. //
  1524. // endpoint is connected
  1525. //
  1526. case ENDPOINT_STATE_CONNECT_CONNECTED:
  1527. {
  1528. HRESULT hr;
  1529. SPIE_DATA UserData;
  1530. //
  1531. // it's possible that the user wants to keep the data, add a
  1532. // reference to keep it from going away
  1533. //
  1534. pReadData->AddRef();
  1535. //
  1536. // we're connected, report the user data
  1537. //
  1538. DEBUG_ONLY( memset( &UserData, 0x00, sizeof( UserData ) ) );
  1539. DBG_CASSERT( sizeof( this ) == sizeof( HANDLE ) );
  1540. UserData.hEndpoint = (HANDLE)(DWORD_PTR)GetHandle();
  1541. UserData.pEndpointContext = GetUserEndpointContext();
  1542. UserData.pReceivedData = &pReadData->m_SPReceivedBuffer;
  1543. DPFX(DPFPREP, 2, "Endpoint 0x%p indicating SPEV_DATA 0x%p to interface 0x%p.",
  1544. this, &UserData, m_pSPData->DP8SPCallbackInterface());
  1545. hr = IDP8SPCallback_IndicateEvent( m_pSPData->DP8SPCallbackInterface(), // pointer to interface
  1546. SPEV_DATA, // user data was received
  1547. &UserData // pointer to data
  1548. );
  1549. DPFX(DPFPREP, 2, "Endpoint 0x%p returning from SPEV_DATA [0x%lx].", this, hr);
  1550. switch ( hr )
  1551. {
  1552. //
  1553. // user didn't keep the data, remove the reference added above
  1554. //
  1555. case DPN_OK:
  1556. {
  1557. DNASSERT( pReadData != NULL );
  1558. pReadData->DecRef();
  1559. break;
  1560. }
  1561. //
  1562. // The user kept the data buffer, they will return it later.
  1563. // Leave the reference to prevent this buffer from being returned
  1564. // to the pool.
  1565. //
  1566. case DPNERR_PENDING:
  1567. {
  1568. break;
  1569. }
  1570. //
  1571. // Unknown return. Remove the reference added above.
  1572. //
  1573. default:
  1574. {
  1575. DNASSERT( pReadData != NULL );
  1576. pReadData->DecRef();
  1577. DPFX(DPFPREP, 0, "User returned unknown error when indicating user data!" );
  1578. DisplayDNError( 0, hr );
  1579. DNASSERT( FALSE );
  1580. break;
  1581. }
  1582. }
  1583. break;
  1584. }
  1585. //
  1586. // Endpoint disconnecting, or we haven't finished acknowledging a connect,
  1587. // ignore data.
  1588. //
  1589. case ENDPOINT_STATE_ATTEMPTING_CONNECT:
  1590. case ENDPOINT_STATE_DISCONNECTING:
  1591. {
  1592. DPFX(DPFPREP, 3, "Endpoint 0x%p ignoring data, state = %u.", this, m_State );
  1593. break;
  1594. }
  1595. //
  1596. // other state
  1597. //
  1598. default:
  1599. {
  1600. DNASSERT( FALSE );
  1601. break;
  1602. }
  1603. }
  1604. return;
  1605. }
  1606. //**********************************************************************
  1607. //**********************************************************************
  1608. // ------------------------------
  1609. // CModemEndpoint::ProcessUserDataOnListen - process received user data on a listen
  1610. // port that may result in a new connection
  1611. //
  1612. // Entry: Pointer to received data
  1613. //
  1614. // Exit: Nothing
  1615. //
  1616. // Note: This function assumes that this endpoint has been locked.
  1617. // ------------------------------
  1618. #undef DPF_MODNAME
  1619. #define DPF_MODNAME "CModemEndpoint::ProcessUserDataOnListen"
  1620. void CModemEndpoint::ProcessUserDataOnListen( CModemReadIOData *const pReadData )
  1621. {
  1622. HRESULT hr;
  1623. CModemEndpoint *pNewEndpoint;
  1624. SPIE_CONNECT ConnectData;
  1625. BOOL fEndpointBound;
  1626. DNASSERT( pReadData != NULL );
  1627. AssertCriticalSectionIsTakenByThisThread( &m_Lock, FALSE );
  1628. DPFX(DPFPREP, 8, "Reporting connect on a listen!" );
  1629. //
  1630. // initialize
  1631. //
  1632. pNewEndpoint = NULL;
  1633. fEndpointBound = FALSE;
  1634. switch ( m_State )
  1635. {
  1636. //
  1637. // this endpoint is still listening
  1638. //
  1639. case ENDPOINT_STATE_LISTENING:
  1640. {
  1641. break;
  1642. }
  1643. //
  1644. // we're unable to process this user data, exti
  1645. //
  1646. case ENDPOINT_STATE_DISCONNECTING:
  1647. {
  1648. goto Exit;
  1649. break;
  1650. }
  1651. //
  1652. // other state
  1653. //
  1654. default:
  1655. {
  1656. DNASSERT( FALSE );
  1657. break;
  1658. }
  1659. }
  1660. //
  1661. // get a new endpoint from the pool
  1662. //
  1663. pNewEndpoint = m_pSPData->GetNewEndpoint();
  1664. if ( pNewEndpoint == NULL )
  1665. {
  1666. hr = DPNERR_OUTOFMEMORY;
  1667. DPFX(DPFPREP, 0, "Could not create new endpoint for new connection on listen!" );
  1668. goto Failure;
  1669. }
  1670. //
  1671. // We are adding this endpoint to the hash table and indicating it up
  1672. // to the user, so it's possible that it could be disconnected (and thus
  1673. // removed from the table) while we're still in here. We need to
  1674. // hold an additional reference for the duration of this function to
  1675. // prevent it from disappearing while we're still indicating data.
  1676. //
  1677. pNewEndpoint->AddCommandRef();
  1678. //
  1679. // open this endpoint as a new connection, since the new endpoint
  1680. // is related to 'this' endpoint, copy local information
  1681. //
  1682. hr = pNewEndpoint->OpenOnListen( this );
  1683. if ( hr != DPN_OK )
  1684. {
  1685. DPFX(DPFPREP, 0, "Problem initializing new endpoint when indicating connect on listen!" );
  1686. DisplayDNError( 0, hr );
  1687. goto Failure;
  1688. }
  1689. //
  1690. // Attempt to bind this endpoint to the socket port. This will reserve our
  1691. // slot before we notify the user. If another message is attempting this same
  1692. // procedure we won't be able to add this endpoint and we'll bail on the message.
  1693. //
  1694. DNASSERT( hr == DPN_OK );
  1695. hr = m_pSPData->BindEndpoint( pNewEndpoint, pNewEndpoint->GetDeviceID(), pNewEndpoint->GetDeviceContext() );
  1696. if ( hr != DPN_OK )
  1697. {
  1698. DPFX(DPFPREP, 0, "Failed to bind endpoint to dataport on new connect from listen!" );
  1699. DisplayDNError( 0, hr );
  1700. goto Failure;
  1701. }
  1702. fEndpointBound = TRUE;
  1703. //
  1704. // Indicate connect on this endpoint.
  1705. //
  1706. DEBUG_ONLY( memset( &ConnectData, 0x00, sizeof( ConnectData ) ) );
  1707. DBG_CASSERT( sizeof( ConnectData.hEndpoint ) == sizeof( pNewEndpoint ) );
  1708. ConnectData.hEndpoint = (HANDLE)(DWORD_PTR)pNewEndpoint->GetHandle();
  1709. DNASSERT( m_Flags.fCommandPending != FALSE );
  1710. DNASSERT( m_pCommandHandle != NULL );
  1711. ConnectData.pCommandContext = m_CurrentCommandParameters.ListenData.pvContext;
  1712. DNASSERT( pNewEndpoint->GetUserEndpointContext() == NULL );
  1713. hr = pNewEndpoint->SignalConnect( &ConnectData );
  1714. switch ( hr )
  1715. {
  1716. //
  1717. // user accepted new connection
  1718. //
  1719. case DPN_OK:
  1720. {
  1721. //
  1722. // fall through to code below
  1723. //
  1724. break;
  1725. }
  1726. //
  1727. // user refused new connection
  1728. //
  1729. case DPNERR_ABORTED:
  1730. {
  1731. DNASSERT( pNewEndpoint->GetUserEndpointContext() == NULL );
  1732. DPFX(DPFPREP, 8, "User refused new connection!" );
  1733. goto Failure;
  1734. break;
  1735. }
  1736. //
  1737. // other
  1738. //
  1739. default:
  1740. {
  1741. DPFX(DPFPREP, 0, "Unknown return when indicating connect event on new connect from listen!" );
  1742. DisplayDNError( 0, hr );
  1743. DNASSERT( FALSE );
  1744. break;
  1745. }
  1746. }
  1747. //
  1748. // note that a connection has been establised and send the data received
  1749. // through this new endpoint
  1750. //
  1751. pNewEndpoint->ProcessUserData( pReadData );
  1752. //
  1753. // Remove the reference we added just after creating the endpoint.
  1754. //
  1755. pNewEndpoint->DecCommandRef();
  1756. pNewEndpoint = NULL;
  1757. Exit:
  1758. return;
  1759. Failure:
  1760. if ( pNewEndpoint != NULL )
  1761. {
  1762. if ( fEndpointBound != FALSE )
  1763. {
  1764. m_pSPData->UnbindEndpoint( pNewEndpoint, ENDPOINT_TYPE_CONNECT );
  1765. fEndpointBound = FALSE;
  1766. }
  1767. //
  1768. // closing endpoint decrements reference count and may return it to the pool
  1769. //
  1770. pNewEndpoint->Close( hr );
  1771. m_pSPData->CloseEndpointHandle( pNewEndpoint );
  1772. pNewEndpoint->DecCommandRef(); // remove reference added just after creating endpoint
  1773. pNewEndpoint = NULL;
  1774. }
  1775. goto Exit;
  1776. }
  1777. //**********************************************************************
  1778. //**********************************************************************
  1779. // ------------------------------
  1780. // CModemEndpoint::SettingsDialogComplete - dialog has completed
  1781. //
  1782. // Entry: Error code for dialog
  1783. //
  1784. // Exit: Nothing
  1785. // ------------------------------
  1786. void CModemEndpoint::SettingsDialogComplete( const HRESULT hDialogResult )
  1787. {
  1788. HRESULT hr;
  1789. //
  1790. // initialize
  1791. //
  1792. hr = hDialogResult;
  1793. //
  1794. // since the dialog is exiting, clear our handle to the dialog
  1795. //
  1796. m_hActiveDialogHandle = NULL;
  1797. //
  1798. // dialog failed, fail the user's command
  1799. //
  1800. if ( hr != DPN_OK )
  1801. {
  1802. if ( hr != DPNERR_USERCANCEL)
  1803. {
  1804. DPFX(DPFPREP, 0, "Failing dialog (err = 0x%lx)!", hr );
  1805. }
  1806. goto Failure;
  1807. }
  1808. AddRef();
  1809. //
  1810. // the remote machine address has been adjusted, finish the command
  1811. //
  1812. switch ( GetType() )
  1813. {
  1814. case ENDPOINT_TYPE_ENUM:
  1815. {
  1816. hr = m_pSPData->GetThreadPool()->SubmitDelayedCommand( EnumQueryJobCallback,
  1817. CancelEnumQueryJobCallback,
  1818. this );
  1819. if ( hr != DPN_OK )
  1820. {
  1821. DecRef();
  1822. DPFX(DPFPREP, 0, "Failed to set delayed enum query!" );
  1823. DisplayDNError( 0, hr );
  1824. goto Failure;
  1825. }
  1826. break;
  1827. }
  1828. case ENDPOINT_TYPE_CONNECT:
  1829. {
  1830. hr = m_pSPData->GetThreadPool()->SubmitDelayedCommand( ConnectJobCallback,
  1831. CancelConnectJobCallback,
  1832. this );
  1833. if ( hr != DPN_OK )
  1834. {
  1835. DecRef();
  1836. DPFX(DPFPREP, 0, "Failed to set delayed connect!" );
  1837. DisplayDNError( 0, hr );
  1838. goto Failure;
  1839. }
  1840. break;
  1841. }
  1842. case ENDPOINT_TYPE_LISTEN:
  1843. {
  1844. hr = m_pSPData->GetThreadPool()->SubmitDelayedCommand( ListenJobCallback,
  1845. CancelListenJobCallback,
  1846. this );
  1847. if ( hr != DPN_OK )
  1848. {
  1849. DecRef();
  1850. DPFX(DPFPREP, 0, "Failed to set delayed listen!" );
  1851. DisplayDNError( 0, hr );
  1852. goto Failure;
  1853. }
  1854. break;
  1855. }
  1856. //
  1857. // unknown!
  1858. //
  1859. default:
  1860. {
  1861. DNASSERT( FALSE );
  1862. hr = DPNERR_GENERIC;
  1863. goto Failure;
  1864. break;
  1865. }
  1866. }
  1867. Exit:
  1868. DecRef();
  1869. return;
  1870. Failure:
  1871. //
  1872. // close this endpoint
  1873. //
  1874. Close( hr );
  1875. m_pSPData->CloseEndpointHandle( this );
  1876. goto Exit;
  1877. }
  1878. //**********************************************************************
  1879. //**********************************************************************
  1880. // ------------------------------
  1881. // CModemEndpoint::CompletePendingCommand - complete an internal commad
  1882. //
  1883. // Entry: Error code returned for command
  1884. //
  1885. // Exit: Nothing
  1886. // ------------------------------
  1887. #undef DPF_MODNAME
  1888. #define DPF_MODNAME "CModemEndpoint::CompletePendingCommand"
  1889. void CModemEndpoint::CompletePendingCommand( const HRESULT hr )
  1890. {
  1891. DNASSERT( m_Flags.fCommandPending != FALSE );
  1892. DNASSERT( m_pCommandHandle != NULL );
  1893. DNASSERT( m_pSPData != NULL );
  1894. DPFX(DPFPREP, 5, "Endpoint 0x%p completing command handle 0x%p (result = 0x%lx, user context 0x%p) to interface 0x%p.",
  1895. this, m_pCommandHandle, hr,
  1896. m_pCommandHandle->GetUserContext(),
  1897. m_pSPData->DP8SPCallbackInterface());
  1898. IDP8SPCallback_CommandComplete( m_pSPData->DP8SPCallbackInterface(), // pointer to SP callbacks
  1899. m_pCommandHandle, // command handle
  1900. hr, // return
  1901. m_pCommandHandle->GetUserContext() // user cookie
  1902. );
  1903. DPFX(DPFPREP, 5, "Endpoint 0x%p returning from command complete [0x%lx].", this, hr);
  1904. m_Flags.fCommandPending = FALSE;
  1905. m_pCommandHandle->DecRef();
  1906. m_pCommandHandle = NULL;
  1907. }
  1908. //**********************************************************************
  1909. //**********************************************************************
  1910. // ------------------------------
  1911. // CModemEndpoint::GetLinkDirection - get link direction for this endpoint
  1912. //
  1913. // Entry: Nothing
  1914. //
  1915. // Exit: Link direction
  1916. // ------------------------------
  1917. #undef DPF_MODNAME
  1918. #define DPF_MODNAME "CModemEndpoint::GetLinkDirection"
  1919. LINK_DIRECTION CModemEndpoint::GetLinkDirection( void ) const
  1920. {
  1921. LINK_DIRECTION LinkDirection;
  1922. LinkDirection = LINK_DIRECTION_OUTGOING;
  1923. switch ( GetType() )
  1924. {
  1925. case ENDPOINT_TYPE_LISTEN:
  1926. {
  1927. LinkDirection = LINK_DIRECTION_INCOMING;
  1928. break;
  1929. }
  1930. //
  1931. // connect and enum are outgoing
  1932. //
  1933. case ENDPOINT_TYPE_CONNECT:
  1934. case ENDPOINT_TYPE_ENUM:
  1935. {
  1936. DNASSERT( LinkDirection == LINK_DIRECTION_OUTGOING );
  1937. break;
  1938. }
  1939. //
  1940. // shouldn't be here
  1941. //
  1942. default:
  1943. {
  1944. DNASSERT( FALSE );
  1945. break;
  1946. }
  1947. }
  1948. return LinkDirection;
  1949. }
  1950. //**********************************************************************
  1951. //**********************************************************************
  1952. // ------------------------------
  1953. // CModemEndpoint::ReturnSelfToPool - return this item to the pool
  1954. //
  1955. // Entry: Nothing
  1956. //
  1957. // Exit: Nothing
  1958. // ------------------------------
  1959. #undef DPF_MODNAME
  1960. #define DPF_MODNAME "CModemEndpoint::ReturnSelfToPool"
  1961. void CModemEndpoint::ReturnSelfToPool( void )
  1962. {
  1963. if ( m_Flags.fCommandPending != FALSE )
  1964. {
  1965. CompletePendingCommand( PendingCommandResult() );
  1966. }
  1967. if ( m_Flags.fConnectIndicated != FALSE )
  1968. {
  1969. SignalDisconnect( GetDisconnectIndicationHandle() );
  1970. }
  1971. DNASSERT( m_Flags.fConnectIndicated == FALSE );
  1972. memset( m_PhoneNumber, 0x00, sizeof( m_PhoneNumber ) );
  1973. SetUserEndpointContext( NULL );
  1974. if (m_fModem)
  1975. {
  1976. g_ModemEndpointPool.Release( this );
  1977. }
  1978. else
  1979. {
  1980. g_ComEndpointPool.Release( this );
  1981. }
  1982. }
  1983. //**********************************************************************
  1984. //**********************************************************************
  1985. // ------------------------------
  1986. // CModemEndpoint::PoolAllocFunction - function called when item is created in pool
  1987. //
  1988. // Entry: Pointer to pool context
  1989. //
  1990. // Exit: Boolean indicating success
  1991. // TRUE = success
  1992. // FALSE = failure
  1993. // ------------------------------
  1994. #undef DPF_MODNAME
  1995. #define DPF_MODNAME "CModemEndpoint::PoolAllocFunction"
  1996. BOOL CModemEndpoint::PoolAllocFunction( void* pvItem, void* pvContext )
  1997. {
  1998. CModemEndpoint* pEndpoint = (CModemEndpoint*)pvItem;
  1999. const ENDPOINT_POOL_CONTEXT* pEPContext = (ENDPOINT_POOL_CONTEXT*)pvContext;
  2000. DNASSERT( pEPContext != NULL );
  2001. pEndpoint->m_fModem = pEPContext->fModem;
  2002. pEndpoint->m_Sig[0] = 'M';
  2003. pEndpoint->m_Sig[1] = 'O';
  2004. pEndpoint->m_Sig[2] = 'E';
  2005. pEndpoint->m_Sig[3] = 'P';
  2006. memset( &pEndpoint->m_PhoneNumber, 0x00, sizeof( pEndpoint->m_PhoneNumber ) );
  2007. pEndpoint->m_dwDeviceID = INVALID_DEVICE_ID;
  2008. //
  2009. // initialize base object
  2010. //
  2011. pEndpoint->m_pSPData = NULL;
  2012. pEndpoint->m_pCommandHandle = NULL;
  2013. pEndpoint->m_Handle = 0;
  2014. pEndpoint->m_State = ENDPOINT_STATE_UNINITIALIZED;
  2015. pEndpoint->m_lCommandRefCount = 0;
  2016. pEndpoint->m_EndpointType = ENDPOINT_TYPE_UNKNOWN;
  2017. pEndpoint->m_pDataPort = NULL;
  2018. pEndpoint->m_hPendingCommandResult = DPNERR_GENERIC;
  2019. pEndpoint->m_hDisconnectIndicationHandle = 0;
  2020. pEndpoint->m_pUserEndpointContext = NULL;
  2021. pEndpoint->m_hActiveDialogHandle = NULL;
  2022. pEndpoint->m_dwEnumSendIndex = 0;
  2023. pEndpoint->m_iRefCount = 0;
  2024. pEndpoint->m_Flags.fConnectIndicated = FALSE;
  2025. pEndpoint->m_Flags.fCommandPending = FALSE;
  2026. pEndpoint->m_Flags.fListenStatusNeedsToBeIndicated = FALSE;
  2027. pEndpoint->m_ComPortData.Reset();
  2028. memset( &pEndpoint->m_CurrentCommandParameters, 0x00, sizeof( pEndpoint->m_CurrentCommandParameters ) );
  2029. memset( &pEndpoint->m_Flags, 0x00, sizeof( pEndpoint->m_Flags ) );
  2030. if ( DNInitializeCriticalSection( &pEndpoint->m_Lock ) == FALSE )
  2031. {
  2032. DPFX(DPFPREP, 0, "Failed to initialize endpoint lock!" );
  2033. return FALSE;
  2034. }
  2035. DebugSetCriticalSectionRecursionCount( &pEndpoint->m_Lock, 0 );
  2036. DebugSetCriticalSectionGroup( &pEndpoint->m_Lock, &g_blDPNModemCritSecsHeld ); // separate dpnmodem CSes from the rest of DPlay's CSes
  2037. pEndpoint->m_Flags.fInitialized = TRUE;
  2038. return TRUE;
  2039. }
  2040. //**********************************************************************
  2041. //**********************************************************************
  2042. // ------------------------------
  2043. // CModemEndpoint::PoolInitFunction - function called when item is created in pool
  2044. //
  2045. // Entry: Pointer to pool context
  2046. //
  2047. // Exit: Boolean indicating success
  2048. // TRUE = success
  2049. // FALSE = failure
  2050. // ------------------------------
  2051. #undef DPF_MODNAME
  2052. #define DPF_MODNAME "CModemEndpoint::PoolInitFunction"
  2053. void CModemEndpoint::PoolInitFunction( void* pvItem, void* pvContext )
  2054. {
  2055. CModemEndpoint* pEndpoint = (CModemEndpoint*)pvItem;
  2056. ENDPOINT_POOL_CONTEXT* pEPContext = (ENDPOINT_POOL_CONTEXT*)pvContext;
  2057. DNASSERT( pEPContext != NULL );
  2058. DNASSERT( pEndpoint->m_pSPData == NULL );
  2059. DNASSERT( pEndpoint->GetState() == ENDPOINT_STATE_UNINITIALIZED );
  2060. DNASSERT( pEndpoint->GetType() == ENDPOINT_TYPE_UNKNOWN );
  2061. DNASSERT( pEndpoint->GetDeviceID() == INVALID_DEVICE_ID );
  2062. DNASSERT( pEndpoint->GetDisconnectIndicationHandle() == 0 );
  2063. pEndpoint->m_pSPData = pEPContext->pSPData;
  2064. pEndpoint->m_pSPData->ObjectAddRef();
  2065. //
  2066. // set reasonable defaults
  2067. //
  2068. pEndpoint->m_ComPortData.SetBaudRate( CBR_57600 );
  2069. pEndpoint->m_ComPortData.SetStopBits( ONESTOPBIT );
  2070. pEndpoint->m_ComPortData.SetParity( NOPARITY );
  2071. pEndpoint->m_ComPortData.SetFlowControl( FLOW_RTSDTR );
  2072. DNASSERT(pEndpoint->m_iRefCount == 0);
  2073. pEndpoint->m_iRefCount = 1;
  2074. }
  2075. //**********************************************************************
  2076. //**********************************************************************
  2077. // ------------------------------
  2078. // CModemEndpoint::PoolReleaseFunction - function called when returned to pool
  2079. //
  2080. // Entry: Nothing
  2081. //
  2082. // Exit: Nothing
  2083. // ------------------------------
  2084. #undef DPF_MODNAME
  2085. #define DPF_MODNAME "CModemEndpoint::PoolReleaseFunction"
  2086. void CModemEndpoint::PoolReleaseFunction( void* pvItem )
  2087. {
  2088. CModemSPData *pSPData;
  2089. CModemEndpoint* pEndpoint = (CModemEndpoint*)pvItem;
  2090. DNASSERT(pEndpoint->m_iRefCount == 0);
  2091. //
  2092. // deinitialize base object
  2093. //
  2094. DNASSERT( pEndpoint->m_pSPData != NULL );
  2095. pSPData = pEndpoint->m_pSPData;
  2096. pEndpoint->m_pSPData = NULL;
  2097. pEndpoint->m_ComPortData.Reset();
  2098. pEndpoint->SetType( ENDPOINT_TYPE_UNKNOWN );
  2099. pEndpoint->SetState( ENDPOINT_STATE_UNINITIALIZED );
  2100. pEndpoint->SetDeviceID( INVALID_DEVICE_ID );
  2101. DNASSERT( pEndpoint->GetDisconnectIndicationHandle() == 0 );
  2102. DNASSERT( pEndpoint->m_Flags.fConnectIndicated == FALSE );
  2103. DNASSERT( pEndpoint->m_Flags.fCommandPending == FALSE );
  2104. DNASSERT( pEndpoint->m_Flags.fListenStatusNeedsToBeIndicated == FALSE );
  2105. DNASSERT( pEndpoint->m_pCommandHandle == NULL );
  2106. DNASSERT( pEndpoint->m_hActiveDialogHandle == NULL );
  2107. pSPData->ObjectDecRef();
  2108. }
  2109. //**********************************************************************
  2110. //**********************************************************************
  2111. // ------------------------------
  2112. // CModemEndpoint::PoolDeallocFunction - function called when deleted from pool
  2113. //
  2114. // Entry: Nothing
  2115. //
  2116. // Exit: Nothing
  2117. // ------------------------------
  2118. #undef DPF_MODNAME
  2119. #define DPF_MODNAME "CModemEndpoint::PoolDeallocFunction"
  2120. void CModemEndpoint::PoolDeallocFunction( void* pvItem )
  2121. {
  2122. CModemEndpoint* pEndpoint = (CModemEndpoint*)pvItem;
  2123. DNASSERT( pEndpoint->m_Flags.fInitialized != FALSE );
  2124. DNDeleteCriticalSection( &pEndpoint->m_Lock );
  2125. pEndpoint->m_pSPData = NULL;
  2126. DNASSERT( pEndpoint->m_pCommandHandle == NULL );
  2127. DNASSERT( pEndpoint->m_Flags.fCommandPending == FALSE );
  2128. pEndpoint->SetState( ENDPOINT_STATE_UNINITIALIZED );
  2129. pEndpoint->SetType( ENDPOINT_TYPE_UNKNOWN );
  2130. DNASSERT( pEndpoint->GetDataPort() == NULL );
  2131. pEndpoint->m_Flags.fInitialized = FALSE;
  2132. DNASSERT( pEndpoint->GetDeviceID() == INVALID_DEVICE_ID );
  2133. DNASSERT( pEndpoint->GetDisconnectIndicationHandle() == 0 );
  2134. DNASSERT( pEndpoint->m_pSPData == NULL );
  2135. DNASSERT( pEndpoint->m_Flags.fInitialized == FALSE );
  2136. DNASSERT( pEndpoint->m_Flags.fConnectIndicated == FALSE );
  2137. DNASSERT( pEndpoint->m_Flags.fCommandPending == FALSE );
  2138. DNASSERT( pEndpoint->m_Flags.fListenStatusNeedsToBeIndicated == FALSE );
  2139. DNASSERT( pEndpoint->m_pCommandHandle == NULL );
  2140. DNASSERT( pEndpoint->m_Handle == 0 );
  2141. DNASSERT( pEndpoint->m_State == ENDPOINT_STATE_UNINITIALIZED );
  2142. DNASSERT( pEndpoint->m_lCommandRefCount == 0 );
  2143. DNASSERT( pEndpoint->m_EndpointType == ENDPOINT_TYPE_UNKNOWN );
  2144. DNASSERT( pEndpoint->m_pDataPort == NULL );
  2145. // DNASSERT( pEndpoint->m_hPendingCommandResult == DPNERR_GENERIC ); MASONB: NOTE: PreFAST caught a bug here because == was =, but it now asserts. Check intent.
  2146. DNASSERT( pEndpoint->m_pUserEndpointContext == NULL );
  2147. DNASSERT( pEndpoint->m_hActiveDialogHandle == NULL );
  2148. DNASSERT( pEndpoint->m_dwEnumSendIndex == 0 );
  2149. DNASSERT( pEndpoint->m_iRefCount == 0 );
  2150. }
  2151. //**********************************************************************
  2152. //**********************************************************************
  2153. // ------------------------------
  2154. // CModemEndpoint::Open - open communications with endpoint
  2155. //
  2156. // Entry: Pointer to host address
  2157. // Pointer to adapter address
  2158. // Link direction
  2159. // Endpoint type
  2160. //
  2161. // Exit: Error code
  2162. // ------------------------------
  2163. #undef DPF_MODNAME
  2164. #define DPF_MODNAME "CModemEndpoint::Open"
  2165. HRESULT CModemEndpoint::Open( IDirectPlay8Address *const pHostAddress,
  2166. IDirectPlay8Address *const pAdapterAddress,
  2167. const LINK_DIRECTION LinkDirection,
  2168. const ENDPOINT_TYPE EndpointType )
  2169. {
  2170. HRESULT hr;
  2171. HRESULT hDeviceResult;
  2172. GUID ModemDeviceGuid;
  2173. DNASSERT( pAdapterAddress != NULL );
  2174. DNASSERT( ( LinkDirection == LINK_DIRECTION_INCOMING ) ||
  2175. ( LinkDirection == LINK_DIRECTION_OUTGOING ) );
  2176. DNASSERT( ( EndpointType == ENDPOINT_TYPE_CONNECT ) ||
  2177. ( EndpointType == ENDPOINT_TYPE_ENUM ) ||
  2178. ( EndpointType == ENDPOINT_TYPE_LISTEN ) ||
  2179. ( EndpointType == ENDPOINT_TYPE_CONNECT_ON_LISTEN ) );
  2180. DNASSERT( ( ( pHostAddress != NULL ) && ( LinkDirection == LINK_DIRECTION_OUTGOING ) ) ||
  2181. ( ( pHostAddress == NULL ) && ( LinkDirection == LINK_DIRECTION_INCOMING ) ) );
  2182. //
  2183. // initialize
  2184. //
  2185. hr = DPN_OK;
  2186. if (m_fModem)
  2187. {
  2188. DNASSERT( lstrlen( m_PhoneNumber ) == 0 );
  2189. DNASSERT( GetDeviceID() == INVALID_DEVICE_ID );
  2190. hDeviceResult = IDirectPlay8Address_GetDevice( pAdapterAddress, &ModemDeviceGuid );
  2191. switch ( hDeviceResult )
  2192. {
  2193. case DPN_OK:
  2194. {
  2195. SetDeviceID( GuidToDeviceID( &ModemDeviceGuid, &g_ModemSPEncryptionGuid ) );
  2196. break;
  2197. }
  2198. case DPNERR_DOESNOTEXIST:
  2199. {
  2200. DNASSERT( GetDeviceID() == INVALID_DEVICE_ID );
  2201. break;
  2202. }
  2203. default:
  2204. {
  2205. hr = hDeviceResult;
  2206. DPFX(DPFPREP, 0, "Failed to get modem device!" );
  2207. DisplayDNError( 0, hr);
  2208. goto Failure;
  2209. }
  2210. }
  2211. if ( LinkDirection == LINK_DIRECTION_OUTGOING )
  2212. {
  2213. HRESULT hPhoneNumberResult;
  2214. DWORD dwWCHARPhoneNumberSize;
  2215. DWORD dwDataType;
  2216. WCHAR PhoneNumber[ LENGTHOF( m_PhoneNumber ) ];
  2217. dwWCHARPhoneNumberSize = sizeof( PhoneNumber );
  2218. hPhoneNumberResult = IDirectPlay8Address_GetComponentByName( pHostAddress,
  2219. DPNA_KEY_PHONENUMBER,
  2220. PhoneNumber,
  2221. &dwWCHARPhoneNumberSize,
  2222. &dwDataType );
  2223. switch ( hPhoneNumberResult )
  2224. {
  2225. case DPN_OK:
  2226. {
  2227. #ifdef UNICODE
  2228. lstrcpy(m_PhoneNumber, PhoneNumber);
  2229. #else
  2230. DWORD dwASCIIPhoneNumberSize;
  2231. //
  2232. // can't use the STR_ functions to convert ANSI to WIDE phone
  2233. // numbers because phone numbers with symbols: "9,", "*70" are
  2234. // interpreted as already being WCHAR when they're not!
  2235. //
  2236. dwASCIIPhoneNumberSize = sizeof( m_PhoneNumber );
  2237. DNASSERT( dwDataType == DPNA_DATATYPE_STRING );
  2238. hr = PhoneNumberFromWCHAR( PhoneNumber, m_PhoneNumber, &dwASCIIPhoneNumberSize );
  2239. DNASSERT( hr == DPN_OK );
  2240. #endif // UNICODE
  2241. break;
  2242. }
  2243. case DPNERR_DOESNOTEXIST:
  2244. {
  2245. break;
  2246. }
  2247. default:
  2248. {
  2249. hr = hPhoneNumberResult;
  2250. DPFX(DPFPREP, 0, "Failed to process phone number!" );
  2251. DisplayDNError( 0, hr );
  2252. goto Failure;
  2253. }
  2254. }
  2255. }
  2256. if ( ( GetDeviceID() == INVALID_DEVICE_ID ) ||
  2257. ( ( LinkDirection == LINK_DIRECTION_OUTGOING ) && ( lstrlen( m_PhoneNumber ) == 0 ) ) )
  2258. {
  2259. hr = DPNERR_INCOMPLETEADDRESS;
  2260. goto Failure;
  2261. }
  2262. }
  2263. else // !m_fModem
  2264. {
  2265. hr = m_ComPortData.ComPortDataFromDP8Addresses( pHostAddress, pAdapterAddress );
  2266. }
  2267. Exit:
  2268. SetType( EndpointType );
  2269. if ( hr != DPN_OK )
  2270. {
  2271. DPFX(DPFPREP, 0, "Problem with CModemEndpoint::Open" );
  2272. DisplayDNError( 0, hr );
  2273. }
  2274. return hr;
  2275. Failure:
  2276. goto Exit;
  2277. }
  2278. //**********************************************************************
  2279. //**********************************************************************
  2280. // ------------------------------
  2281. // CModemEndpoint::OpenOnListen - open this endpoint when data is received on a listen
  2282. //
  2283. // Entry: Nothing
  2284. //
  2285. // Exit: Noting
  2286. // ------------------------------
  2287. #undef DPF_MODNAME
  2288. #define DPF_MODNAME "CModemEndpoint::OpenOnListen"
  2289. HRESULT CModemEndpoint::OpenOnListen( const CModemEndpoint *const pListenEndpoint )
  2290. {
  2291. HRESULT hr;
  2292. DNASSERT( pListenEndpoint != NULL );
  2293. //
  2294. // initialize
  2295. //
  2296. hr = DPN_OK;
  2297. if (m_fModem)
  2298. {
  2299. SetDeviceID( pListenEndpoint->GetDeviceID() );
  2300. }
  2301. else
  2302. {
  2303. m_ComPortData.Copy( pListenEndpoint->GetComPortData() );
  2304. }
  2305. SetType( ENDPOINT_TYPE_CONNECT_ON_LISTEN );
  2306. SetState( ENDPOINT_STATE_ATTEMPTING_CONNECT );
  2307. return hr;
  2308. }
  2309. //**********************************************************************
  2310. //**********************************************************************
  2311. // ------------------------------
  2312. // CModemEndpoint::Close - close this endpoint
  2313. //
  2314. // Entry: Nothing
  2315. //
  2316. // Exit: Noting
  2317. // ------------------------------
  2318. #undef DPF_MODNAME
  2319. #define DPF_MODNAME "CModemEndpoint::Close"
  2320. void CModemEndpoint::Close( const HRESULT hActiveCommandResult )
  2321. {
  2322. DPFX(DPFPREP, 6, "(0x%p) Parameters (0x%lx)", this, hActiveCommandResult);
  2323. //
  2324. // Set the command result so it can be returned when the endpoint reference
  2325. // count is zero.
  2326. //
  2327. SetCommandResult( hActiveCommandResult );
  2328. DPFX(DPFPREP, 6, "(0x%p) Leaving", this);
  2329. }
  2330. //**********************************************************************
  2331. //**********************************************************************
  2332. // ------------------------------
  2333. // CModemEndpoint::GetLinkSpeed - get speed of link
  2334. //
  2335. // Entry: Nothing
  2336. //
  2337. // Exit: Link speed
  2338. // ------------------------------
  2339. #undef DPF_MODNAME
  2340. #define DPF_MODNAME "CModemEndpoint::GetLinkSpeed"
  2341. DWORD CModemEndpoint::GetLinkSpeed( void ) const
  2342. {
  2343. return GetBaudRate();
  2344. }
  2345. //**********************************************************************
  2346. //**********************************************************************
  2347. // ------------------------------
  2348. // CModemEndpoint::EnumComplete - enumeration has completed
  2349. //
  2350. // Entry: Command completion code
  2351. //
  2352. // Exit: Nothing
  2353. // ------------------------------
  2354. #undef DPF_MODNAME
  2355. #define DPF_MODNAME "CModemEndpoint::EnumComplete"
  2356. void CModemEndpoint::EnumComplete( const HRESULT hCommandResult )
  2357. {
  2358. Close( hCommandResult );
  2359. m_pSPData->CloseEndpointHandle( this );
  2360. m_dwEnumSendIndex = 0;
  2361. }
  2362. //**********************************************************************
  2363. //**********************************************************************
  2364. // ------------------------------
  2365. // CModemEndpoint::GetDeviceContext - get device context to initialize data port
  2366. //
  2367. // Entry: Nothing
  2368. //
  2369. // Exit: Device context
  2370. // ------------------------------
  2371. #undef DPF_MODNAME
  2372. #define DPF_MODNAME "CModemEndpoint::GetDeviceContext"
  2373. const void *CModemEndpoint::GetDeviceContext( void ) const
  2374. {
  2375. if (m_fModem)
  2376. {
  2377. return NULL;
  2378. }
  2379. else
  2380. {
  2381. return &m_ComPortData;
  2382. }
  2383. }
  2384. //**********************************************************************
  2385. //**********************************************************************
  2386. // ------------------------------
  2387. // CModemEndpoint::GetRemoteHostDP8Address - get address of remote host
  2388. //
  2389. // Entry: Nothing
  2390. //
  2391. // Exit: Pointer to address
  2392. // ------------------------------
  2393. #undef DPF_MODNAME
  2394. #define DPF_MODNAME "CModemEndpoint::GetRemoteHostDP8Address"
  2395. IDirectPlay8Address *CModemEndpoint::GetRemoteHostDP8Address( void ) const
  2396. {
  2397. IDirectPlay8Address *pAddress;
  2398. HRESULT hr;
  2399. if (!m_fModem)
  2400. {
  2401. return GetLocalAdapterDP8Address( ADDRESS_TYPE_REMOTE_HOST );
  2402. }
  2403. //
  2404. // initialize
  2405. //
  2406. pAddress = NULL;
  2407. hr = COM_CoCreateInstance( CLSID_DirectPlay8Address,
  2408. NULL,
  2409. CLSCTX_INPROC_SERVER,
  2410. IID_IDirectPlay8Address,
  2411. reinterpret_cast<void**>( &pAddress ), FALSE );
  2412. if ( hr != DPN_OK )
  2413. {
  2414. DNASSERT( pAddress == NULL );
  2415. DPFX(DPFPREP, 0, "GetRemoteHostDP8Address: Failed to create Address when converting data port to address!" );
  2416. goto Failure;
  2417. }
  2418. //
  2419. // set the SP guid
  2420. //
  2421. hr = IDirectPlay8Address_SetSP( pAddress, &CLSID_DP8SP_MODEM );
  2422. if ( hr != DPN_OK )
  2423. {
  2424. DPFX(DPFPREP, 0, "GetRemoteHostDP8Address: Failed to set service provider GUID!" );
  2425. DisplayDNError( 0, hr );
  2426. goto Failure;
  2427. }
  2428. //
  2429. // Host names can only be returned for connect and enum endpoints. Host
  2430. // names are the phone numbers that were called and will be unknown on a
  2431. // 'listen' endpoint.
  2432. //
  2433. switch ( GetType() )
  2434. {
  2435. case ENDPOINT_TYPE_ENUM:
  2436. case ENDPOINT_TYPE_CONNECT:
  2437. {
  2438. DWORD dwPhoneNumberLength;
  2439. dwPhoneNumberLength = lstrlen( m_PhoneNumber );
  2440. if ( dwPhoneNumberLength != 0 )
  2441. {
  2442. #ifdef UNICODE
  2443. hr = IDirectPlay8Address_AddComponent( pAddress,
  2444. DPNA_KEY_PHONENUMBER,
  2445. m_PhoneNumber,
  2446. (dwPhoneNumberLength + 1) * sizeof( *m_PhoneNumber ),
  2447. DPNA_DATATYPE_STRING );
  2448. #else
  2449. WCHAR WCHARPhoneNumber[ sizeof( m_PhoneNumber ) ];
  2450. DWORD dwWCHARPhoneNumberLength;
  2451. //
  2452. // can't use the STR_ functions to convert ANSI to WIDE phone
  2453. // numbers because phone numbers with symbols: "9,", "*70" are
  2454. // interpreted as already being WCHAR when they're not!
  2455. //
  2456. dwWCHARPhoneNumberLength = LENGTHOF( WCHARPhoneNumber );
  2457. hr = PhoneNumberToWCHAR( m_PhoneNumber, WCHARPhoneNumber, &dwWCHARPhoneNumberLength );
  2458. DNASSERT( hr == DPN_OK );
  2459. hr = IDirectPlay8Address_AddComponent( pAddress,
  2460. DPNA_KEY_PHONENUMBER,
  2461. WCHARPhoneNumber,
  2462. dwWCHARPhoneNumberLength * sizeof( *WCHARPhoneNumber ),
  2463. DPNA_DATATYPE_STRING );
  2464. #endif // UNICODE
  2465. if ( hr != DPN_OK )
  2466. {
  2467. DPFX(DPFPREP, 0, "GetRemoteHostDP8Address: Failed to add phone number to hostname!" );
  2468. DisplayDNError( 0, hr );
  2469. goto Failure;
  2470. }
  2471. }
  2472. break;
  2473. }
  2474. case ENDPOINT_TYPE_LISTEN:
  2475. {
  2476. break;
  2477. }
  2478. default:
  2479. {
  2480. DNASSERT( FALSE );
  2481. break;
  2482. }
  2483. }
  2484. Exit:
  2485. return pAddress;
  2486. Failure:
  2487. if ( pAddress != NULL )
  2488. {
  2489. IDirectPlay8Address_Release( pAddress );
  2490. pAddress = NULL;
  2491. }
  2492. goto Exit;
  2493. }
  2494. //**********************************************************************
  2495. //**********************************************************************
  2496. // ------------------------------
  2497. // CModemEndpoint::GetLocalAdapterDP8Address - get address from local adapter
  2498. //
  2499. // Entry: Adadpter address format
  2500. //
  2501. // Exit: Pointer to address
  2502. // ------------------------------
  2503. #undef DPF_MODNAME
  2504. #define DPF_MODNAME "CModemEndpoint::GetLocalAdapterDP8Address"
  2505. IDirectPlay8Address *CModemEndpoint::GetLocalAdapterDP8Address( const ADDRESS_TYPE AddressType ) const
  2506. {
  2507. CDataPort *pDataPort;
  2508. DNASSERT( GetDataPort() != NULL );
  2509. pDataPort = GetDataPort();
  2510. if (m_fModem)
  2511. {
  2512. return pDataPort->GetLocalAdapterDP8Address( AddressType );
  2513. }
  2514. else
  2515. {
  2516. return pDataPort->ComPortData()->DP8AddressFromComPortData( AddressType );
  2517. }
  2518. }
  2519. //**********************************************************************
  2520. #ifndef DPNBUILD_NOSPUI
  2521. //**********************************************************************
  2522. // ------------------------------
  2523. // CModemEndpoint::ShowIncomingSettingsDialog - show dialog for incoming modem settings
  2524. //
  2525. // Entry: Pointer to thread pool
  2526. //
  2527. // Exit: Error code
  2528. // ------------------------------
  2529. #undef DPF_MODNAME
  2530. #define DPF_MODNAME "CModemEndpoint::ShowIncomingSettingsDialog"
  2531. HRESULT CModemEndpoint::ShowIncomingSettingsDialog( CModemThreadPool *const pThreadPool )
  2532. {
  2533. HRESULT hr;
  2534. DIALOG_FUNCTION* pFunction;
  2535. if (m_fModem)
  2536. {
  2537. pFunction = DisplayIncomingModemSettingsDialog;
  2538. }
  2539. else
  2540. {
  2541. pFunction = DisplayComPortSettingsDialog;
  2542. }
  2543. DNASSERT( pThreadPool != NULL );
  2544. //
  2545. // initialize
  2546. //
  2547. hr = DPN_OK;
  2548. AddRef();
  2549. hr = pThreadPool->SpawnDialogThread( pFunction, this );
  2550. if ( hr != DPN_OK )
  2551. {
  2552. DPFX(DPFPREP, 0, "Failed to start incoming modem dialog!" );
  2553. DisplayDNError( 0, hr );
  2554. goto Failure;
  2555. }
  2556. Exit:
  2557. return hr;
  2558. Failure:
  2559. DecRef();
  2560. goto Exit;
  2561. }
  2562. //**********************************************************************
  2563. //**********************************************************************
  2564. // ------------------------------
  2565. // CModemEndpoint::ShowOutgoingSettingsDialog - show settings dialog for outgoing
  2566. // modem connection
  2567. //
  2568. // Entry: Pointer to thread pool
  2569. //
  2570. // Exit: Error code
  2571. // ------------------------------
  2572. #undef DPF_MODNAME
  2573. #define DPF_MODNAME "CModemEndpoint::ShowOutgoingSettingsDialog"
  2574. HRESULT CModemEndpoint::ShowOutgoingSettingsDialog( CModemThreadPool *const pThreadPool )
  2575. {
  2576. HRESULT hr;
  2577. DIALOG_FUNCTION* pFunction;
  2578. DNASSERT( pThreadPool != NULL );
  2579. if (m_fModem)
  2580. {
  2581. pFunction = DisplayOutgoingModemSettingsDialog;
  2582. }
  2583. else
  2584. {
  2585. pFunction = DisplayComPortSettingsDialog;
  2586. }
  2587. //
  2588. // initialize
  2589. //
  2590. hr = DPN_OK;
  2591. AddRef();
  2592. hr = pThreadPool->SpawnDialogThread( pFunction, this );
  2593. if ( hr != DPN_OK )
  2594. {
  2595. DPFX(DPFPREP, 0, "Failed to start incoming modem dialog!" );
  2596. DisplayDNError( 0, hr );
  2597. goto Failure;
  2598. }
  2599. Exit:
  2600. return hr;
  2601. Failure:
  2602. DecRef();
  2603. goto Exit;
  2604. }
  2605. //**********************************************************************
  2606. //**********************************************************************
  2607. // ------------------------------
  2608. // CModemEndpoint::StopSettingsDialog - stop a settings dialog
  2609. //
  2610. // Entry: Dialog handle
  2611. //
  2612. // Exit: Nothing
  2613. // ------------------------------
  2614. #undef DPF_MODNAME
  2615. #define DPF_MODNAME "CModemEndpoint::StopSettingsDialog"
  2616. void CModemEndpoint::StopSettingsDialog( const HWND hDialog )
  2617. {
  2618. if (m_fModem)
  2619. {
  2620. StopModemSettingsDialog( hDialog );
  2621. }
  2622. else
  2623. {
  2624. StopComPortSettingsDialog( hDialog );
  2625. }
  2626. }
  2627. //**********************************************************************
  2628. #endif // !DPNBUILD_NOSPUI