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
2618 lines
59 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1998-2000 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: SerialSP.cpp
|
|
* Content: Service provider serial interface functions
|
|
*
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 12/03/98 jtk Created
|
|
* 09/23/99 jtk Derived from ComCore.cpp
|
|
***************************************************************************/
|
|
|
|
#include "dnmdmi.h"
|
|
|
|
|
|
//**********************************************************************
|
|
// Constant definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Macro definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Structure definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Variable definitions
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function prototypes
|
|
//**********************************************************************
|
|
|
|
//**********************************************************************
|
|
// Function definitions
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_AddRef - increment interface reference cound
|
|
//
|
|
// Entry: Pointer to interface
|
|
//
|
|
// Exit: Current interface reference count
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_AddRef"
|
|
|
|
STDMETHODIMP_(ULONG) DNMODEMSP_AddRef( IDP8ServiceProvider *pThis )
|
|
{
|
|
CModemSPData * pSPData;
|
|
ULONG ulResult;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p)", pThis);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
ulResult = pSPData->AddRef();
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%u]", ulResult);
|
|
|
|
return ulResult;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Release - release an interface
|
|
//
|
|
// Entry: Pointer to current interface
|
|
// Desired interface ID
|
|
// Pointer to pointer to new interface
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Release"
|
|
|
|
STDMETHODIMP_(ULONG) DNMODEMSP_Release( IDP8ServiceProvider *pThis )
|
|
{
|
|
CModemSPData * pSPData;
|
|
ULONG ulResult;
|
|
|
|
|
|
DNASSERT( pThis != NULL );
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
ulResult = pSPData->DecRef();
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%u]", ulResult);
|
|
|
|
return ulResult;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Initialize - initialize SP interface
|
|
//
|
|
// Entry: Pointer to interface
|
|
// Pointer to initialization data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Initialize"
|
|
|
|
STDMETHODIMP DNMODEMSP_Initialize( IDP8ServiceProvider *pThis, SPINITIALIZEDATA *pData )
|
|
{
|
|
HRESULT hr;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pData != NULL );
|
|
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
//
|
|
// prevent anyone else from messing with this interface and bump up the reference
|
|
// count
|
|
//
|
|
pSPData->Lock();
|
|
|
|
//
|
|
// check interface state
|
|
//
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// uninitialized interface, we can initialize it
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other state
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
case SPSTATE_CLOSING:
|
|
default:
|
|
{
|
|
hr = DPNERR_ALREADYINITIALIZED;
|
|
DPFX(DPFPREP, 0, "Attempted to reinitialize interface!" );
|
|
DNASSERT( FALSE );
|
|
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// before we get too far, check for the availablility of serial ports or
|
|
// modems
|
|
//
|
|
switch ( pSPData->GetType() )
|
|
{
|
|
case TYPE_SERIAL:
|
|
{
|
|
BOOL fPortAvailable[ MAX_DATA_PORTS ];
|
|
DWORD dwPortCount;
|
|
|
|
|
|
hr = GenerateAvailableComPortList( fPortAvailable, ( LENGTHOF( fPortAvailable ) - 1 ), &dwPortCount );
|
|
if ( ( hr != DPN_OK ) || ( dwPortCount == 0 ) )
|
|
{
|
|
hr = DPNERR_UNSUPPORTED;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case TYPE_MODEM:
|
|
{
|
|
if ( pSPData->GetThreadPool()->TAPIAvailable() != FALSE )
|
|
{
|
|
DWORD dwModemCount;
|
|
DWORD dwModemNameDataSize;
|
|
HRESULT hTempResult;
|
|
|
|
|
|
//
|
|
// Get count of available modems. If this call succeeds but there
|
|
// are no modems returned, fail.
|
|
//
|
|
dwModemCount = 0;
|
|
dwModemNameDataSize = 0;
|
|
hTempResult = GenerateAvailableModemList( pSPData->GetThreadPool()->GetTAPIInfo(),
|
|
&dwModemCount,
|
|
NULL,
|
|
&dwModemNameDataSize );
|
|
if ( ( hTempResult != DPNERR_BUFFERTOOSMALL ) && ( hTempResult != DPN_OK ) )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to detect available modems!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
if ( dwModemCount == 0 )
|
|
{
|
|
DPFX(DPFPREP, 1, "No modems detected!" );
|
|
hr = DPNERR_UNSUPPORTED;
|
|
goto Failure;
|
|
}
|
|
|
|
DNASSERT( hr == DPN_OK );
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 0, "TAPI not available!" );
|
|
hr = DPNERR_UNSUPPORTED;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// remember the init data
|
|
//
|
|
pSPData->SetCallbackData( pData );
|
|
|
|
//
|
|
// Success from here on in
|
|
//
|
|
IDP8SPCallback_AddRef( pSPData->DP8SPCallbackInterface() );
|
|
pSPData->SetState( SPSTATE_INITIALIZED );
|
|
pSPData->Unlock();
|
|
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
pSPData->Unlock();
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Close - close this instance of the service provier
|
|
//
|
|
// Entry: Pointer to the service provider to close
|
|
//
|
|
// Exit: Error Code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Close"
|
|
|
|
STDMETHODIMP DNMODEMSP_Close( IDP8ServiceProvider *pThis )
|
|
{
|
|
HRESULT hr;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p)", pThis);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
switch ( pSPData->GetType() )
|
|
{
|
|
case TYPE_SERIAL:
|
|
case TYPE_MODEM:
|
|
{
|
|
//
|
|
// release our ref to the DPlay callbacks
|
|
//
|
|
pSPData->Shutdown();
|
|
IDP8ServiceProvider_Release( pThis );
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Connect - start process to establish comport connection to a remote host
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Pointer to connection data
|
|
//
|
|
// Exit: Error Code
|
|
//
|
|
// Note: Any command handle allocated by this function is closed by the
|
|
// endpoint.
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Connect"
|
|
|
|
STDMETHODIMP DNMODEMSP_Connect( IDP8ServiceProvider *pThis, SPCONNECTDATA *pConnectData )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hTempResult;
|
|
CModemSPData *pSPData;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemCommandData *pCommand;
|
|
BOOL fEndpointOpen;
|
|
GUID DeviceGUID;
|
|
GUID guidnull;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pConnectData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pConnectData != NULL );
|
|
DNASSERT( pConnectData->pAddressHost != NULL );
|
|
DNASSERT( pConnectData->pAddressDeviceInfo != NULL );
|
|
DNASSERT( ( pConnectData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
|
|
DNASSERT( ( pConnectData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
|
|
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPNERR_PENDING;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pEndpoint = NULL;
|
|
pCommand = NULL;
|
|
fEndpointOpen = FALSE;
|
|
pConnectData->hCommand = NULL;
|
|
pConnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
memset(&guidnull, 0, sizeof(guidnull));
|
|
|
|
|
|
//
|
|
// the user is attempting an operation that relies on the thread pool, lock
|
|
// it down to prevent threads from being lost.
|
|
//
|
|
hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// validate state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect called on uninitialized SP!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect called while SP closing!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
DNASSERT( hr != DPN_OK );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// check for invalid device ID
|
|
//
|
|
hTempResult = IDirectPlay8Address_GetDevice( pConnectData->pAddressDeviceInfo, &DeviceGUID );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// there was a device ID, check against GUID_NULL
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
|
|
{
|
|
hr = DPNERR_ADDRESSING;
|
|
DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
|
|
goto Failure;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// no device address specified, not a problem
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other, stop and figure out why we're here
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to validate device address!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get endpoint for this connection
|
|
//
|
|
pEndpoint = pSPData->GetNewEndpoint();
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Cannot create new endpoint!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// get new command
|
|
//
|
|
pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
|
|
if ( pCommand == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Cannot get command handle!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// initialize command
|
|
//
|
|
pConnectData->hCommand = pCommand;
|
|
pConnectData->dwCommandDescriptor = pCommand->GetDescriptor();
|
|
pCommand->SetType( COMMAND_TYPE_CONNECT );
|
|
pCommand->SetState( COMMAND_STATE_PENDING );
|
|
pCommand->SetEndpoint( pEndpoint );
|
|
|
|
//
|
|
// open this endpoint
|
|
//
|
|
hTempResult = pEndpoint->Open( pConnectData->pAddressHost,
|
|
pConnectData->pAddressDeviceInfo,
|
|
LINK_DIRECTION_OUTGOING,
|
|
ENDPOINT_TYPE_CONNECT );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// endpoint opened, no problem
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
//
|
|
// copy connect data and the submit background job
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyConnectData( pConnectData );
|
|
pEndpoint->AddRef();
|
|
|
|
hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->ConnectJobCallback,
|
|
pEndpoint->CancelConnectJobCallback,
|
|
pEndpoint );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
pEndpoint->DecRef();
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to set delayed listen!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// this endpoint has been handed off, remove our reference to it
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// not all of the addressing information was specifed, need to query user
|
|
//
|
|
case DPNERR_INCOMPLETEADDRESS:
|
|
{
|
|
#ifndef DPNBUILD_NOSPUI
|
|
if ( ( pConnectData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
|
|
{
|
|
//
|
|
// copy connect data for future reference and then start the dialog
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyConnectData( pConnectData );
|
|
|
|
hTempResult = pEndpoint->ShowOutgoingSettingsDialog( pSPData->GetThreadPool() );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Problem showing settings dialog!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// this endpoint has been handed off, remove our reference to it
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
|
|
goto Exit;
|
|
}
|
|
else
|
|
#endif // !DPNBUILD_NOSPUI
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Connect: Problem opening endpoint with host address!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
}
|
|
Exit:
|
|
DNASSERT( pEndpoint == NULL );
|
|
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
// this command cannot complete synchronously!
|
|
DNASSERT( hr != DPN_OK );
|
|
|
|
DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Connect()" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
//
|
|
// return any outstanding endpoint
|
|
//
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
if ( fEndpointOpen != FALSE )
|
|
{
|
|
DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
|
|
pEndpoint->Close( hr );
|
|
fEndpointOpen = FALSE;
|
|
}
|
|
|
|
pSPData->CloseEndpointHandle( pEndpoint );
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
//
|
|
// return any outstanding command
|
|
//
|
|
if ( pCommand != NULL )
|
|
{
|
|
pCommand->DecRef();
|
|
pCommand = NULL;
|
|
pConnectData->hCommand = NULL;
|
|
pConnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Disconnect - disconnect from a remote host
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Pointer to connection data
|
|
//
|
|
// Exit: Error Code
|
|
//
|
|
// Note: This command is considered final, there's no chance to cancel a
|
|
// disconnect.
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Disconnect"
|
|
|
|
STDMETHODIMP DNMODEMSP_Disconnect( IDP8ServiceProvider *pThis, SPDISCONNECTDATA *pDisconnectData )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hTempResult;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pDisconnectData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pDisconnectData != NULL );
|
|
DNASSERT( pDisconnectData->hEndpoint != INVALID_HANDLE_VALUE && pDisconnectData->hEndpoint != 0 );
|
|
DNASSERT( pDisconnectData->dwFlags == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pEndpoint = NULL;
|
|
pDisconnectData->hCommand = NULL;
|
|
pDisconnectData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
//
|
|
// check service provider state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
DNASSERT( hr == DPN_OK );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "Disconnect called on uninitialized SP!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "Disconnect called on closing SP!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
hr = DPNERR_GENERIC;
|
|
DNASSERT( FALSE );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPN_OK )
|
|
{
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// look up the endpoint and if it's found, close its handle
|
|
//
|
|
pEndpoint = pSPData->GetEndpointAndCloseHandle( (DPNHANDLE)(DWORD_PTR)pDisconnectData->hEndpoint );
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
hr = DPNERR_INVALIDENDPOINT;
|
|
goto Failure;
|
|
}
|
|
|
|
hTempResult = pEndpoint->Disconnect( (DPNHANDLE)(DWORD_PTR)pDisconnectData->hEndpoint );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// endpoint disconnected immediately
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Other return. Since the disconnect didn't complete, we need
|
|
// to unlock the endpoint.
|
|
//
|
|
default:
|
|
{
|
|
DPFX(DPFPREP, 0, "Error reported when attempting to disconnect endpoint in DNMODEMSP_Disconnect!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
//
|
|
// remove oustanding reference from GetEndpointHandleAndClose()
|
|
//
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
pEndpoint->DecRef();
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Disconnect()" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_Listen - start process to listen for comport connections
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Pointer to listen data
|
|
//
|
|
// Exit: Error Code
|
|
//
|
|
// Note: Any command handle allocated by this function is closed by the
|
|
// endpoint.
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_Listen"
|
|
|
|
STDMETHODIMP DNMODEMSP_Listen( IDP8ServiceProvider *pThis, SPLISTENDATA *pListenData )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hTempResult;
|
|
CModemSPData *pSPData;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemCommandData *pCommand;
|
|
BOOL fEndpointOpen;
|
|
BOOL fInterfaceReferenceAdded;
|
|
GUID DeviceGUID;
|
|
GUID guidnull;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pListenData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pListenData != NULL );
|
|
DNASSERT( ( pListenData->dwFlags & ~( DPNSPF_OKTOQUERY | DPNSPF_BINDLISTENTOGATEWAY | DPNSPF_LISTEN_DISALLOWENUMS ) ) == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPNERR_PENDING;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pEndpoint = NULL;
|
|
pCommand = NULL;
|
|
fEndpointOpen = FALSE;
|
|
pListenData->hCommand = NULL;
|
|
pListenData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
fInterfaceReferenceAdded = FALSE;
|
|
memset(&guidnull, 0, sizeof(guidnull));
|
|
|
|
|
|
//
|
|
// the user is attempting an operation that relies on the thread pool, lock
|
|
// it down to prevent threads from being lost.
|
|
//
|
|
hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// validate state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
fInterfaceReferenceAdded = TRUE;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Listen called on uninitialized SP!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Listen called while SP closing!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
DNASSERT( hr != DPN_OK );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// check for invalid device ID
|
|
//
|
|
hTempResult = IDirectPlay8Address_GetDevice( pListenData->pAddressDeviceInfo, &DeviceGUID );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// there was a device ID, check against GUID_NULL
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
|
|
{
|
|
hr = DPNERR_ADDRESSING;
|
|
DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
|
|
goto Failure;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// no device address specified, not a problem
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other, stop and figure out why we're here
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to validate device address!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get endpoint for this connection
|
|
//
|
|
pEndpoint = pSPData->GetNewEndpoint();
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Cannot create new endpoint!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// get new command
|
|
//
|
|
pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
|
|
if ( pCommand == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Cannot get command handle!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// initialize command
|
|
//
|
|
pListenData->hCommand = pCommand;
|
|
pListenData->dwCommandDescriptor = pCommand->GetDescriptor();
|
|
pCommand->SetType( COMMAND_TYPE_LISTEN );
|
|
pCommand->SetState( COMMAND_STATE_PENDING );
|
|
pCommand->SetEndpoint( pEndpoint );
|
|
|
|
//
|
|
// open this endpoint
|
|
//
|
|
hTempResult = pEndpoint->Open( NULL,
|
|
pListenData->pAddressDeviceInfo,
|
|
LINK_DIRECTION_INCOMING,
|
|
ENDPOINT_TYPE_LISTEN );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// address conversion was fine, complete this command in the background
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
//
|
|
// copy connect data and the submit background job
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyListenData( pListenData );
|
|
pEndpoint->AddRef();
|
|
|
|
hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->ListenJobCallback,
|
|
pEndpoint->CancelListenJobCallback,
|
|
pEndpoint );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
pEndpoint->DecRef();
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_Listen: Failed to submit delayed listen!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// this endpoint has been handed off, remove our reference to it
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// address was incomplete, display a dialog if we can, otherwise fail the command
|
|
//
|
|
case DPNERR_INCOMPLETEADDRESS:
|
|
{
|
|
if ( ( pListenData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
|
|
{
|
|
//
|
|
// copy connect data for future reference and then start the dialog
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyListenData( pListenData );
|
|
|
|
hTempResult = pEndpoint->ShowIncomingSettingsDialog( pSPData->GetThreadPool() );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Problem showing settings dialog in DNMODEMSP_Listen!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// This endpoint has been handed off, clear the pointer to it.
|
|
// There is no reference to remove because the command is
|
|
// still pending.
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
|
|
goto Exit;
|
|
}
|
|
else
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Problem initializing endpoint in DNMODEMSP_Listen!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
DNASSERT( pEndpoint == NULL );
|
|
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
// this command cannot complete synchronously!
|
|
DNASSERT( hr != DPN_OK );
|
|
|
|
DPFX(DPFPREP, 0, "Problem with DNMODEMSP_Listen()" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
if ( fInterfaceReferenceAdded != FALSE )
|
|
{
|
|
IDP8ServiceProvider_Release( pThis );
|
|
fInterfaceReferenceAdded = FALSE;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
//
|
|
// return any outstanding endpoint
|
|
//
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
if ( fEndpointOpen != FALSE )
|
|
{
|
|
DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
|
|
pEndpoint->Close( hr );
|
|
fEndpointOpen = FALSE;
|
|
}
|
|
|
|
pSPData->CloseEndpointHandle( pEndpoint );
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
//
|
|
// return any outstanding command
|
|
//
|
|
if ( pCommand != NULL )
|
|
{
|
|
pCommand->DecRef();
|
|
pCommand = NULL;
|
|
|
|
pListenData->hCommand = NULL;
|
|
pListenData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_EnumQuery - start process to enum comport connections
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Pointer to enum data
|
|
//
|
|
// Exit: Error Code
|
|
//
|
|
// Note: Any command handle allocated by this function is closed by the
|
|
// endpoint.
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_EnumQuery"
|
|
|
|
STDMETHODIMP DNMODEMSP_EnumQuery( IDP8ServiceProvider *pThis, SPENUMQUERYDATA *pEnumQueryData )
|
|
{
|
|
HRESULT hr;
|
|
HRESULT hTempResult;
|
|
CModemSPData *pSPData;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemCommandData *pCommand;
|
|
BOOL fEndpointOpen;
|
|
GUID DeviceGUID;
|
|
GUID guidnull;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumQueryData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pEnumQueryData != NULL );
|
|
DNASSERT( ( pEnumQueryData->dwFlags & ~( DPNSPF_OKTOQUERY ) ) == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPNERR_PENDING;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pEndpoint = NULL;
|
|
pCommand = NULL;
|
|
fEndpointOpen = FALSE;
|
|
pEnumQueryData->hCommand = NULL;
|
|
pEnumQueryData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
memset(&guidnull, 0, sizeof(guidnull));
|
|
|
|
|
|
//
|
|
// the user is attempting an operation that relies on the thread pool, lock
|
|
// it down to prevent threads from being lost.
|
|
//
|
|
hTempResult = pSPData->GetThreadPool()->PreventThreadPoolReduction();
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to prevent thread pool reduction!" );
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// validate state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery called on uninitialized SP!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery called while SP closing!" );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_GENERIC;
|
|
goto Failure;
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
DNASSERT( hr != DPN_OK );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// check for invalid device ID
|
|
//
|
|
hTempResult = IDirectPlay8Address_GetDevice( pEnumQueryData->pAddressDeviceInfo, &DeviceGUID );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// there was a device ID, check against GUID_NULL
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
if ( IsEqualCLSID( DeviceGUID, guidnull ) != FALSE )
|
|
{
|
|
hr = DPNERR_ADDRESSING;
|
|
DPFX(DPFPREP, 0, "GUID_NULL was specified as a serial/modem device!" );
|
|
goto Failure;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// no device address specified, not a problem
|
|
//
|
|
case DPNERR_DOESNOTEXIST:
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other, stop and figure out why we're here
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "Failed to validate device address!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// get endpoint for this connection
|
|
//
|
|
pEndpoint = pSPData->GetNewEndpoint();
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Cannot create new endpoint!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// get new command
|
|
//
|
|
pCommand = (CModemCommandData*)g_ModemCommandDataPool.Get();
|
|
if ( pCommand == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Cannot get command handle!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// initialize command
|
|
//
|
|
pEnumQueryData->hCommand = pCommand;
|
|
pEnumQueryData->dwCommandDescriptor = pCommand->GetDescriptor();
|
|
pCommand->SetType( COMMAND_TYPE_ENUM_QUERY );
|
|
pCommand->SetState( COMMAND_STATE_INPROGRESS );
|
|
pCommand->SetEndpoint( pEndpoint );
|
|
|
|
//
|
|
// open this endpoint
|
|
//
|
|
hTempResult = pEndpoint->Open( pEnumQueryData->pAddressHost,
|
|
pEnumQueryData->pAddressDeviceInfo,
|
|
LINK_DIRECTION_OUTGOING,
|
|
ENDPOINT_TYPE_ENUM );
|
|
switch ( hTempResult )
|
|
{
|
|
//
|
|
// address was incomplete, display a dialog if we can, otherwise fail the command
|
|
//
|
|
case DPNERR_INCOMPLETEADDRESS:
|
|
{
|
|
#ifndef DPNBUILD_NOSPUI
|
|
if ( ( pEnumQueryData->dwFlags & DPNSPF_OKTOQUERY ) != 0 )
|
|
{
|
|
//
|
|
// copy connect data for future reference and then start the dialog
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyEnumQueryData( pEnumQueryData );
|
|
|
|
hTempResult = pEndpoint->ShowOutgoingSettingsDialog( pSPData->GetThreadPool() );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Problem showing settings dialog!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// this endpoint has been handed off, remove our reference to it
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
|
|
goto Exit;
|
|
}
|
|
else
|
|
#endif // !DPNBUILD_NOSPUI
|
|
{
|
|
hr = hTempResult;
|
|
goto Failure;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// address conversion was fine, complete this command in the background
|
|
//
|
|
case DPN_OK:
|
|
{
|
|
//
|
|
// copy connect data and the submit background job
|
|
//
|
|
fEndpointOpen = TRUE;
|
|
pEndpoint->CopyEnumQueryData( pEnumQueryData );
|
|
pEndpoint->AddRef();
|
|
|
|
hTempResult = pSPData->GetThreadPool()->SubmitDelayedCommand( pEndpoint->EnumQueryJobCallback,
|
|
pEndpoint->CancelEnumQueryJobCallback,
|
|
pEndpoint );
|
|
if ( hTempResult != DPN_OK )
|
|
{
|
|
pEndpoint->DecRef();
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Failed to submit delayed connect!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// this endpoint has been handed off, remove our reference to it
|
|
//
|
|
pEndpoint = NULL;
|
|
DNASSERT( hr == DPNERR_PENDING );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
hr = hTempResult;
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_EnumQuery: Problem initializing endpoint!" );
|
|
DisplayDNError( 0, hTempResult );
|
|
goto Failure;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
DNASSERT( pEndpoint == NULL );
|
|
|
|
if ( hr != DPNERR_PENDING )
|
|
{
|
|
DNASSERT( hr != DPN_OK );
|
|
DPFX(DPFPREP, 0, "Problem with DNMODEMSP_EnumQuery" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
if ( fEndpointOpen != FALSE )
|
|
{
|
|
DNASSERT( ( hr != DPN_OK ) && ( hr != DPNERR_PENDING ) );
|
|
pEndpoint->Close( hr );
|
|
fEndpointOpen = FALSE;
|
|
}
|
|
|
|
DNASSERT( FALSE );
|
|
pSPData->CloseEndpointHandle( pEndpoint );
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
//
|
|
// return any outstanding command
|
|
//
|
|
if ( pCommand != NULL )
|
|
{
|
|
pCommand->DecRef();
|
|
pCommand = NULL;
|
|
|
|
pEnumQueryData->hCommand = NULL;
|
|
pEnumQueryData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
/*
|
|
*
|
|
* DNMODEMSP_SendData sends data to the specified "player"
|
|
*
|
|
* This call MUST BE HIGHLY OPTIMIZED
|
|
*
|
|
*/
|
|
//**********************************************************************
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_SendData"
|
|
|
|
STDMETHODIMP DNMODEMSP_SendData( IDP8ServiceProvider *pThis, SPSENDDATA *pSendData )
|
|
{
|
|
HRESULT hr;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemWriteIOData *pWriteData;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pSendData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pSendData != NULL );
|
|
DNASSERT( pSendData->pBuffers != NULL );
|
|
DNASSERT( pSendData->dwBufferCount != 0 );
|
|
DNASSERT( pSendData->hEndpoint != INVALID_HANDLE_VALUE && pSendData->hEndpoint != 0 );
|
|
DNASSERT( pSendData->dwFlags == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPNERR_PENDING;
|
|
pEndpoint = NULL;
|
|
pSendData->hCommand = NULL;
|
|
pSendData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
pWriteData = NULL;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
DNASSERT( pSPData->GetState() == SPSTATE_INITIALIZED );
|
|
|
|
//
|
|
// No need to lock down the thread counts here because the user already has
|
|
// a connect or something running or they wouldn't be calling this function.
|
|
// That outstanding connect would have locked down the thread pool.
|
|
//
|
|
|
|
//
|
|
// Attempt to grab the endpoint from the handle. If this succeeds, the
|
|
// endpoint can send.
|
|
//
|
|
pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pSendData->hEndpoint );
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
hr = DPNERR_INVALIDHANDLE;
|
|
DPFX(DPFPREP, 0, "Invalid endpoint handle on send!" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// send data from pool
|
|
//
|
|
pWriteData = pSPData->GetThreadPool()->CreateWriteIOData();
|
|
if ( pWriteData == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "Cannot get new write data from pool in SendData!" );
|
|
goto Failure;
|
|
}
|
|
DNASSERT( pWriteData->m_pCommand != NULL );
|
|
DNASSERT( pWriteData->DataPort() == NULL );
|
|
|
|
//
|
|
// set the command state and fill in the message information
|
|
//
|
|
pWriteData->m_pCommand->SetType( COMMAND_TYPE_SEND );
|
|
pWriteData->m_pCommand->SetState( COMMAND_STATE_PENDING );
|
|
pWriteData->m_pCommand->SetEndpoint( pEndpoint );
|
|
pWriteData->m_pCommand->SetUserContext( pSendData->pvContext );
|
|
DNASSERT( pWriteData->m_SendCompleteAction == SEND_COMPLETE_ACTION_UNKNOWN );
|
|
pWriteData->m_SendCompleteAction = SEND_COMPLETE_ACTION_COMPLETE_COMMAND;
|
|
|
|
DNASSERT( pSendData->dwBufferCount != 0 );
|
|
pWriteData->m_uBufferCount = pSendData->dwBufferCount;
|
|
pWriteData->m_pBuffers = pSendData->pBuffers;
|
|
|
|
pSendData->hCommand = pWriteData->m_pCommand;
|
|
pSendData->dwCommandDescriptor = pWriteData->m_pCommand->GetDescriptor();
|
|
|
|
//
|
|
// send data through the endpoint
|
|
//
|
|
pEndpoint->SendUserData( pWriteData );
|
|
|
|
Exit:
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
pEndpoint->DecCommandRef();
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
if ( pWriteData != NULL )
|
|
{
|
|
pSPData->GetThreadPool()->ReturnWriteIOData( pWriteData );
|
|
DEBUG_ONLY( pWriteData = NULL );
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_CancelCommand - cancels a command in progress
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Handle of command
|
|
// Command descriptor
|
|
//
|
|
// Exit: Error Code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_CancelCommand"
|
|
|
|
STDMETHODIMP DNMODEMSP_CancelCommand( IDP8ServiceProvider *pThis, HANDLE hCommand, DWORD dwCommandDescriptor )
|
|
{
|
|
HRESULT hr;
|
|
CModemSPData *pSPData;
|
|
CModemCommandData *pCommandData;
|
|
BOOL fReferenceAdded;
|
|
BOOL fCommandLocked;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p, %ld)", pThis, hCommand, dwCommandDescriptor);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( hCommand != NULL );
|
|
DNASSERT( dwCommandDescriptor != NULL_DESCRIPTOR );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pCommandData = NULL;
|
|
fReferenceAdded = FALSE;
|
|
fCommandLocked = FALSE;
|
|
|
|
//
|
|
// vlidate state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider initialized
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
DNASSERT( hr == DPN_OK );
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
fReferenceAdded = TRUE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "Disconnect called on uninitialized SP!" );
|
|
DNASSERT( FALSE );
|
|
goto Exit;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "Disconnect called on closing SP!" );
|
|
DNASSERT( FALSE );
|
|
goto Exit;
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
hr = DPNERR_GENERIC;
|
|
DNASSERT( FALSE );
|
|
goto Exit;
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPN_OK )
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
pCommandData = static_cast<CModemCommandData*>( hCommand );
|
|
pCommandData->Lock();
|
|
fCommandLocked = TRUE;
|
|
|
|
//
|
|
// this should never happen
|
|
//
|
|
if ( pCommandData->GetDescriptor() != dwCommandDescriptor )
|
|
{
|
|
hr = DPNERR_INVALIDCOMMAND;
|
|
DPFX(DPFPREP, 0, "Attempt to cancel command with mismatched command descriptor!" );
|
|
goto Exit;
|
|
}
|
|
|
|
switch ( pCommandData->GetState() )
|
|
{
|
|
//
|
|
// unknown command state
|
|
//
|
|
case COMMAND_STATE_UNKNOWN:
|
|
{
|
|
hr = DPNERR_INVALIDCOMMAND;
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// command is waiting to be processed, set command state to be cancelling
|
|
// and wait for someone to pick it up
|
|
//
|
|
case COMMAND_STATE_PENDING:
|
|
{
|
|
pCommandData->SetState( COMMAND_STATE_CANCELLING );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// command in progress, and can't be cancelled
|
|
//
|
|
case COMMAND_STATE_INPROGRESS_CANNOT_CANCEL:
|
|
{
|
|
hr = DPNERR_CANNOTCANCEL;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Command is already being cancelled. This is not a problem, but shouldn't
|
|
// be happening.
|
|
//
|
|
case COMMAND_STATE_CANCELLING:
|
|
{
|
|
DNASSERT( hr == DPN_OK );
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// command is in progress, find out what type of command it is
|
|
//
|
|
case COMMAND_STATE_INPROGRESS:
|
|
{
|
|
switch ( pCommandData->GetType() )
|
|
{
|
|
case COMMAND_TYPE_UNKNOWN:
|
|
{
|
|
// we should never be in this state!
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
case COMMAND_TYPE_CONNECT:
|
|
{
|
|
// we should never be in this state!
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
case COMMAND_TYPE_LISTEN:
|
|
{
|
|
CModemEndpoint *pEndpoint;
|
|
|
|
|
|
//
|
|
// set this command to the cancel state before we shut down
|
|
// this endpoint
|
|
//
|
|
pCommandData->SetState( COMMAND_STATE_CANCELLING );
|
|
pCommandData->Unlock();
|
|
fCommandLocked = FALSE;
|
|
|
|
pEndpoint = pCommandData->GetEndpoint();
|
|
pEndpoint->Lock();
|
|
switch ( pEndpoint->GetState() )
|
|
{
|
|
//
|
|
// endpoint is already disconnecting, no action needs to be taken
|
|
//
|
|
case ENDPOINT_STATE_DISCONNECTING:
|
|
{
|
|
pEndpoint->Unlock();
|
|
goto Exit;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Endpoint is listening. Flag it as Disconnecting and
|
|
// add a reference so it doesn't disappear on us
|
|
//
|
|
case ENDPOINT_STATE_LISTENING:
|
|
{
|
|
pEndpoint->SetState( ENDPOINT_STATE_DISCONNECTING );
|
|
pEndpoint->AddRef();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other state
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
pEndpoint->Unlock();
|
|
|
|
pEndpoint->Close( DPNERR_USERCANCEL );
|
|
pSPData->CloseEndpointHandle( pEndpoint );
|
|
|
|
pEndpoint->DecRef();
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Note: this code is duplicated in CModemEndpoint::ProcessTAPIMessage
|
|
//
|
|
case COMMAND_TYPE_ENUM_QUERY:
|
|
{
|
|
CModemEndpoint *pEndpoint;
|
|
|
|
|
|
pEndpoint = pCommandData->GetEndpoint();
|
|
DNASSERT( pEndpoint != NULL );
|
|
|
|
pEndpoint->AddRef();
|
|
pCommandData->SetState( COMMAND_STATE_CANCELLING );
|
|
pCommandData->Unlock();
|
|
|
|
fCommandLocked = FALSE;
|
|
|
|
pEndpoint->Lock();
|
|
pEndpoint->SetState( ENDPOINT_STATE_DISCONNECTING );
|
|
pEndpoint->Unlock();
|
|
|
|
pEndpoint->StopEnumCommand( DPNERR_USERCANCEL );
|
|
pEndpoint->DecRef();
|
|
|
|
break;
|
|
}
|
|
|
|
case COMMAND_TYPE_SEND:
|
|
{
|
|
// we should never be here
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// other command state
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
if ( fCommandLocked != FALSE )
|
|
{
|
|
DNASSERT( pCommandData != NULL );
|
|
pCommandData->Unlock();
|
|
fCommandLocked = FALSE;
|
|
}
|
|
|
|
if ( fReferenceAdded != FALSE )
|
|
{
|
|
IDP8ServiceProvider_Release( pThis );
|
|
fReferenceAdded = FALSE;
|
|
}
|
|
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem with DNMODEMSP_CancelCommand!" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_EnumRespond - send response to enumeration data
|
|
//
|
|
// Entry: Pointer to the service provider interface
|
|
// Pointer to enum response data
|
|
//
|
|
// Exit: Error Code
|
|
//
|
|
// Note: This command is supposed to be fast. All initial error checking
|
|
// will be ASSERTs so they go away in the retail build.
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_EnumRespond"
|
|
|
|
STDMETHODIMP DNMODEMSP_EnumRespond( IDP8ServiceProvider *pThis, SPENUMRESPONDDATA *pEnumRespondData )
|
|
{
|
|
HRESULT hr;
|
|
CModemEndpoint *pEndpoint;
|
|
CModemWriteIOData *pWriteData;
|
|
CModemSPData *pSPData;
|
|
const ENDPOINT_ENUM_QUERY_CONTEXT *pEnumQueryContext;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumRespondData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pEnumRespondData != NULL );
|
|
DNASSERT( pEnumRespondData->dwFlags == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPNERR_PENDING;
|
|
pEndpoint = NULL;
|
|
pWriteData = NULL;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
DBG_CASSERT( OFFSETOF( ENDPOINT_ENUM_QUERY_CONTEXT, EnumQueryData ) == 0 );
|
|
pEnumQueryContext = reinterpret_cast<ENDPOINT_ENUM_QUERY_CONTEXT*>( pEnumRespondData->pQuery );
|
|
|
|
pEnumRespondData->hCommand = NULL;
|
|
pEnumRespondData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
DNASSERT( pSPData->GetState() == SPSTATE_INITIALIZED );
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
|
|
//
|
|
// check for valid endpoint
|
|
//
|
|
pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pEnumQueryContext->hEndpoint );
|
|
if ( pEndpoint == NULL )
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_INVALIDENDPOINT;
|
|
DPFX(DPFPREP, 8, "Invalid endpoint handle in DNMODEMSP_EnumRespond" );
|
|
goto Failure;
|
|
}
|
|
|
|
//
|
|
// no need to poke at the thread pool here to lock down threads because we
|
|
// can only really be here if there's an enum and that enum locked down the
|
|
// thread pool.
|
|
//
|
|
pWriteData = pSPData->GetThreadPool()->CreateWriteIOData();
|
|
if ( pWriteData == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "Cannot get new WRITE_IO_DATA for enum response!" );
|
|
goto Failure;
|
|
}
|
|
|
|
pWriteData->m_pCommand->SetType( COMMAND_TYPE_SEND );
|
|
pWriteData->m_pCommand->SetState( COMMAND_STATE_PENDING );
|
|
pWriteData->m_pCommand->SetEndpoint( pEndpoint );
|
|
pWriteData->m_pCommand->SetUserContext( pEnumRespondData->pvContext );
|
|
DNASSERT( pWriteData->m_SendCompleteAction == SEND_COMPLETE_ACTION_UNKNOWN );
|
|
pWriteData->m_SendCompleteAction = SEND_COMPLETE_ACTION_COMPLETE_COMMAND;
|
|
|
|
pWriteData->m_uBufferCount = pEnumRespondData->dwBufferCount;
|
|
pWriteData->m_pBuffers = pEnumRespondData->pBuffers;
|
|
|
|
pEnumRespondData->hCommand = pWriteData->m_pCommand;
|
|
pEnumRespondData->dwCommandDescriptor = pWriteData->m_pCommand->GetDescriptor();
|
|
|
|
//
|
|
// send data
|
|
//
|
|
pEndpoint->SendEnumResponseData( pWriteData, pEnumQueryContext->uEnumRTTIndex );
|
|
|
|
Exit:
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
pEndpoint->DecCommandRef();
|
|
pEndpoint = NULL;
|
|
}
|
|
|
|
IDP8ServiceProvider_Release( pThis );
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
if ( pWriteData != NULL )
|
|
{
|
|
DNASSERT( pSPData != NULL );
|
|
pSPData->GetThreadPool()->ReturnWriteIOData( pWriteData );
|
|
|
|
pEnumRespondData->hCommand = NULL;
|
|
pEnumRespondData->dwCommandDescriptor = NULL_DESCRIPTOR;
|
|
|
|
pWriteData = NULL;
|
|
}
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_IsApplicationSupported - determine if this application is supported by this
|
|
// SP.
|
|
//
|
|
// Entry: Pointer to DNSP Interface
|
|
// Pointer to input data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_IsApplicationSupported"
|
|
|
|
STDMETHODIMP DNMODEMSP_IsApplicationSupported( IDP8ServiceProvider *pThis, SPISAPPLICATIONSUPPORTEDDATA *pIsApplicationSupportedData )
|
|
{
|
|
HRESULT hr;
|
|
BOOL fInterfaceReferenceAdded;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pIsApplicationSupportedData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pIsApplicationSupportedData != NULL );
|
|
DNASSERT( pIsApplicationSupportedData->pApplicationGuid != NULL );
|
|
DNASSERT( pIsApplicationSupportedData->dwFlags == 0 );
|
|
|
|
//
|
|
// initialize, we support all applications with this SP
|
|
//
|
|
hr = DPN_OK;
|
|
fInterfaceReferenceAdded = FALSE;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
//
|
|
// no need to tell thread pool to lock the thread count for this function.
|
|
//
|
|
|
|
//
|
|
// validate SP state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized, add a reference and proceed
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
fInterfaceReferenceAdded = TRUE;
|
|
DNASSERT( hr == DPN_OK );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "IsApplicationSupported called on uninitialized SP!" );
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "IsApplicationSupported called while SP closing!" );
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_GENERIC;
|
|
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPN_OK )
|
|
{
|
|
goto Failure;
|
|
}
|
|
|
|
Exit:
|
|
if ( fInterfaceReferenceAdded != FALSE )
|
|
{
|
|
IDP8ServiceProvider_Release( pThis );
|
|
fInterfaceReferenceAdded = FALSE;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_GetCaps - get SP or endpoint capabilities
|
|
//
|
|
// Entry: Pointer to DirectPlay
|
|
// Pointer to caps data to fill
|
|
//
|
|
// Exit: Error Code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_GetCaps"
|
|
|
|
STDMETHODIMP DNMODEMSP_GetCaps( IDP8ServiceProvider *pThis, SPGETCAPSDATA *pCapsData )
|
|
{
|
|
HRESULT hr;
|
|
LONG iIOThreadCount;
|
|
CModemSPData *pSPData = NULL;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pCapsData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pCapsData != NULL );
|
|
DNASSERT( pCapsData->dwSize == sizeof( *pCapsData ) );
|
|
DNASSERT( pCapsData->hEndpoint == INVALID_HANDLE_VALUE );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
//
|
|
// there are no flags for this SP
|
|
//
|
|
pCapsData->dwFlags = 0;
|
|
|
|
//
|
|
// set frame sizes
|
|
//
|
|
pCapsData->dwUserFrameSize = MAX_USER_PAYLOAD;
|
|
pCapsData->dwEnumFrameSize = 1000;
|
|
|
|
//
|
|
// get link speed
|
|
//
|
|
if ( pCapsData->hEndpoint != INVALID_HANDLE_VALUE )
|
|
{
|
|
// TODO: MASONB: I see no path where this is ever used
|
|
CModemEndpoint *pEndpoint;
|
|
|
|
|
|
pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pCapsData->hEndpoint );
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
pCapsData->dwLocalLinkSpeed = pEndpoint->GetLinkSpeed();
|
|
pEndpoint->DecCommandRef();
|
|
}
|
|
else
|
|
{
|
|
hr = DPNERR_INVALIDENDPOINT;
|
|
DPFX(DPFPREP, 0, "Invalid endpoint specified to GetCaps()" );
|
|
goto Failure;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pCapsData->dwLocalLinkSpeed = CBR_256000;
|
|
}
|
|
|
|
//
|
|
// get IO thread count
|
|
//
|
|
hr = pSPData->GetThreadPool()->GetIOThreadCount( &iIOThreadCount );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_GetCaps: Failed to get thread pool count!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
pCapsData->dwIOThreadCount = iIOThreadCount;
|
|
|
|
//
|
|
// set enumeration defaults
|
|
//
|
|
pCapsData->dwDefaultEnumRetryCount = DEFAULT_ENUM_RETRY_COUNT;
|
|
pCapsData->dwDefaultEnumRetryInterval = DEFAULT_ENUM_RETRY_INTERVAL;
|
|
pCapsData->dwDefaultEnumTimeout = DEFAULT_ENUM_TIMEOUT;
|
|
|
|
pCapsData->dwBuffersPerThread = 1;
|
|
pCapsData->dwSystemBufferSize = 0;
|
|
|
|
Exit:
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_SetCaps - set SP capabilities
|
|
//
|
|
// Entry: Pointer to DirectPlay
|
|
// Pointer to caps data to use
|
|
//
|
|
// Exit: Error Code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_SetCaps"
|
|
|
|
STDMETHODIMP DNMODEMSP_SetCaps( IDP8ServiceProvider *pThis, SPSETCAPSDATA *pCapsData )
|
|
{
|
|
HRESULT hr;
|
|
BOOL fInterfaceReferenceAdded;
|
|
CModemSPData *pSPData;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pCapsData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pCapsData != NULL );
|
|
DNASSERT( pCapsData->dwSize == sizeof( *pCapsData ) );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
fInterfaceReferenceAdded = FALSE;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
|
|
|
|
//
|
|
// no need to tell thread pool to lock the thread count for this function.
|
|
//
|
|
|
|
//
|
|
// validate SP state
|
|
//
|
|
pSPData->Lock();
|
|
switch ( pSPData->GetState() )
|
|
{
|
|
//
|
|
// provider is initialized, add a reference and proceed
|
|
//
|
|
case SPSTATE_INITIALIZED:
|
|
{
|
|
IDP8ServiceProvider_AddRef( pThis );
|
|
fInterfaceReferenceAdded = TRUE;
|
|
DNASSERT( hr == DPN_OK );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is uninitialized
|
|
//
|
|
case SPSTATE_UNINITIALIZED:
|
|
{
|
|
hr = DPNERR_UNINITIALIZED;
|
|
DPFX(DPFPREP, 0, "AddToGroup called on uninitialized SP!" );
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// provider is closing
|
|
//
|
|
case SPSTATE_CLOSING:
|
|
{
|
|
hr = DPNERR_ABORTED;
|
|
DPFX(DPFPREP, 0, "AddToGroup called while SP closing!" );
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// unknown
|
|
//
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
hr = DPNERR_GENERIC;
|
|
|
|
break;
|
|
}
|
|
}
|
|
pSPData->Unlock();
|
|
if ( hr != DPN_OK )
|
|
{
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// validate caps
|
|
//
|
|
if ( pCapsData->dwBuffersPerThread == 0 )
|
|
{
|
|
DPFX(DPFPREP, 0, "Failing SetCaps because dwBuffersPerThread == 0" );
|
|
hr = DPNERR_INVALIDPARAM;
|
|
goto Failure;
|
|
}
|
|
|
|
|
|
//
|
|
// change thread count, if requested
|
|
//
|
|
if (pCapsData->dwIOThreadCount != 0)
|
|
{
|
|
hr = pSPData->GetThreadPool()->SetIOThreadCount( pCapsData->dwIOThreadCount );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "DNMODEMSP_SetCaps: Failed to set thread pool count!" );
|
|
DisplayDNError( 0, hr );
|
|
goto Failure;
|
|
}
|
|
}
|
|
|
|
|
|
Exit:
|
|
if ( fInterfaceReferenceAdded != FALSE )
|
|
{
|
|
IDP8ServiceProvider_Release( pThis );
|
|
fInterfaceReferenceAdded = FALSE;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_ReturnReceiveBuffers - return receive buffers to pool
|
|
//
|
|
// Entry: Pointer to DNSP interface
|
|
// Pointer to caps data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_ReturnReceiveBuffers"
|
|
|
|
STDMETHODIMP DNMODEMSP_ReturnReceiveBuffers( IDP8ServiceProvider *pThis, SPRECEIVEDBUFFER *pReceivedBuffers )
|
|
{
|
|
SPRECEIVEDBUFFER *pBuffers;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pReceivedBuffers);
|
|
|
|
//
|
|
// no need to tell thread pool to lock the thread count for this function.
|
|
//
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pReceivedBuffers != NULL );
|
|
|
|
pBuffers = pReceivedBuffers;
|
|
while ( pBuffers != NULL )
|
|
{
|
|
SPRECEIVEDBUFFER *pTemp;
|
|
CModemReadIOData *pReadData;
|
|
|
|
|
|
pTemp = pBuffers;
|
|
pBuffers = pBuffers->pNext;
|
|
pReadData = CModemReadIOData::ReadDataFromSPReceivedBuffer( pTemp );
|
|
pReadData->DecRef();
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [DPN_OK]");
|
|
|
|
return DPN_OK;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_GetAddressInfo - get address information
|
|
//
|
|
// Entry: Pointer to service provider interface
|
|
// Pointer to get address data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_GetAddressInfo"
|
|
|
|
STDMETHODIMP DNMODEMSP_GetAddressInfo( IDP8ServiceProvider *pThis, SPGETADDRESSINFODATA *pGetAddressInfoData )
|
|
{
|
|
HRESULT hr;
|
|
CModemSPData *pSPData;
|
|
CModemEndpoint *pEndpoint;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pGetAddressInfoData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pGetAddressInfoData != NULL );
|
|
DNASSERT( pGetAddressInfoData->hEndpoint != INVALID_HANDLE_VALUE && pGetAddressInfoData->hEndpoint != 0 );
|
|
DNASSERT( ( pGetAddressInfoData->Flags & ~( SP_GET_ADDRESS_INFO_LOCAL_ADAPTER |
|
|
SP_GET_ADDRESS_INFO_REMOTE_HOST |
|
|
SP_GET_ADDRESS_INFO_LISTEN_HOST_ADDRESSES |
|
|
SP_GET_ADDRESS_INFO_LOCAL_HOST_PUBLIC_ADDRESS ) ) == 0 );
|
|
|
|
//
|
|
// initialize
|
|
//
|
|
hr = DPN_OK;
|
|
pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pGetAddressInfoData->pAddress = NULL;
|
|
|
|
pEndpoint = pSPData->EndpointFromHandle( (DPNHANDLE)(DWORD_PTR)pGetAddressInfoData->hEndpoint );
|
|
if ( pEndpoint != NULL )
|
|
{
|
|
switch ( pGetAddressInfoData->Flags )
|
|
{
|
|
case SP_GET_ADDRESS_INFO_REMOTE_HOST:
|
|
{
|
|
pGetAddressInfoData->pAddress = pEndpoint->GetRemoteHostDP8Address();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// there is no concept of a 'public' address for this service provider so
|
|
// all local addresses are the same
|
|
//
|
|
case SP_GET_ADDRESS_INFO_LOCAL_ADAPTER:
|
|
{
|
|
pGetAddressInfoData->pAddress = pEndpoint->GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER );
|
|
break;
|
|
}
|
|
|
|
case SP_GET_ADDRESS_INFO_LOCAL_HOST_PUBLIC_ADDRESS:
|
|
case SP_GET_ADDRESS_INFO_LISTEN_HOST_ADDRESSES:
|
|
{
|
|
pGetAddressInfoData->pAddress = pEndpoint->GetLocalAdapterDP8Address( ADDRESS_TYPE_LOCAL_ADAPTER_HOST_FORMAT );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
DNASSERT( FALSE );
|
|
break;
|
|
}
|
|
}
|
|
|
|
pEndpoint->DecCommandRef();
|
|
pEndpoint = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = DPNERR_INVALIDENDPOINT;
|
|
}
|
|
|
|
if ( hr != DPN_OK )
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem getting DP8Address from endpoint!" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
// ------------------------------
|
|
// DNMODEMSP_EnumAdapters - enumerate adapters for this SP
|
|
//
|
|
// Entry: Pointer to service provider interface
|
|
// Pointer to enum adapters data
|
|
//
|
|
// Exit: Error code
|
|
// ------------------------------
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_EnumAdapters"
|
|
|
|
STDMETHODIMP DNMODEMSP_EnumAdapters( IDP8ServiceProvider *pThis, SPENUMADAPTERSDATA *pEnumAdaptersData )
|
|
{
|
|
HRESULT hr;
|
|
CDataPort *pDataPort;
|
|
DATA_PORT_POOL_CONTEXT DataPortPoolContext;
|
|
|
|
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pEnumAdaptersData);
|
|
|
|
DNASSERT( pThis != NULL );
|
|
DNASSERT( pEnumAdaptersData->dwFlags == 0 );
|
|
DNASSERT( ( pEnumAdaptersData->pAdapterData != NULL ) ||
|
|
( pEnumAdaptersData->dwAdapterDataSize == 0 ) );
|
|
|
|
//
|
|
// intialize
|
|
//
|
|
hr = DPN_OK;
|
|
pDataPort = NULL;
|
|
pEnumAdaptersData->dwAdapterCount = 0;
|
|
|
|
DataPortPoolContext.pSPData = CModemSPData::SPDataFromCOMInterface( pThis );
|
|
pDataPort = CreateDataPort( &DataPortPoolContext );
|
|
if ( pDataPort == NULL )
|
|
{
|
|
hr = DPNERR_OUTOFMEMORY;
|
|
DPFX(DPFPREP, 0, "Problem getting new dataport!" );
|
|
goto Failure;
|
|
}
|
|
|
|
hr = pDataPort->EnumAdapters( pEnumAdaptersData );
|
|
if ( hr != DPN_OK )
|
|
{
|
|
if (hr != DPNERR_BUFFERTOOSMALL)
|
|
{
|
|
DPFX(DPFPREP, 0, "Problem enumerating adapters!" );
|
|
DisplayDNError( 0, hr );
|
|
}
|
|
else
|
|
{
|
|
DPFX(DPFPREP, 1, "Buffer too small to enumerate adapters." );
|
|
}
|
|
goto Failure;
|
|
}
|
|
|
|
Exit:
|
|
if ( pDataPort != NULL )
|
|
{
|
|
pDataPort->DecRef();
|
|
pDataPort = NULL;
|
|
}
|
|
|
|
DPFX(DPFPREP, 2, "Returning: [0x%lx]", hr);
|
|
|
|
return hr;
|
|
|
|
Failure:
|
|
goto Exit;
|
|
}
|
|
//**********************************************************************
|
|
|
|
|
|
//**********************************************************************
|
|
/*
|
|
*
|
|
* DNMODEMSP_NotSupported is used for methods required to implement the
|
|
* interface but that are not supported by this SP.
|
|
*
|
|
*/
|
|
//**********************************************************************
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNMODEMSP_NotSupported"
|
|
|
|
STDMETHODIMP DNMODEMSP_NotSupported( IDP8ServiceProvider *pThis, PVOID pvParam )
|
|
{
|
|
DPFX(DPFPREP, 2, "Parameters: (0x%p, 0x%p)", pThis, pvParam);
|
|
DPFX(DPFPREP, 2, "Returning: [DPNERR_UNSUPPORTED]");
|
|
return DPNERR_UNSUPPORTED;
|
|
}
|
|
//**********************************************************************
|
|
|