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.

2618 lines
59 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: SerialSP.cpp
  6. * Content: Service provider serial interface functions
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 12/03/98 jtk Created
  13. * 09/23/99 jtk Derived from ComCore.cpp
  14. ***************************************************************************/
  15. #include "dnmdmi.h"
  16. //**********************************************************************
  17. // Constant definitions
  18. //**********************************************************************
  19. //**********************************************************************
  20. // Macro definitions
  21. //**********************************************************************
  22. //**********************************************************************
  23. // Structure definitions
  24. //**********************************************************************
  25. //**********************************************************************
  26. // Variable definitions
  27. //**********************************************************************
  28. //**********************************************************************
  29. // Function prototypes
  30. //**********************************************************************
  31. //**********************************************************************
  32. // Function definitions
  33. //**********************************************************************
  34. //**********************************************************************
  35. // ------------------------------
  36. // DNMODEMSP_AddRef - increment interface reference cound
  37. //
  38. // Entry: Pointer to interface
  39. //
  40. // Exit: Current interface reference count
  41. // ------------------------------
  42. #undef DPF_MODNAME
  43. #define DPF_MODNAME "DNMODEMSP_AddRef"
  44. STDMETHODIMP_(ULONG) DNMODEMSP_AddRef( IDP8ServiceProvider *pThis )
  45. {
  46. CModemSPData * pSPData;
  47. ULONG ulResult;
  48. DPFX(DPFPREP, 2, "Parameters: (0x%p)", pThis);
  49. DNASSERT( pThis != NULL );
  50. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  51. ulResult = pSPData->AddRef();
  52. DPFX(DPFPREP, 2, "Returning: [0x%u]", ulResult);
  53. return ulResult;
  54. }
  55. //**********************************************************************
  56. //**********************************************************************
  57. // ------------------------------
  58. // DNMODEMSP_Release - release an interface
  59. //
  60. // Entry: Pointer to current interface
  61. // Desired interface ID
  62. // Pointer to pointer to new interface
  63. //
  64. // Exit: Error code
  65. // ------------------------------
  66. #undef DPF_MODNAME
  67. #define DPF_MODNAME "DNMODEMSP_Release"
  68. STDMETHODIMP_(ULONG) DNMODEMSP_Release( IDP8ServiceProvider *pThis )
  69. {
  70. CModemSPData * pSPData;
  71. ULONG ulResult;
  72. DNASSERT( pThis != NULL );
  73. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  74. ulResult = pSPData->DecRef();
  75. DPFX(DPFPREP, 2, "Returning: [0x%u]", ulResult);
  76. return ulResult;
  77. }
  78. //**********************************************************************
  79. //**********************************************************************
  80. // ------------------------------
  81. // DNMODEMSP_Initialize - initialize SP interface
  82. //
  83. // Entry: Pointer to interface
  84. // Pointer to initialization data
  85. //
  86. // Exit: Error code
  87. // ------------------------------
  88. #undef DPF_MODNAME
  89. #define DPF_MODNAME "DNMODEMSP_Initialize"
  90. STDMETHODIMP DNMODEMSP_Initialize( IDP8ServiceProvider *pThis, SPINITIALIZEDATA *pData )
  91. {
  92. HRESULT hr;
  93. CModemSPData *pSPData;
  94. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pData);
  95. DNASSERT( pThis != NULL );
  96. DNASSERT( pData != NULL );
  97. //
  98. // initialize
  99. //
  100. hr = DPN_OK;
  101. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  102. //
  103. // prevent anyone else from messing with this interface and bump up the reference
  104. // count
  105. //
  106. pSPData->Lock();
  107. //
  108. // check interface state
  109. //
  110. switch ( pSPData->GetState() )
  111. {
  112. //
  113. // uninitialized interface, we can initialize it
  114. //
  115. case SPSTATE_UNINITIALIZED:
  116. {
  117. break;
  118. }
  119. //
  120. // other state
  121. //
  122. case SPSTATE_INITIALIZED:
  123. case SPSTATE_CLOSING:
  124. default:
  125. {
  126. hr = DPNERR_ALREADYINITIALIZED;
  127. DPFX(DPFPREP, 0, "Attempted to reinitialize interface!" );
  128. DNASSERT( FALSE );
  129. goto Exit;
  130. }
  131. }
  132. //
  133. // before we get too far, check for the availablility of serial ports or
  134. // modems
  135. //
  136. switch ( pSPData->GetType() )
  137. {
  138. case TYPE_SERIAL:
  139. {
  140. BOOL fPortAvailable[ MAX_DATA_PORTS ];
  141. DWORD dwPortCount;
  142. hr = GenerateAvailableComPortList( fPortAvailable, ( LENGTHOF( fPortAvailable ) - 1 ), &dwPortCount );
  143. if ( ( hr != DPN_OK ) || ( dwPortCount == 0 ) )
  144. {
  145. hr = DPNERR_UNSUPPORTED;
  146. goto Failure;
  147. }
  148. break;
  149. }
  150. case TYPE_MODEM:
  151. {
  152. if ( pSPData->GetThreadPool()->TAPIAvailable() != FALSE )
  153. {
  154. DWORD dwModemCount;
  155. DWORD dwModemNameDataSize;
  156. HRESULT hTempResult;
  157. //
  158. // Get count of available modems. If this call succeeds but there
  159. // are no modems returned, fail.
  160. //
  161. dwModemCount = 0;
  162. dwModemNameDataSize = 0;
  163. hTempResult = GenerateAvailableModemList( pSPData->GetThreadPool()->GetTAPIInfo(),
  164. &dwModemCount,
  165. NULL,
  166. &dwModemNameDataSize );
  167. if ( ( hTempResult != DPNERR_BUFFERTOOSMALL ) && ( hTempResult != DPN_OK ) )
  168. {
  169. hr = hTempResult;
  170. DPFX(DPFPREP, 0, "Failed to detect available modems!" );
  171. DisplayDNError( 0, hr );
  172. goto Failure;
  173. }
  174. if ( dwModemCount == 0 )
  175. {
  176. DPFX(DPFPREP, 1, "No modems detected!" );
  177. hr = DPNERR_UNSUPPORTED;
  178. goto Failure;
  179. }
  180. DNASSERT( hr == DPN_OK );
  181. }
  182. else
  183. {
  184. DPFX(DPFPREP, 0, "TAPI not available!" );
  185. hr = DPNERR_UNSUPPORTED;
  186. goto Failure;
  187. }
  188. break;
  189. }
  190. default:
  191. {
  192. DNASSERT( FALSE );
  193. break;
  194. }
  195. }
  196. //
  197. // remember the init data
  198. //
  199. pSPData->SetCallbackData( pData );
  200. //
  201. // Success from here on in
  202. //
  203. IDP8SPCallback_AddRef( pSPData->DP8SPCallbackInterface() );
  204. pSPData->SetState( SPSTATE_INITIALIZED );
  205. pSPData->Unlock();
  206. IDP8ServiceProvider_AddRef( pThis );
  207. Exit:
  208. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  209. return hr;
  210. Failure:
  211. pSPData->Unlock();
  212. goto Exit;
  213. }
  214. //**********************************************************************
  215. //**********************************************************************
  216. // ------------------------------
  217. // DNMODEMSP_Close - close this instance of the service provier
  218. //
  219. // Entry: Pointer to the service provider to close
  220. //
  221. // Exit: Error Code
  222. // ------------------------------
  223. #undef DPF_MODNAME
  224. #define DPF_MODNAME "DNMODEMSP_Close"
  225. STDMETHODIMP DNMODEMSP_Close( IDP8ServiceProvider *pThis )
  226. {
  227. HRESULT hr;
  228. CModemSPData *pSPData;
  229. DPFX(DPFPREP, 2, "Parameters: (0x%p)", pThis);
  230. DNASSERT( pThis != NULL );
  231. //
  232. // initialize
  233. //
  234. hr = DPN_OK;
  235. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  236. switch ( pSPData->GetType() )
  237. {
  238. case TYPE_SERIAL:
  239. case TYPE_MODEM:
  240. {
  241. //
  242. // release our ref to the DPlay callbacks
  243. //
  244. pSPData->Shutdown();
  245. IDP8ServiceProvider_Release( pThis );
  246. break;
  247. }
  248. default:
  249. {
  250. DNASSERT( FALSE );
  251. break;
  252. }
  253. }
  254. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  255. return hr;
  256. }
  257. //**********************************************************************
  258. //**********************************************************************
  259. // ------------------------------
  260. // DNMODEMSP_Connect - start process to establish comport connection to a remote host
  261. //
  262. // Entry: Pointer to the service provider interface
  263. // Pointer to connection data
  264. //
  265. // Exit: Error Code
  266. //
  267. // Note: Any command handle allocated by this function is closed by the
  268. // endpoint.
  269. // ------------------------------
  270. #undef DPF_MODNAME
  271. #define DPF_MODNAME "DNMODEMSP_Connect"
  272. STDMETHODIMP DNMODEMSP_Connect( IDP8ServiceProvider *pThis, SPCONNECTDATA *pConnectData )
  273. {
  274. HRESULT hr;
  275. HRESULT hTempResult;
  276. CModemSPData *pSPData;
  277. CModemEndpoint *pEndpoint;
  278. CModemCommandData *pCommand;
  279. BOOL fEndpointOpen;
  280. GUID DeviceGUID;
  281. GUID guidnull;
  282. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pConnectData);
  283. DNASSERT( pThis != NULL );
  284. DNASSERT( pConnectData != NULL );
  285. DNASSERT( pConnectData->pAddressHost != NULL );
  286. DNASSERT( pConnectData->pAddressDeviceInfo != NULL );
  287. DNASSERT( ( pConnectData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
  288. DNASSERT( ( pConnectData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
  289. //
  290. // initialize
  291. //
  292. hr = DPNERR_PENDING;
  293. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  294. pEndpoint = NULL;
  295. pCommand = NULL;
  296. fEndpointOpen = FALSE;
  297. pConnectData->hCommand = NULL;
  298. pConnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
  299. memset(&guidnull, 0, sizeof(guidnull));
  300. //
  301. // the user is attempting an operation that relies on the thread pool, lock
  302. // it down to prevent threads from being lost.
  303. //
  304. hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
  305. if ( hTempResult != DPN_OK )
  306. {
  307. hr = hTempResult;
  308. DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
  309. goto Failure;
  310. }
  311. //
  312. // validate state
  313. //
  314. pSPData->Lock();
  315. switch ( pSPData->GetState() )
  316. {
  317. //
  318. // provider is initialized
  319. //
  320. case SPSTATE_INITIALIZED:
  321. {
  322. DNASSERT( hr == DPNERR_PENDING );
  323. break;
  324. }
  325. //
  326. // provider is uninitialized
  327. //
  328. case SPSTATE_UNINITIALIZED:
  329. {
  330. hr = DPNERR_UNINITIALIZED;
  331. DPFX(DPFPREP, 0, "DNMODEMSP_Connect called on uninitialized SP!" );
  332. goto Failure;
  333. break;
  334. }
  335. //
  336. // provider is closing
  337. //
  338. case SPSTATE_CLOSING:
  339. {
  340. hr = DPNERR_ABORTED;
  341. DPFX(DPFPREP, 0, "DNMODEMSP_Connect called while SP closing!" );
  342. goto Failure;
  343. break;
  344. }
  345. //
  346. // unknown
  347. //
  348. default:
  349. {
  350. DNASSERT( FALSE );
  351. hr = DPNERR_GENERIC;
  352. goto Failure;
  353. break;
  354. }
  355. }
  356. pSPData->Unlock();
  357. if ( hr != DPNERR_PENDING )
  358. {
  359. DNASSERT( hr != DPN_OK );
  360. goto Failure;
  361. }
  362. //
  363. // check for invalid device ID
  364. //
  365. hTempResult = IDirectPlay8Address_GetDevice( pConnectData->pAddressDeviceInfo, &DeviceGUID );
  366. switch ( hTempResult )
  367. {
  368. //
  369. // there was a device ID, check against GUID_NULL
  370. //
  371. case DPN_OK:
  372. {
  373. if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
  374. {
  375. hr = DPNERR_ADDRESSING;
  376. DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
  377. goto Failure;
  378. }
  379. break;
  380. }
  381. //
  382. // no device address specified, not a problem
  383. //
  384. case DPNERR_DOESNOTEXIST:
  385. {
  386. break;
  387. }
  388. //
  389. // other, stop and figure out why we're here
  390. //
  391. default:
  392. {
  393. DNASSERT( FALSE );
  394. hr = hTempResult;
  395. DPFX(DPFPREP, 0, "Failed to validate device address!" );
  396. DisplayDNError( 0, hTempResult );
  397. break;
  398. }
  399. }
  400. //
  401. // get endpoint for this connection
  402. //
  403. pEndpoint = pSPData->GetNewEndpoint();
  404. if ( pEndpoint == NULL )
  405. {
  406. hr = DPNERR_OUTOFMEMORY;
  407. DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Cannot create new endpoint!" );
  408. goto Failure;
  409. }
  410. //
  411. // get new command
  412. //
  413. pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
  414. if ( pCommand == NULL )
  415. {
  416. hr = DPNERR_OUTOFMEMORY;
  417. DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Cannot get command handle!" );
  418. goto Failure;
  419. }
  420. //
  421. // initialize command
  422. //
  423. pConnectData->hCommand = pCommand;
  424. pConnectData->dwCommandDescriptor = pCommand->GetDescriptor();
  425. pCommand->SetType( COMMAND_TYPE_CONNECT );
  426. pCommand->SetState( COMMAND_STATE_PENDING );
  427. pCommand->SetEndpoint( pEndpoint );
  428. //
  429. // open this endpoint
  430. //
  431. hTempResult = pEndpoint->Open( pConnectData->pAddressHost,
  432. pConnectData->pAddressDeviceInfo,
  433. LINK_DIRECTION_OUTGOING,
  434. ENDPOINT_TYPE_CONNECT );
  435. switch ( hTempResult )
  436. {
  437. //
  438. // endpoint opened, no problem
  439. //
  440. case DPN_OK:
  441. {
  442. //
  443. // copy connect data and the submit background job
  444. //
  445. fEndpointOpen = TRUE;
  446. pEndpoint->CopyConnectData( pConnectData );
  447. pEndpoint->AddRef();
  448. hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->ConnectJobCallback,
  449. pEndpoint->CancelConnectJobCallback,
  450. pEndpoint );
  451. if ( hTempResult != DPN_OK )
  452. {
  453. pEndpoint->DecRef();
  454. hr = hTempResult;
  455. DPFX(DPFPREP, 0, "Failed to set delayed listen!" );
  456. DisplayDNError( 0, hr );
  457. goto Failure;
  458. }
  459. //
  460. // this endpoint has been handed off, remove our reference to it
  461. //
  462. pEndpoint = NULL;
  463. DNASSERT( hr == DPNERR_PENDING );
  464. break;
  465. }
  466. //
  467. // not all of the addressing information was specifed, need to query user
  468. //
  469. case DPNERR_INCOMPLETEADDRESS:
  470. {
  471. #ifndef DPNBUILD_NOSPUI
  472. if ( ( pConnectData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
  473. {
  474. //
  475. // copy connect data for future reference and then start the dialog
  476. //
  477. fEndpointOpen = TRUE;
  478. pEndpoint->CopyConnectData( pConnectData );
  479. hTempResult = pEndpoint->ShowOutgoingSettingsDialog( pSPData->GetThreadPool() );
  480. if ( hTempResult != DPN_OK )
  481. {
  482. hr = hTempResult;
  483. DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Problem showing settings dialog!" );
  484. DisplayDNError( 0, hTempResult );
  485. goto Failure;
  486. }
  487. //
  488. // this endpoint has been handed off, remove our reference to it
  489. //
  490. pEndpoint = NULL;
  491. DNASSERT( hr == DPNERR_PENDING );
  492. goto Exit;
  493. }
  494. else
  495. #endif // !DPNBUILD_NOSPUI
  496. {
  497. hr = hTempResult;
  498. goto Failure;
  499. }
  500. break;
  501. }
  502. default:
  503. {
  504. hr = hTempResult;
  505. DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Problem opening endpoint with host address!" );
  506. DisplayDNError( 0, hTempResult );
  507. goto Failure;
  508. break;
  509. }
  510. }
  511. Exit:
  512. DNASSERT( pEndpoint == NULL );
  513. if ( hr != DPNERR_PENDING )
  514. {
  515. // this command cannot complete synchronously!
  516. DNASSERT( hr != DPN_OK );
  517. DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Connect()" );
  518. DisplayDNError( 0, hr );
  519. }
  520. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  521. return hr;
  522. Failure:
  523. //
  524. // return any outstanding endpoint
  525. //
  526. if ( pEndpoint != NULL )
  527. {
  528. if ( fEndpointOpen != FALSE )
  529. {
  530. DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
  531. pEndpoint->Close( hr );
  532. fEndpointOpen = FALSE;
  533. }
  534. pSPData->CloseEndpointHandle( pEndpoint );
  535. pEndpoint = NULL;
  536. }
  537. //
  538. // return any outstanding command
  539. //
  540. if ( pCommand != NULL )
  541. {
  542. pCommand->DecRef();
  543. pCommand = NULL;
  544. pConnectData->hCommand = NULL;
  545. pConnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
  546. }
  547. goto Exit;
  548. }
  549. //**********************************************************************
  550. //**********************************************************************
  551. // ------------------------------
  552. // DNMODEMSP_Disconnect - disconnect from a remote host
  553. //
  554. // Entry: Pointer to the service provider interface
  555. // Pointer to connection data
  556. //
  557. // Exit: Error Code
  558. //
  559. // Note: This command is considered final, there's no chance to cancel a
  560. // disconnect.
  561. // ------------------------------
  562. #undef DPF_MODNAME
  563. #define DPF_MODNAME "DNMODEMSP_Disconnect"
  564. STDMETHODIMP DNMODEMSP_Disconnect( IDP8ServiceProvider *pThis, SPDISCONNECTDATA *pDisconnectData )
  565. {
  566. HRESULT hr;
  567. HRESULT hTempResult;
  568. CModemEndpoint *pEndpoint;
  569. CModemSPData *pSPData;
  570. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pDisconnectData);
  571. DNASSERT( pThis != NULL );
  572. DNASSERT( pDisconnectData != NULL );
  573. DNASSERT( pDisconnectData->hEndpoint != INVALID_HANDLE_VALUE && pDisconnectData->hEndpoint != 0 );
  574. DNASSERT( pDisconnectData->dwFlags == 0 );
  575. //
  576. // initialize
  577. //
  578. hr = DPN_OK;
  579. pEndpoint = NULL;
  580. pDisconnectData->hCommand = NULL;
  581. pDisconnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
  582. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  583. //
  584. // check service provider state
  585. //
  586. pSPData->Lock();
  587. switch ( pSPData->GetState() )
  588. {
  589. //
  590. // provider is initialized
  591. //
  592. case SPSTATE_INITIALIZED:
  593. {
  594. DNASSERT( hr == DPN_OK );
  595. break;
  596. }
  597. //
  598. // provider is uninitialized
  599. //
  600. case SPSTATE_UNINITIALIZED:
  601. {
  602. hr = DPNERR_UNINITIALIZED;
  603. DPFX(DPFPREP, 0, "Disconnect called on uninitialized SP!" );
  604. goto Failure;
  605. break;
  606. }
  607. //
  608. // provider is closing
  609. //
  610. case SPSTATE_CLOSING:
  611. {
  612. hr = DPNERR_ABORTED;
  613. DPFX(DPFPREP, 0, "Disconnect called on closing SP!" );
  614. goto Failure;
  615. break;
  616. }
  617. //
  618. // unknown
  619. //
  620. default:
  621. {
  622. hr = DPNERR_GENERIC;
  623. DNASSERT( FALSE );
  624. goto Failure;
  625. break;
  626. }
  627. }
  628. pSPData->Unlock();
  629. if ( hr != DPN_OK )
  630. {
  631. goto Failure;
  632. }
  633. //
  634. // look up the endpoint and if it's found, close its handle
  635. //
  636. pEndpoint = pSPData->GetEndpointAndCloseHandle( (DPNHANDLE)(DWORD_PTR)pDisconnectData->hEndpoint );
  637. if ( pEndpoint == NULL )
  638. {
  639. hr = DPNERR_INVALIDENDPOINT;
  640. goto Failure;
  641. }
  642. hTempResult = pEndpoint->Disconnect( (DPNHANDLE)(DWORD_PTR)pDisconnectData->hEndpoint );
  643. switch ( hTempResult )
  644. {
  645. //
  646. // endpoint disconnected immediately
  647. //
  648. case DPN_OK:
  649. {
  650. break;
  651. }
  652. //
  653. // Other return. Since the disconnect didn't complete, we need
  654. // to unlock the endpoint.
  655. //
  656. default:
  657. {
  658. DPFX(DPFPREP, 0, "Error reported when attempting to disconnect endpoint in DNMODEMSP_Disconnect!" );
  659. DisplayDNError( 0, hTempResult );
  660. break;
  661. }
  662. }
  663. Exit:
  664. //
  665. // remove oustanding reference from GetEndpointHandleAndClose()
  666. //
  667. if ( pEndpoint != NULL )
  668. {
  669. pEndpoint->DecRef();
  670. pEndpoint = NULL;
  671. }
  672. if ( hr != DPN_OK )
  673. {
  674. DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Disconnect()" );
  675. DisplayDNError( 0, hr );
  676. }
  677. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  678. return hr;
  679. Failure:
  680. goto Exit;
  681. }
  682. //**********************************************************************
  683. //**********************************************************************
  684. // ------------------------------
  685. // DNMODEMSP_Listen - start process to listen for comport connections
  686. //
  687. // Entry: Pointer to the service provider interface
  688. // Pointer to listen data
  689. //
  690. // Exit: Error Code
  691. //
  692. // Note: Any command handle allocated by this function is closed by the
  693. // endpoint.
  694. // ------------------------------
  695. #undef DPF_MODNAME
  696. #define DPF_MODNAME "DNMODEMSP_Listen"
  697. STDMETHODIMP DNMODEMSP_Listen( IDP8ServiceProvider *pThis, SPLISTENDATA *pListenData )
  698. {
  699. HRESULT hr;
  700. HRESULT hTempResult;
  701. CModemSPData *pSPData;
  702. CModemEndpoint *pEndpoint;
  703. CModemCommandData *pCommand;
  704. BOOL fEndpointOpen;
  705. BOOL fInterfaceReferenceAdded;
  706. GUID DeviceGUID;
  707. GUID guidnull;
  708. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pListenData);
  709. DNASSERT( pThis != NULL );
  710. DNASSERT( pListenData != NULL );
  711. DNASSERT( ( pListenData->dwFlags & ~( DPNSPF_OKTOQUERY | DPNSPF_BINDLISTENTOGATEWAY | DPNSPF_LISTEN_DISALLOWENUMS ) ) == 0 );
  712. //
  713. // initialize
  714. //
  715. hr = DPNERR_PENDING;
  716. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  717. pEndpoint = NULL;
  718. pCommand = NULL;
  719. fEndpointOpen = FALSE;
  720. pListenData->hCommand = NULL;
  721. pListenData->dwCommandDescriptor = NULL_DESCRIPTOR;
  722. fInterfaceReferenceAdded = FALSE;
  723. memset(&guidnull, 0, sizeof(guidnull));
  724. //
  725. // the user is attempting an operation that relies on the thread pool, lock
  726. // it down to prevent threads from being lost.
  727. //
  728. hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
  729. if ( hTempResult != DPN_OK )
  730. {
  731. hr = hTempResult;
  732. DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
  733. goto Failure;
  734. }
  735. //
  736. // validate state
  737. //
  738. pSPData->Lock();
  739. switch ( pSPData->GetState() )
  740. {
  741. //
  742. // provider is initialized
  743. //
  744. case SPSTATE_INITIALIZED:
  745. {
  746. DNASSERT( hr == DPNERR_PENDING );
  747. IDP8ServiceProvider_AddRef( pThis );
  748. fInterfaceReferenceAdded = TRUE;
  749. break;
  750. }
  751. //
  752. // provider is uninitialized
  753. //
  754. case SPSTATE_UNINITIALIZED:
  755. {
  756. hr = DPNERR_UNINITIALIZED;
  757. DPFX(DPFPREP, 0, "DNMODEMSP_Listen called on uninitialized SP!" );
  758. goto Failure;
  759. break;
  760. }
  761. //
  762. // provider is closing
  763. //
  764. case SPSTATE_CLOSING:
  765. {
  766. hr = DPNERR_ABORTED;
  767. DPFX(DPFPREP, 0, "DNMODEMSP_Listen called while SP closing!" );
  768. goto Failure;
  769. break;
  770. }
  771. //
  772. // unknown
  773. //
  774. default:
  775. {
  776. DNASSERT( FALSE );
  777. hr = DPNERR_GENERIC;
  778. goto Failure;
  779. break;
  780. }
  781. }
  782. pSPData->Unlock();
  783. if ( hr != DPNERR_PENDING )
  784. {
  785. DNASSERT( hr != DPN_OK );
  786. goto Failure;
  787. }
  788. //
  789. // check for invalid device ID
  790. //
  791. hTempResult = IDirectPlay8Address_GetDevice( pListenData->pAddressDeviceInfo, &DeviceGUID );
  792. switch ( hTempResult )
  793. {
  794. //
  795. // there was a device ID, check against GUID_NULL
  796. //
  797. case DPN_OK:
  798. {
  799. if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
  800. {
  801. hr = DPNERR_ADDRESSING;
  802. DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
  803. goto Failure;
  804. }
  805. break;
  806. }
  807. //
  808. // no device address specified, not a problem
  809. //
  810. case DPNERR_DOESNOTEXIST:
  811. {
  812. break;
  813. }
  814. //
  815. // other, stop and figure out why we're here
  816. //
  817. default:
  818. {
  819. DNASSERT( FALSE );
  820. hr = hTempResult;
  821. DPFX(DPFPREP, 0, "Failed to validate device address!" );
  822. DisplayDNError( 0, hTempResult );
  823. break;
  824. }
  825. }
  826. //
  827. // get endpoint for this connection
  828. //
  829. pEndpoint = pSPData->GetNewEndpoint();
  830. if ( pEndpoint == NULL )
  831. {
  832. hr = DPNERR_OUTOFMEMORY;
  833. DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Cannot create new endpoint!" );
  834. goto Failure;
  835. }
  836. //
  837. // get new command
  838. //
  839. pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
  840. if ( pCommand == NULL )
  841. {
  842. hr = DPNERR_OUTOFMEMORY;
  843. DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Cannot get command handle!" );
  844. goto Failure;
  845. }
  846. //
  847. // initialize command
  848. //
  849. pListenData->hCommand = pCommand;
  850. pListenData->dwCommandDescriptor = pCommand->GetDescriptor();
  851. pCommand->SetType( COMMAND_TYPE_LISTEN );
  852. pCommand->SetState( COMMAND_STATE_PENDING );
  853. pCommand->SetEndpoint( pEndpoint );
  854. //
  855. // open this endpoint
  856. //
  857. hTempResult = pEndpoint->Open( NULL,
  858. pListenData->pAddressDeviceInfo,
  859. LINK_DIRECTION_INCOMING,
  860. ENDPOINT_TYPE_LISTEN );
  861. switch ( hTempResult )
  862. {
  863. //
  864. // address conversion was fine, complete this command in the background
  865. //
  866. case DPN_OK:
  867. {
  868. //
  869. // copy connect data and the submit background job
  870. //
  871. fEndpointOpen = TRUE;
  872. pEndpoint->CopyListenData( pListenData );
  873. pEndpoint->AddRef();
  874. hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->ListenJobCallback,
  875. pEndpoint->CancelListenJobCallback,
  876. pEndpoint );
  877. if ( hTempResult != DPN_OK )
  878. {
  879. pEndpoint->DecRef();
  880. hr = hTempResult;
  881. DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Failed to submit delayed listen!" );
  882. DisplayDNError( 0, hr );
  883. goto Failure;
  884. }
  885. //
  886. // this endpoint has been handed off, remove our reference to it
  887. //
  888. pEndpoint = NULL;
  889. DNASSERT( hr == DPNERR_PENDING );
  890. break;
  891. }
  892. //
  893. // address was incomplete, display a dialog if we can, otherwise fail the command
  894. //
  895. case DPNERR_INCOMPLETEADDRESS:
  896. {
  897. if ( ( pListenData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
  898. {
  899. //
  900. // copy connect data for future reference and then start the dialog
  901. //
  902. fEndpointOpen = TRUE;
  903. pEndpoint->CopyListenData( pListenData );
  904. hTempResult = pEndpoint->ShowIncomingSettingsDialog( pSPData->GetThreadPool() );
  905. if ( hTempResult != DPN_OK )
  906. {
  907. hr = hTempResult;
  908. DPFX(DPFPREP, 0, "Problem showing settings dialog in DNMODEMSP_Listen!" );
  909. DisplayDNError( 0, hTempResult );
  910. goto Failure;
  911. }
  912. //
  913. // This endpoint has been handed off, clear the pointer to it.
  914. // There is no reference to remove because the command is
  915. // still pending.
  916. //
  917. pEndpoint = NULL;
  918. DNASSERT( hr == DPNERR_PENDING );
  919. goto Exit;
  920. }
  921. else
  922. {
  923. hr = hTempResult;
  924. goto Failure;
  925. }
  926. break;
  927. }
  928. default:
  929. {
  930. hr = hTempResult;
  931. DPFX(DPFPREP, 0, "Problem initializing endpoint in DNMODEMSP_Listen!" );
  932. DisplayDNError( 0, hTempResult );
  933. goto Failure;
  934. break;
  935. }
  936. }
  937. Exit:
  938. DNASSERT( pEndpoint == NULL );
  939. if ( hr != DPNERR_PENDING )
  940. {
  941. // this command cannot complete synchronously!
  942. DNASSERT( hr != DPN_OK );
  943. DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Listen()" );
  944. DisplayDNError( 0, hr );
  945. }
  946. if ( fInterfaceReferenceAdded != FALSE )
  947. {
  948. IDP8ServiceProvider_Release( pThis );
  949. fInterfaceReferenceAdded = FALSE;
  950. }
  951. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  952. return hr;
  953. Failure:
  954. //
  955. // return any outstanding endpoint
  956. //
  957. if ( pEndpoint != NULL )
  958. {
  959. if ( fEndpointOpen != FALSE )
  960. {
  961. DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
  962. pEndpoint->Close( hr );
  963. fEndpointOpen = FALSE;
  964. }
  965. pSPData->CloseEndpointHandle( pEndpoint );
  966. pEndpoint = NULL;
  967. }
  968. //
  969. // return any outstanding command
  970. //
  971. if ( pCommand != NULL )
  972. {
  973. pCommand->DecRef();
  974. pCommand = NULL;
  975. pListenData->hCommand = NULL;
  976. pListenData->dwCommandDescriptor = NULL_DESCRIPTOR;
  977. }
  978. goto Exit;
  979. }
  980. //**********************************************************************
  981. //**********************************************************************
  982. // ------------------------------
  983. // DNMODEMSP_EnumQuery - start process to enum comport connections
  984. //
  985. // Entry: Pointer to the service provider interface
  986. // Pointer to enum data
  987. //
  988. // Exit: Error Code
  989. //
  990. // Note: Any command handle allocated by this function is closed by the
  991. // endpoint.
  992. // ------------------------------
  993. #undef DPF_MODNAME
  994. #define DPF_MODNAME "DNMODEMSP_EnumQuery"
  995. STDMETHODIMP DNMODEMSP_EnumQuery( IDP8ServiceProvider *pThis, SPENUMQUERYDATA *pEnumQueryData )
  996. {
  997. HRESULT hr;
  998. HRESULT hTempResult;
  999. CModemSPData *pSPData;
  1000. CModemEndpoint *pEndpoint;
  1001. CModemCommandData *pCommand;
  1002. BOOL fEndpointOpen;
  1003. GUID DeviceGUID;
  1004. GUID guidnull;
  1005. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumQueryData);
  1006. DNASSERT( pThis != NULL );
  1007. DNASSERT( pEnumQueryData != NULL );
  1008. DNASSERT( ( pEnumQueryData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
  1009. //
  1010. // initialize
  1011. //
  1012. hr = DPNERR_PENDING;
  1013. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1014. pEndpoint = NULL;
  1015. pCommand = NULL;
  1016. fEndpointOpen = FALSE;
  1017. pEnumQueryData->hCommand = NULL;
  1018. pEnumQueryData->dwCommandDescriptor = NULL_DESCRIPTOR;
  1019. memset(&guidnull, 0, sizeof(guidnull));
  1020. //
  1021. // the user is attempting an operation that relies on the thread pool, lock
  1022. // it down to prevent threads from being lost.
  1023. //
  1024. hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
  1025. if ( hTempResult != DPN_OK )
  1026. {
  1027. hr = hTempResult;
  1028. DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
  1029. goto Failure;
  1030. }
  1031. //
  1032. // validate state
  1033. //
  1034. pSPData->Lock();
  1035. switch ( pSPData->GetState() )
  1036. {
  1037. //
  1038. // provider is initialized
  1039. //
  1040. case SPSTATE_INITIALIZED:
  1041. {
  1042. DNASSERT( hr == DPNERR_PENDING );
  1043. break;
  1044. }
  1045. //
  1046. // provider is uninitialized
  1047. //
  1048. case SPSTATE_UNINITIALIZED:
  1049. {
  1050. hr = DPNERR_UNINITIALIZED;
  1051. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery called on uninitialized SP!" );
  1052. goto Failure;
  1053. break;
  1054. }
  1055. //
  1056. // provider is closing
  1057. //
  1058. case SPSTATE_CLOSING:
  1059. {
  1060. hr = DPNERR_ABORTED;
  1061. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery called while SP closing!" );
  1062. goto Failure;
  1063. break;
  1064. }
  1065. //
  1066. // unknown
  1067. //
  1068. default:
  1069. {
  1070. DNASSERT( FALSE );
  1071. hr = DPNERR_GENERIC;
  1072. goto Failure;
  1073. break;
  1074. }
  1075. }
  1076. pSPData->Unlock();
  1077. if ( hr != DPNERR_PENDING )
  1078. {
  1079. DNASSERT( hr != DPN_OK );
  1080. goto Failure;
  1081. }
  1082. //
  1083. // check for invalid device ID
  1084. //
  1085. hTempResult = IDirectPlay8Address_GetDevice( pEnumQueryData->pAddressDeviceInfo, &DeviceGUID );
  1086. switch ( hTempResult )
  1087. {
  1088. //
  1089. // there was a device ID, check against GUID_NULL
  1090. //
  1091. case DPN_OK:
  1092. {
  1093. if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
  1094. {
  1095. hr = DPNERR_ADDRESSING;
  1096. DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
  1097. goto Failure;
  1098. }
  1099. break;
  1100. }
  1101. //
  1102. // no device address specified, not a problem
  1103. //
  1104. case DPNERR_DOESNOTEXIST:
  1105. {
  1106. break;
  1107. }
  1108. //
  1109. // other, stop and figure out why we're here
  1110. //
  1111. default:
  1112. {
  1113. DNASSERT( FALSE );
  1114. hr = hTempResult;
  1115. DPFX(DPFPREP, 0, "Failed to validate device address!" );
  1116. DisplayDNError( 0, hTempResult );
  1117. break;
  1118. }
  1119. }
  1120. //
  1121. // get endpoint for this connection
  1122. //
  1123. pEndpoint = pSPData->GetNewEndpoint();
  1124. if ( pEndpoint == NULL )
  1125. {
  1126. hr = DPNERR_OUTOFMEMORY;
  1127. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Cannot create new endpoint!" );
  1128. goto Failure;
  1129. }
  1130. //
  1131. // get new command
  1132. //
  1133. pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
  1134. if ( pCommand == NULL )
  1135. {
  1136. hr = DPNERR_OUTOFMEMORY;
  1137. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Cannot get command handle!" );
  1138. goto Failure;
  1139. }
  1140. //
  1141. // initialize command
  1142. //
  1143. pEnumQueryData->hCommand = pCommand;
  1144. pEnumQueryData->dwCommandDescriptor = pCommand->GetDescriptor();
  1145. pCommand->SetType( COMMAND_TYPE_ENUM_QUERY );
  1146. pCommand->SetState( COMMAND_STATE_INPROGRESS );
  1147. pCommand->SetEndpoint( pEndpoint );
  1148. //
  1149. // open this endpoint
  1150. //
  1151. hTempResult = pEndpoint->Open( pEnumQueryData->pAddressHost,
  1152. pEnumQueryData->pAddressDeviceInfo,
  1153. LINK_DIRECTION_OUTGOING,
  1154. ENDPOINT_TYPE_ENUM );
  1155. switch ( hTempResult )
  1156. {
  1157. //
  1158. // address was incomplete, display a dialog if we can, otherwise fail the command
  1159. //
  1160. case DPNERR_INCOMPLETEADDRESS:
  1161. {
  1162. #ifndef DPNBUILD_NOSPUI
  1163. if ( ( pEnumQueryData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
  1164. {
  1165. //
  1166. // copy connect data for future reference and then start the dialog
  1167. //
  1168. fEndpointOpen = TRUE;
  1169. pEndpoint->CopyEnumQueryData( pEnumQueryData );
  1170. hTempResult = pEndpoint->ShowOutgoingSettingsDialog( pSPData->GetThreadPool() );
  1171. if ( hTempResult != DPN_OK )
  1172. {
  1173. hr = hTempResult;
  1174. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Problem showing settings dialog!" );
  1175. DisplayDNError( 0, hTempResult );
  1176. goto Failure;
  1177. }
  1178. //
  1179. // this endpoint has been handed off, remove our reference to it
  1180. //
  1181. pEndpoint = NULL;
  1182. DNASSERT( hr == DPNERR_PENDING );
  1183. goto Exit;
  1184. }
  1185. else
  1186. #endif // !DPNBUILD_NOSPUI
  1187. {
  1188. hr = hTempResult;
  1189. goto Failure;
  1190. }
  1191. break;
  1192. }
  1193. //
  1194. // address conversion was fine, complete this command in the background
  1195. //
  1196. case DPN_OK:
  1197. {
  1198. //
  1199. // copy connect data and the submit background job
  1200. //
  1201. fEndpointOpen = TRUE;
  1202. pEndpoint->CopyEnumQueryData( pEnumQueryData );
  1203. pEndpoint->AddRef();
  1204. hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->EnumQueryJobCallback,
  1205. pEndpoint->CancelEnumQueryJobCallback,
  1206. pEndpoint );
  1207. if ( hTempResult != DPN_OK )
  1208. {
  1209. pEndpoint->DecRef();
  1210. hr = hTempResult;
  1211. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Failed to submit delayed connect!" );
  1212. DisplayDNError( 0, hr );
  1213. goto Failure;
  1214. }
  1215. //
  1216. // this endpoint has been handed off, remove our reference to it
  1217. //
  1218. pEndpoint = NULL;
  1219. DNASSERT( hr == DPNERR_PENDING );
  1220. break;
  1221. }
  1222. default:
  1223. {
  1224. hr = hTempResult;
  1225. DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Problem initializing endpoint!" );
  1226. DisplayDNError( 0, hTempResult );
  1227. goto Failure;
  1228. break;
  1229. }
  1230. }
  1231. Exit:
  1232. DNASSERT( pEndpoint == NULL );
  1233. if ( hr != DPNERR_PENDING )
  1234. {
  1235. DNASSERT( hr != DPN_OK );
  1236. DPFX(DPFPREP, 0, "Problem with DNMODEMSP_EnumQuery" );
  1237. DisplayDNError( 0, hr );
  1238. }
  1239. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1240. return hr;
  1241. Failure:
  1242. if ( pEndpoint != NULL )
  1243. {
  1244. if ( fEndpointOpen != FALSE )
  1245. {
  1246. DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
  1247. pEndpoint->Close( hr );
  1248. fEndpointOpen = FALSE;
  1249. }
  1250. DNASSERT( FALSE );
  1251. pSPData->CloseEndpointHandle( pEndpoint );
  1252. pEndpoint = NULL;
  1253. }
  1254. //
  1255. // return any outstanding command
  1256. //
  1257. if ( pCommand != NULL )
  1258. {
  1259. pCommand->DecRef();
  1260. pCommand = NULL;
  1261. pEnumQueryData->hCommand = NULL;
  1262. pEnumQueryData->dwCommandDescriptor = NULL_DESCRIPTOR;
  1263. }
  1264. goto Exit;
  1265. }
  1266. //**********************************************************************
  1267. //**********************************************************************
  1268. /*
  1269. *
  1270. * DNMODEMSP_SendData sends data to the specified "player"
  1271. *
  1272. * This call MUST BE HIGHLY OPTIMIZED
  1273. *
  1274. */
  1275. //**********************************************************************
  1276. #undef DPF_MODNAME
  1277. #define DPF_MODNAME "DNMODEMSP_SendData"
  1278. STDMETHODIMP DNMODEMSP_SendData( IDP8ServiceProvider *pThis, SPSENDDATA *pSendData )
  1279. {
  1280. HRESULT hr;
  1281. CModemEndpoint *pEndpoint;
  1282. CModemWriteIOData *pWriteData;
  1283. CModemSPData *pSPData;
  1284. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pSendData);
  1285. DNASSERT( pThis != NULL );
  1286. DNASSERT( pSendData != NULL );
  1287. DNASSERT( pSendData->pBuffers != NULL );
  1288. DNASSERT( pSendData->dwBufferCount != 0 );
  1289. DNASSERT( pSendData->hEndpoint != INVALID_HANDLE_VALUE && pSendData->hEndpoint != 0 );
  1290. DNASSERT( pSendData->dwFlags == 0 );
  1291. //
  1292. // initialize
  1293. //
  1294. hr = DPNERR_PENDING;
  1295. pEndpoint = NULL;
  1296. pSendData->hCommand = NULL;
  1297. pSendData->dwCommandDescriptor = NULL_DESCRIPTOR;
  1298. pWriteData = NULL;
  1299. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1300. DNASSERT( pSPData->GetState() == SPSTATE_INITIALIZED );
  1301. //
  1302. // No need to lock down the thread counts here because the user already has
  1303. // a connect or something running or they wouldn't be calling this function.
  1304. // That outstanding connect would have locked down the thread pool.
  1305. //
  1306. //
  1307. // Attempt to grab the endpoint from the handle. If this succeeds, the
  1308. // endpoint can send.
  1309. //
  1310. pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pSendData->hEndpoint );
  1311. if ( pEndpoint == NULL )
  1312. {
  1313. hr = DPNERR_INVALIDHANDLE;
  1314. DPFX(DPFPREP, 0, "Invalid endpoint handle on send!" );
  1315. goto Failure;
  1316. }
  1317. //
  1318. // send data from pool
  1319. //
  1320. pWriteData = pSPData->GetThreadPool()->CreateWriteIOData();
  1321. if ( pWriteData == NULL )
  1322. {
  1323. hr = DPNERR_OUTOFMEMORY;
  1324. DPFX(DPFPREP, 0, "Cannot get new write data from pool in SendData!" );
  1325. goto Failure;
  1326. }
  1327. DNASSERT( pWriteData->m_pCommand != NULL );
  1328. DNASSERT( pWriteData->DataPort() == NULL );
  1329. //
  1330. // set the command state and fill in the message information
  1331. //
  1332. pWriteData->m_pCommand->SetType( COMMAND_TYPE_SEND );
  1333. pWriteData->m_pCommand->SetState( COMMAND_STATE_PENDING );
  1334. pWriteData->m_pCommand->SetEndpoint( pEndpoint );
  1335. pWriteData->m_pCommand->SetUserContext( pSendData->pvContext );
  1336. DNASSERT( pWriteData->m_SendCompleteAction == SEND_COMPLETE_ACTION_UNKNOWN );
  1337. pWriteData->m_SendCompleteAction = SEND_COMPLETE_ACTION_COMPLETE_COMMAND;
  1338. DNASSERT( pSendData->dwBufferCount != 0 );
  1339. pWriteData->m_uBufferCount = pSendData->dwBufferCount;
  1340. pWriteData->m_pBuffers = pSendData->pBuffers;
  1341. pSendData->hCommand = pWriteData->m_pCommand;
  1342. pSendData->dwCommandDescriptor = pWriteData->m_pCommand->GetDescriptor();
  1343. //
  1344. // send data through the endpoint
  1345. //
  1346. pEndpoint->SendUserData( pWriteData );
  1347. Exit:
  1348. if ( pEndpoint != NULL )
  1349. {
  1350. pEndpoint->DecCommandRef();
  1351. pEndpoint = NULL;
  1352. }
  1353. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1354. return hr;
  1355. Failure:
  1356. if ( pWriteData != NULL )
  1357. {
  1358. pSPData->GetThreadPool()->ReturnWriteIOData( pWriteData );
  1359. DEBUG_ONLY( pWriteData = NULL );
  1360. }
  1361. goto Exit;
  1362. }
  1363. //**********************************************************************
  1364. //**********************************************************************
  1365. // ------------------------------
  1366. // DNMODEMSP_CancelCommand - cancels a command in progress
  1367. //
  1368. // Entry: Pointer to the service provider interface
  1369. // Handle of command
  1370. // Command descriptor
  1371. //
  1372. // Exit: Error Code
  1373. // ------------------------------
  1374. #undef DPF_MODNAME
  1375. #define DPF_MODNAME "DNMODEMSP_CancelCommand"
  1376. STDMETHODIMP DNMODEMSP_CancelCommand( IDP8ServiceProvider *pThis, HANDLE hCommand, DWORD dwCommandDescriptor )
  1377. {
  1378. HRESULT hr;
  1379. CModemSPData *pSPData;
  1380. CModemCommandData *pCommandData;
  1381. BOOL fReferenceAdded;
  1382. BOOL fCommandLocked;
  1383. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p, %ld)", pThis, hCommand, dwCommandDescriptor);
  1384. DNASSERT( pThis != NULL );
  1385. DNASSERT( hCommand != NULL );
  1386. DNASSERT( dwCommandDescriptor != NULL_DESCRIPTOR );
  1387. //
  1388. // initialize
  1389. //
  1390. hr = DPN_OK;
  1391. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1392. pCommandData = NULL;
  1393. fReferenceAdded = FALSE;
  1394. fCommandLocked = FALSE;
  1395. //
  1396. // vlidate state
  1397. //
  1398. pSPData->Lock();
  1399. switch ( pSPData->GetState() )
  1400. {
  1401. //
  1402. // provider initialized
  1403. //
  1404. case SPSTATE_INITIALIZED:
  1405. {
  1406. DNASSERT( hr == DPN_OK );
  1407. IDP8ServiceProvider_AddRef( pThis );
  1408. fReferenceAdded = TRUE;
  1409. break;
  1410. }
  1411. //
  1412. // provider is uninitialized
  1413. //
  1414. case SPSTATE_UNINITIALIZED:
  1415. {
  1416. hr = DPNERR_UNINITIALIZED;
  1417. DPFX(DPFPREP, 0, "Disconnect called on uninitialized SP!" );
  1418. DNASSERT( FALSE );
  1419. goto Exit;
  1420. break;
  1421. }
  1422. //
  1423. // provider is closing
  1424. //
  1425. case SPSTATE_CLOSING:
  1426. {
  1427. hr = DPNERR_ABORTED;
  1428. DPFX(DPFPREP, 0, "Disconnect called on closing SP!" );
  1429. DNASSERT( FALSE );
  1430. goto Exit;
  1431. break;
  1432. }
  1433. //
  1434. // unknown
  1435. //
  1436. default:
  1437. {
  1438. hr = DPNERR_GENERIC;
  1439. DNASSERT( FALSE );
  1440. goto Exit;
  1441. break;
  1442. }
  1443. }
  1444. pSPData->Unlock();
  1445. if ( hr != DPN_OK )
  1446. {
  1447. goto Exit;
  1448. }
  1449. pCommandData = static_cast<CModemCommandData*>( hCommand );
  1450. pCommandData->Lock();
  1451. fCommandLocked = TRUE;
  1452. //
  1453. // this should never happen
  1454. //
  1455. if ( pCommandData->GetDescriptor() != dwCommandDescriptor )
  1456. {
  1457. hr = DPNERR_INVALIDCOMMAND;
  1458. DPFX(DPFPREP, 0, "Attempt to cancel command with mismatched command descriptor!" );
  1459. goto Exit;
  1460. }
  1461. switch ( pCommandData->GetState() )
  1462. {
  1463. //
  1464. // unknown command state
  1465. //
  1466. case COMMAND_STATE_UNKNOWN:
  1467. {
  1468. hr = DPNERR_INVALIDCOMMAND;
  1469. DNASSERT( FALSE );
  1470. break;
  1471. }
  1472. //
  1473. // command is waiting to be processed, set command state to be cancelling
  1474. // and wait for someone to pick it up
  1475. //
  1476. case COMMAND_STATE_PENDING:
  1477. {
  1478. pCommandData->SetState( COMMAND_STATE_CANCELLING );
  1479. break;
  1480. }
  1481. //
  1482. // command in progress, and can't be cancelled
  1483. //
  1484. case COMMAND_STATE_INPROGRESS_CANNOT_CANCEL:
  1485. {
  1486. hr = DPNERR_CANNOTCANCEL;
  1487. break;
  1488. }
  1489. //
  1490. // Command is already being cancelled. This is not a problem, but shouldn't
  1491. // be happening.
  1492. //
  1493. case COMMAND_STATE_CANCELLING:
  1494. {
  1495. DNASSERT( hr == DPN_OK );
  1496. DNASSERT( FALSE );
  1497. break;
  1498. }
  1499. //
  1500. // command is in progress, find out what type of command it is
  1501. //
  1502. case COMMAND_STATE_INPROGRESS:
  1503. {
  1504. switch ( pCommandData->GetType() )
  1505. {
  1506. case COMMAND_TYPE_UNKNOWN:
  1507. {
  1508. // we should never be in this state!
  1509. DNASSERT( FALSE );
  1510. break;
  1511. }
  1512. case COMMAND_TYPE_CONNECT:
  1513. {
  1514. // we should never be in this state!
  1515. DNASSERT( FALSE );
  1516. break;
  1517. }
  1518. case COMMAND_TYPE_LISTEN:
  1519. {
  1520. CModemEndpoint *pEndpoint;
  1521. //
  1522. // set this command to the cancel state before we shut down
  1523. // this endpoint
  1524. //
  1525. pCommandData->SetState( COMMAND_STATE_CANCELLING );
  1526. pCommandData->Unlock();
  1527. fCommandLocked = FALSE;
  1528. pEndpoint = pCommandData->GetEndpoint();
  1529. pEndpoint->Lock();
  1530. switch ( pEndpoint->GetState() )
  1531. {
  1532. //
  1533. // endpoint is already disconnecting, no action needs to be taken
  1534. //
  1535. case ENDPOINT_STATE_DISCONNECTING:
  1536. {
  1537. pEndpoint->Unlock();
  1538. goto Exit;
  1539. break;
  1540. }
  1541. //
  1542. // Endpoint is listening. Flag it as Disconnecting and
  1543. // add a reference so it doesn't disappear on us
  1544. //
  1545. case ENDPOINT_STATE_LISTENING:
  1546. {
  1547. pEndpoint->SetState( ENDPOINT_STATE_DISCONNECTING );
  1548. pEndpoint->AddRef();
  1549. break;
  1550. }
  1551. //
  1552. // other state
  1553. //
  1554. default:
  1555. {
  1556. DNASSERT( FALSE );
  1557. break;
  1558. }
  1559. }
  1560. pEndpoint->Unlock();
  1561. pEndpoint->Close( DPNERR_USERCANCEL );
  1562. pSPData->CloseEndpointHandle( pEndpoint );
  1563. pEndpoint->DecRef();
  1564. break;
  1565. }
  1566. //
  1567. // Note: this code is duplicated in CModemEndpoint::ProcessTAPIMessage
  1568. //
  1569. case COMMAND_TYPE_ENUM_QUERY:
  1570. {
  1571. CModemEndpoint *pEndpoint;
  1572. pEndpoint = pCommandData->GetEndpoint();
  1573. DNASSERT( pEndpoint != NULL );
  1574. pEndpoint->AddRef();
  1575. pCommandData->SetState( COMMAND_STATE_CANCELLING );
  1576. pCommandData->Unlock();
  1577. fCommandLocked = FALSE;
  1578. pEndpoint->Lock();
  1579. pEndpoint->SetState( ENDPOINT_STATE_DISCONNECTING );
  1580. pEndpoint->Unlock();
  1581. pEndpoint->StopEnumCommand( DPNERR_USERCANCEL );
  1582. pEndpoint->DecRef();
  1583. break;
  1584. }
  1585. case COMMAND_TYPE_SEND:
  1586. {
  1587. // we should never be here
  1588. DNASSERT( FALSE );
  1589. break;
  1590. }
  1591. default:
  1592. {
  1593. DNASSERT( FALSE );
  1594. break;
  1595. }
  1596. }
  1597. break;
  1598. }
  1599. //
  1600. // other command state
  1601. //
  1602. default:
  1603. {
  1604. DNASSERT( FALSE );
  1605. break;
  1606. }
  1607. }
  1608. Exit:
  1609. if ( fCommandLocked != FALSE )
  1610. {
  1611. DNASSERT( pCommandData != NULL );
  1612. pCommandData->Unlock();
  1613. fCommandLocked = FALSE;
  1614. }
  1615. if ( fReferenceAdded != FALSE )
  1616. {
  1617. IDP8ServiceProvider_Release( pThis );
  1618. fReferenceAdded = FALSE;
  1619. }
  1620. if ( hr != DPN_OK )
  1621. {
  1622. DPFX(DPFPREP, 0, "Problem with DNMODEMSP_CancelCommand!" );
  1623. DisplayDNError( 0, hr );
  1624. }
  1625. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1626. return hr;
  1627. }
  1628. //**********************************************************************
  1629. //**********************************************************************
  1630. // ------------------------------
  1631. // DNMODEMSP_EnumRespond - send response to enumeration data
  1632. //
  1633. // Entry: Pointer to the service provider interface
  1634. // Pointer to enum response data
  1635. //
  1636. // Exit: Error Code
  1637. //
  1638. // Note: This command is supposed to be fast. All initial error checking
  1639. // will be ASSERTs so they go away in the retail build.
  1640. // ------------------------------
  1641. #undef DPF_MODNAME
  1642. #define DPF_MODNAME "DNMODEMSP_EnumRespond"
  1643. STDMETHODIMP DNMODEMSP_EnumRespond( IDP8ServiceProvider *pThis, SPENUMRESPONDDATA *pEnumRespondData )
  1644. {
  1645. HRESULT hr;
  1646. CModemEndpoint *pEndpoint;
  1647. CModemWriteIOData *pWriteData;
  1648. CModemSPData *pSPData;
  1649. const ENDPOINT_ENUM_QUERY_CONTEXT *pEnumQueryContext;
  1650. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumRespondData);
  1651. DNASSERT( pThis != NULL );
  1652. DNASSERT( pEnumRespondData != NULL );
  1653. DNASSERT( pEnumRespondData->dwFlags == 0 );
  1654. //
  1655. // initialize
  1656. //
  1657. hr = DPNERR_PENDING;
  1658. pEndpoint = NULL;
  1659. pWriteData = NULL;
  1660. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1661. DBG_CASSERT( OFFSETOF( ENDPOINT_ENUM_QUERY_CONTEXT, EnumQueryData ) == 0 );
  1662. pEnumQueryContext = reinterpret_cast<ENDPOINT_ENUM_QUERY_CONTEXT*>( pEnumRespondData->pQuery );
  1663. pEnumRespondData->hCommand = NULL;
  1664. pEnumRespondData->dwCommandDescriptor = NULL_DESCRIPTOR;
  1665. DNASSERT( pSPData->GetState() == SPSTATE_INITIALIZED );
  1666. IDP8ServiceProvider_AddRef( pThis );
  1667. //
  1668. // check for valid endpoint
  1669. //
  1670. pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pEnumQueryContext->hEndpoint );
  1671. if ( pEndpoint == NULL )
  1672. {
  1673. DNASSERT( FALSE );
  1674. hr = DPNERR_INVALIDENDPOINT;
  1675. DPFX(DPFPREP, 8, "Invalid endpoint handle in DNMODEMSP_EnumRespond" );
  1676. goto Failure;
  1677. }
  1678. //
  1679. // no need to poke at the thread pool here to lock down threads because we
  1680. // can only really be here if there's an enum and that enum locked down the
  1681. // thread pool.
  1682. //
  1683. pWriteData = pSPData->GetThreadPool()->CreateWriteIOData();
  1684. if ( pWriteData == NULL )
  1685. {
  1686. hr = DPNERR_OUTOFMEMORY;
  1687. DPFX(DPFPREP, 0, "Cannot get new WRITE_IO_DATA for enum response!" );
  1688. goto Failure;
  1689. }
  1690. pWriteData->m_pCommand->SetType( COMMAND_TYPE_SEND );
  1691. pWriteData->m_pCommand->SetState( COMMAND_STATE_PENDING );
  1692. pWriteData->m_pCommand->SetEndpoint( pEndpoint );
  1693. pWriteData->m_pCommand->SetUserContext( pEnumRespondData->pvContext );
  1694. DNASSERT( pWriteData->m_SendCompleteAction == SEND_COMPLETE_ACTION_UNKNOWN );
  1695. pWriteData->m_SendCompleteAction = SEND_COMPLETE_ACTION_COMPLETE_COMMAND;
  1696. pWriteData->m_uBufferCount = pEnumRespondData->dwBufferCount;
  1697. pWriteData->m_pBuffers = pEnumRespondData->pBuffers;
  1698. pEnumRespondData->hCommand = pWriteData->m_pCommand;
  1699. pEnumRespondData->dwCommandDescriptor = pWriteData->m_pCommand->GetDescriptor();
  1700. //
  1701. // send data
  1702. //
  1703. pEndpoint->SendEnumResponseData( pWriteData, pEnumQueryContext->uEnumRTTIndex );
  1704. Exit:
  1705. if ( pEndpoint != NULL )
  1706. {
  1707. pEndpoint->DecCommandRef();
  1708. pEndpoint = NULL;
  1709. }
  1710. IDP8ServiceProvider_Release( pThis );
  1711. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1712. return hr;
  1713. Failure:
  1714. if ( pWriteData != NULL )
  1715. {
  1716. DNASSERT( pSPData != NULL );
  1717. pSPData->GetThreadPool()->ReturnWriteIOData( pWriteData );
  1718. pEnumRespondData->hCommand = NULL;
  1719. pEnumRespondData->dwCommandDescriptor = NULL_DESCRIPTOR;
  1720. pWriteData = NULL;
  1721. }
  1722. goto Exit;
  1723. }
  1724. //**********************************************************************
  1725. //**********************************************************************
  1726. // ------------------------------
  1727. // DNMODEMSP_IsApplicationSupported - determine if this application is supported by this
  1728. // SP.
  1729. //
  1730. // Entry: Pointer to DNSP Interface
  1731. // Pointer to input data
  1732. //
  1733. // Exit: Error code
  1734. // ------------------------------
  1735. #undef DPF_MODNAME
  1736. #define DPF_MODNAME "DNMODEMSP_IsApplicationSupported"
  1737. STDMETHODIMP DNMODEMSP_IsApplicationSupported( IDP8ServiceProvider *pThis, SPISAPPLICATIONSUPPORTEDDATA *pIsApplicationSupportedData )
  1738. {
  1739. HRESULT hr;
  1740. BOOL fInterfaceReferenceAdded;
  1741. CModemSPData *pSPData;
  1742. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pIsApplicationSupportedData);
  1743. DNASSERT( pThis != NULL );
  1744. DNASSERT( pIsApplicationSupportedData != NULL );
  1745. DNASSERT( pIsApplicationSupportedData->pApplicationGuid != NULL );
  1746. DNASSERT( pIsApplicationSupportedData->dwFlags == 0 );
  1747. //
  1748. // initialize, we support all applications with this SP
  1749. //
  1750. hr = DPN_OK;
  1751. fInterfaceReferenceAdded = FALSE;
  1752. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1753. //
  1754. // no need to tell thread pool to lock the thread count for this function.
  1755. //
  1756. //
  1757. // validate SP state
  1758. //
  1759. pSPData->Lock();
  1760. switch ( pSPData->GetState() )
  1761. {
  1762. //
  1763. // provider is initialized, add a reference and proceed
  1764. //
  1765. case SPSTATE_INITIALIZED:
  1766. {
  1767. IDP8ServiceProvider_AddRef( pThis );
  1768. fInterfaceReferenceAdded = TRUE;
  1769. DNASSERT( hr == DPN_OK );
  1770. break;
  1771. }
  1772. //
  1773. // provider is uninitialized
  1774. //
  1775. case SPSTATE_UNINITIALIZED:
  1776. {
  1777. hr = DPNERR_UNINITIALIZED;
  1778. DPFX(DPFPREP, 0, "IsApplicationSupported called on uninitialized SP!" );
  1779. break;
  1780. }
  1781. //
  1782. // provider is closing
  1783. //
  1784. case SPSTATE_CLOSING:
  1785. {
  1786. hr = DPNERR_ABORTED;
  1787. DPFX(DPFPREP, 0, "IsApplicationSupported called while SP closing!" );
  1788. break;
  1789. }
  1790. //
  1791. // unknown
  1792. //
  1793. default:
  1794. {
  1795. DNASSERT( FALSE );
  1796. hr = DPNERR_GENERIC;
  1797. break;
  1798. }
  1799. }
  1800. pSPData->Unlock();
  1801. if ( hr != DPN_OK )
  1802. {
  1803. goto Failure;
  1804. }
  1805. Exit:
  1806. if ( fInterfaceReferenceAdded != FALSE )
  1807. {
  1808. IDP8ServiceProvider_Release( pThis );
  1809. fInterfaceReferenceAdded = FALSE;
  1810. }
  1811. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1812. return hr;
  1813. Failure:
  1814. goto Exit;
  1815. }
  1816. //**********************************************************************
  1817. //**********************************************************************
  1818. // ------------------------------
  1819. // DNMODEMSP_GetCaps - get SP or endpoint capabilities
  1820. //
  1821. // Entry: Pointer to DirectPlay
  1822. // Pointer to caps data to fill
  1823. //
  1824. // Exit: Error Code
  1825. // ------------------------------
  1826. #undef DPF_MODNAME
  1827. #define DPF_MODNAME "DNMODEMSP_GetCaps"
  1828. STDMETHODIMP DNMODEMSP_GetCaps( IDP8ServiceProvider *pThis, SPGETCAPSDATA *pCapsData )
  1829. {
  1830. HRESULT hr;
  1831. LONG iIOThreadCount;
  1832. CModemSPData *pSPData = NULL;
  1833. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pCapsData);
  1834. DNASSERT( pThis != NULL );
  1835. DNASSERT( pCapsData != NULL );
  1836. DNASSERT( pCapsData->dwSize == sizeof( *pCapsData ) );
  1837. DNASSERT( pCapsData->hEndpoint == INVALID_HANDLE_VALUE );
  1838. //
  1839. // initialize
  1840. //
  1841. hr = DPN_OK;
  1842. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1843. //
  1844. // there are no flags for this SP
  1845. //
  1846. pCapsData->dwFlags = 0;
  1847. //
  1848. // set frame sizes
  1849. //
  1850. pCapsData->dwUserFrameSize = MAX_USER_PAYLOAD;
  1851. pCapsData->dwEnumFrameSize = 1000;
  1852. //
  1853. // get link speed
  1854. //
  1855. if ( pCapsData->hEndpoint != INVALID_HANDLE_VALUE )
  1856. {
  1857. // TODO: MASONB: I see no path where this is ever used
  1858. CModemEndpoint *pEndpoint;
  1859. pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pCapsData->hEndpoint );
  1860. if ( pEndpoint != NULL )
  1861. {
  1862. pCapsData->dwLocalLinkSpeed = pEndpoint->GetLinkSpeed();
  1863. pEndpoint->DecCommandRef();
  1864. }
  1865. else
  1866. {
  1867. hr = DPNERR_INVALIDENDPOINT;
  1868. DPFX(DPFPREP, 0, "Invalid endpoint specified to GetCaps()" );
  1869. goto Failure;
  1870. }
  1871. }
  1872. else
  1873. {
  1874. pCapsData->dwLocalLinkSpeed = CBR_256000;
  1875. }
  1876. //
  1877. // get IO thread count
  1878. //
  1879. hr = pSPData->GetThreadPool()->GetIOThreadCount( &iIOThreadCount );
  1880. if ( hr != DPN_OK )
  1881. {
  1882. DPFX(DPFPREP, 0, "DNMODEMSP_GetCaps: Failed to get thread pool count!" );
  1883. DisplayDNError( 0, hr );
  1884. goto Failure;
  1885. }
  1886. pCapsData->dwIOThreadCount = iIOThreadCount;
  1887. //
  1888. // set enumeration defaults
  1889. //
  1890. pCapsData->dwDefaultEnumRetryCount = DEFAULT_ENUM_RETRY_COUNT;
  1891. pCapsData->dwDefaultEnumRetryInterval = DEFAULT_ENUM_RETRY_INTERVAL;
  1892. pCapsData->dwDefaultEnumTimeout = DEFAULT_ENUM_TIMEOUT;
  1893. pCapsData->dwBuffersPerThread = 1;
  1894. pCapsData->dwSystemBufferSize = 0;
  1895. Exit:
  1896. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  1897. return hr;
  1898. Failure:
  1899. goto Exit;
  1900. }
  1901. //**********************************************************************
  1902. //**********************************************************************
  1903. // ------------------------------
  1904. // DNMODEMSP_SetCaps - set SP capabilities
  1905. //
  1906. // Entry: Pointer to DirectPlay
  1907. // Pointer to caps data to use
  1908. //
  1909. // Exit: Error Code
  1910. // ------------------------------
  1911. #undef DPF_MODNAME
  1912. #define DPF_MODNAME "DNMODEMSP_SetCaps"
  1913. STDMETHODIMP DNMODEMSP_SetCaps( IDP8ServiceProvider *pThis, SPSETCAPSDATA *pCapsData )
  1914. {
  1915. HRESULT hr;
  1916. BOOL fInterfaceReferenceAdded;
  1917. CModemSPData *pSPData;
  1918. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pCapsData);
  1919. DNASSERT( pThis != NULL );
  1920. DNASSERT( pCapsData != NULL );
  1921. DNASSERT( pCapsData->dwSize == sizeof( *pCapsData ) );
  1922. //
  1923. // initialize
  1924. //
  1925. hr = DPN_OK;
  1926. fInterfaceReferenceAdded = FALSE;
  1927. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  1928. //
  1929. // no need to tell thread pool to lock the thread count for this function.
  1930. //
  1931. //
  1932. // validate SP state
  1933. //
  1934. pSPData->Lock();
  1935. switch ( pSPData->GetState() )
  1936. {
  1937. //
  1938. // provider is initialized, add a reference and proceed
  1939. //
  1940. case SPSTATE_INITIALIZED:
  1941. {
  1942. IDP8ServiceProvider_AddRef( pThis );
  1943. fInterfaceReferenceAdded = TRUE;
  1944. DNASSERT( hr == DPN_OK );
  1945. break;
  1946. }
  1947. //
  1948. // provider is uninitialized
  1949. //
  1950. case SPSTATE_UNINITIALIZED:
  1951. {
  1952. hr = DPNERR_UNINITIALIZED;
  1953. DPFX(DPFPREP, 0, "AddToGroup called on uninitialized SP!" );
  1954. break;
  1955. }
  1956. //
  1957. // provider is closing
  1958. //
  1959. case SPSTATE_CLOSING:
  1960. {
  1961. hr = DPNERR_ABORTED;
  1962. DPFX(DPFPREP, 0, "AddToGroup called while SP closing!" );
  1963. break;
  1964. }
  1965. //
  1966. // unknown
  1967. //
  1968. default:
  1969. {
  1970. DNASSERT( FALSE );
  1971. hr = DPNERR_GENERIC;
  1972. break;
  1973. }
  1974. }
  1975. pSPData->Unlock();
  1976. if ( hr != DPN_OK )
  1977. {
  1978. goto Failure;
  1979. }
  1980. //
  1981. // validate caps
  1982. //
  1983. if ( pCapsData->dwBuffersPerThread == 0 )
  1984. {
  1985. DPFX(DPFPREP, 0, "Failing SetCaps because dwBuffersPerThread == 0" );
  1986. hr = DPNERR_INVALIDPARAM;
  1987. goto Failure;
  1988. }
  1989. //
  1990. // change thread count, if requested
  1991. //
  1992. if (pCapsData->dwIOThreadCount != 0)
  1993. {
  1994. hr = pSPData->GetThreadPool()->SetIOThreadCount( pCapsData->dwIOThreadCount );
  1995. if ( hr != DPN_OK )
  1996. {
  1997. DPFX(DPFPREP, 0, "DNMODEMSP_SetCaps: Failed to set thread pool count!" );
  1998. DisplayDNError( 0, hr );
  1999. goto Failure;
  2000. }
  2001. }
  2002. Exit:
  2003. if ( fInterfaceReferenceAdded != FALSE )
  2004. {
  2005. IDP8ServiceProvider_Release( pThis );
  2006. fInterfaceReferenceAdded = FALSE;
  2007. }
  2008. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  2009. return hr;
  2010. Failure:
  2011. goto Exit;
  2012. }
  2013. //**********************************************************************
  2014. //**********************************************************************
  2015. // ------------------------------
  2016. // DNMODEMSP_ReturnReceiveBuffers - return receive buffers to pool
  2017. //
  2018. // Entry: Pointer to DNSP interface
  2019. // Pointer to caps data
  2020. //
  2021. // Exit: Error code
  2022. // ------------------------------
  2023. #undef DPF_MODNAME
  2024. #define DPF_MODNAME "DNMODEMSP_ReturnReceiveBuffers"
  2025. STDMETHODIMP DNMODEMSP_ReturnReceiveBuffers( IDP8ServiceProvider *pThis, SPRECEIVEDBUFFER *pReceivedBuffers )
  2026. {
  2027. SPRECEIVEDBUFFER *pBuffers;
  2028. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pReceivedBuffers);
  2029. //
  2030. // no need to tell thread pool to lock the thread count for this function.
  2031. //
  2032. DNASSERT( pThis != NULL );
  2033. DNASSERT( pReceivedBuffers != NULL );
  2034. pBuffers = pReceivedBuffers;
  2035. while ( pBuffers != NULL )
  2036. {
  2037. SPRECEIVEDBUFFER *pTemp;
  2038. CModemReadIOData *pReadData;
  2039. pTemp = pBuffers;
  2040. pBuffers = pBuffers->pNext;
  2041. pReadData = CModemReadIOData::ReadDataFromSPReceivedBuffer( pTemp );
  2042. pReadData->DecRef();
  2043. }
  2044. DPFX(DPFPREP, 2, "Returning: [DPN_OK]");
  2045. return DPN_OK;
  2046. }
  2047. //**********************************************************************
  2048. //**********************************************************************
  2049. // ------------------------------
  2050. // DNMODEMSP_GetAddressInfo - get address information
  2051. //
  2052. // Entry: Pointer to service provider interface
  2053. // Pointer to get address data
  2054. //
  2055. // Exit: Error code
  2056. // ------------------------------
  2057. #undef DPF_MODNAME
  2058. #define DPF_MODNAME "DNMODEMSP_GetAddressInfo"
  2059. STDMETHODIMP DNMODEMSP_GetAddressInfo( IDP8ServiceProvider *pThis, SPGETADDRESSINFODATA *pGetAddressInfoData )
  2060. {
  2061. HRESULT hr;
  2062. CModemSPData *pSPData;
  2063. CModemEndpoint *pEndpoint;
  2064. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pGetAddressInfoData);
  2065. DNASSERT( pThis != NULL );
  2066. DNASSERT( pGetAddressInfoData != NULL );
  2067. DNASSERT( pGetAddressInfoData->hEndpoint != INVALID_HANDLE_VALUE && pGetAddressInfoData->hEndpoint != 0 );
  2068. DNASSERT( ( pGetAddressInfoData->Flags & ~( SP_GET_ADDRESS_INFO_LOCAL_ADAPTER |
  2069. SP_GET_ADDRESS_INFO_REMOTE_HOST |
  2070. SP_GET_ADDRESS_INFO_LISTEN_HOST_ADDRESSES |
  2071. SP_GET_ADDRESS_INFO_LOCAL_HOST_PUBLIC_ADDRESS ) ) == 0 );
  2072. //
  2073. // initialize
  2074. //
  2075. hr = DPN_OK;
  2076. pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  2077. pGetAddressInfoData->pAddress = NULL;
  2078. pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pGetAddressInfoData->hEndpoint );
  2079. if ( pEndpoint != NULL )
  2080. {
  2081. switch ( pGetAddressInfoData->Flags )
  2082. {
  2083. case SP_GET_ADDRESS_INFO_REMOTE_HOST:
  2084. {
  2085. pGetAddressInfoData->pAddress = pEndpoint->GetRemoteHostDP8Address();
  2086. break;
  2087. }
  2088. //
  2089. // there is no concept of a 'public' address for this service provider so
  2090. // all local addresses are the same
  2091. //
  2092. case SP_GET_ADDRESS_INFO_LOCAL_ADAPTER:
  2093. {
  2094. pGetAddressInfoData->pAddress = pEndpoint->GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
  2095. break;
  2096. }
  2097. case SP_GET_ADDRESS_INFO_LOCAL_HOST_PUBLIC_ADDRESS:
  2098. case SP_GET_ADDRESS_INFO_LISTEN_HOST_ADDRESSES:
  2099. {
  2100. pGetAddressInfoData->pAddress = pEndpoint->GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER_HOST_FORMAT );
  2101. break;
  2102. }
  2103. default:
  2104. {
  2105. DNASSERT( FALSE );
  2106. break;
  2107. }
  2108. }
  2109. pEndpoint->DecCommandRef();
  2110. pEndpoint = NULL;
  2111. }
  2112. else
  2113. {
  2114. hr = DPNERR_INVALIDENDPOINT;
  2115. }
  2116. if ( hr != DPN_OK )
  2117. {
  2118. DPFX(DPFPREP, 0, "Problem getting DP8Address from endpoint!" );
  2119. DisplayDNError( 0, hr );
  2120. }
  2121. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  2122. return hr;
  2123. }
  2124. //**********************************************************************
  2125. //**********************************************************************
  2126. // ------------------------------
  2127. // DNMODEMSP_EnumAdapters - enumerate adapters for this SP
  2128. //
  2129. // Entry: Pointer to service provider interface
  2130. // Pointer to enum adapters data
  2131. //
  2132. // Exit: Error code
  2133. // ------------------------------
  2134. #undef DPF_MODNAME
  2135. #define DPF_MODNAME "DNMODEMSP_EnumAdapters"
  2136. STDMETHODIMP DNMODEMSP_EnumAdapters( IDP8ServiceProvider *pThis, SPENUMADAPTERSDATA *pEnumAdaptersData )
  2137. {
  2138. HRESULT hr;
  2139. CDataPort *pDataPort;
  2140. DATA_PORT_POOL_CONTEXT DataPortPoolContext;
  2141. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumAdaptersData);
  2142. DNASSERT( pThis != NULL );
  2143. DNASSERT( pEnumAdaptersData->dwFlags == 0 );
  2144. DNASSERT( ( pEnumAdaptersData->pAdapterData != NULL ) ||
  2145. ( pEnumAdaptersData->dwAdapterDataSize == 0 ) );
  2146. //
  2147. // intialize
  2148. //
  2149. hr = DPN_OK;
  2150. pDataPort = NULL;
  2151. pEnumAdaptersData->dwAdapterCount = 0;
  2152. DataPortPoolContext.pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
  2153. pDataPort = CreateDataPort( &DataPortPoolContext );
  2154. if ( pDataPort == NULL )
  2155. {
  2156. hr = DPNERR_OUTOFMEMORY;
  2157. DPFX(DPFPREP, 0, "Problem getting new dataport!" );
  2158. goto Failure;
  2159. }
  2160. hr = pDataPort->EnumAdapters( pEnumAdaptersData );
  2161. if ( hr != DPN_OK )
  2162. {
  2163. if (hr != DPNERR_BUFFERTOOSMALL)
  2164. {
  2165. DPFX(DPFPREP, 0, "Problem enumerating adapters!" );
  2166. DisplayDNError( 0, hr );
  2167. }
  2168. else
  2169. {
  2170. DPFX(DPFPREP, 1, "Buffer too small to enumerate adapters." );
  2171. }
  2172. goto Failure;
  2173. }
  2174. Exit:
  2175. if ( pDataPort != NULL )
  2176. {
  2177. pDataPort->DecRef();
  2178. pDataPort = NULL;
  2179. }
  2180. DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
  2181. return hr;
  2182. Failure:
  2183. goto Exit;
  2184. }
  2185. //**********************************************************************
  2186. //**********************************************************************
  2187. /*
  2188. *
  2189. * DNMODEMSP_NotSupported is used for methods required to implement the
  2190. * interface but that are not supported by this SP.
  2191. *
  2192. */
  2193. //**********************************************************************
  2194. #undef DPF_MODNAME
  2195. #define DPF_MODNAME "DNMODEMSP_NotSupported"
  2196. STDMETHODIMP DNMODEMSP_NotSupported( IDP8ServiceProvider *pThis, PVOID pvParam )
  2197. {
  2198. DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pvParam);
  2199. DPFX(DPFPREP, 2, "Returning: [DPNERR_UNSUPPORTED]");
  2200. return DPNERR_UNSUPPORTED;
  2201. }
  2202. //**********************************************************************