/*========================================================================== * * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved. * * File: SPData.cpp * Content: Global variables for the DNSerial service provider in class * format. * * * History: * Date By Reason * ==== == ====== * 03/15/99 jtk Dereived from Locals.cpp ***************************************************************************/ #include "dnmdmi.h" //********************************************************************** // Constant definitions //********************************************************************** // default number of command descriptors to create #define DEFAULT_COMMAND_POOL_SIZE 20 #define COMMAND_POOL_GROW_SIZE 5 //********************************************************************** // Macro definitions //********************************************************************** //********************************************************************** // Structure definitions //********************************************************************** //********************************************************************** // Variable definitions //********************************************************************** //********************************************************************** // Function prototypes //********************************************************************** //********************************************************************** // Function definitions //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::CModemSPData - constructor // // Entry: Nothing // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::CModemSPData" CModemSPData::CModemSPData(): m_lRefCount( 0 ), m_lObjectRefCount( 0 ), m_hShutdownEvent( NULL ), m_SPType( TYPE_UNKNOWN ), m_State( SPSTATE_UNINITIALIZED ), m_pThreadPool( NULL ), m_fLockInitialized( FALSE ), m_fHandleTableInitialized( FALSE ), m_fDataPortDataLockInitialized( FALSE ), m_fInterfaceGlobalsInitialized( FALSE ) { m_Sig[0] = 'S'; m_Sig[1] = 'P'; m_Sig[2] = 'D'; m_Sig[3] = 'T'; memset( &m_InitData, 0x00, sizeof( m_InitData ) ); memset( &m_DataPortList, 0x00, sizeof( m_DataPortList ) ); memset( &m_COMInterface, 0x00, sizeof( m_COMInterface ) ); #ifndef DPNBUILD_LIBINTERFACE DNInterlockedIncrement( &g_lModemOutstandingInterfaceCount ); #endif // ! DPNBUILD_LIBINTERFACE } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::~CModemSPData - destructor // // Entry: Nothing // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::~CModemSPData" CModemSPData::~CModemSPData() { UINT_PTR uIndex; DNASSERT( m_lRefCount == 0 ); DNASSERT( m_lObjectRefCount == 0 ); DNASSERT( m_hShutdownEvent == NULL ); DNASSERT( m_SPType == TYPE_UNKNOWN ); DNASSERT( m_State == SPSTATE_UNINITIALIZED ); DNASSERT( m_pThreadPool == NULL ); uIndex = LENGTHOF( m_DataPortList ); while ( uIndex > 0 ) { uIndex--; DNASSERT( m_DataPortList[ uIndex ] == NULL ); } DNASSERT( m_fLockInitialized == FALSE ); DNASSERT( m_fHandleTableInitialized == FALSE ); DNASSERT( m_fDataPortDataLockInitialized == FALSE ); DNASSERT( m_fInterfaceGlobalsInitialized == FALSE ); #ifndef DPNBUILD_LIBINTERFACE DNInterlockedDecrement( &g_lModemOutstandingInterfaceCount ); #endif // ! DPNBUILD_LIBINTERFACE } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::Initialize - intialize // // Entry: Pointer to DirectNet // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::Initialize" HRESULT CModemSPData::Initialize( const SP_TYPE SPType, IDP8ServiceProviderVtbl *const pVtbl ) { HRESULT hr; DNASSERT( pVtbl != NULL ); // // initialize // hr = DPN_OK; DNASSERT( m_lRefCount == 1 ); DNASSERT( m_lObjectRefCount == 0 ); DNASSERT( GetType() == TYPE_UNKNOWN ); DNASSERT( GetType() == TYPE_UNKNOWN ); m_SPType = SPType; DNASSERT( m_COMInterface.m_pCOMVtbl == NULL ); m_COMInterface.m_pCOMVtbl = pVtbl; DNASSERT( m_fLockInitialized == FALSE ); DNASSERT( m_fDataPortDataLockInitialized == FALSE ); DNASSERT( m_fInterfaceGlobalsInitialized == FALSE ); // // attempt to initialize shutdown event // DNASSERT( m_hShutdownEvent == NULL ); m_hShutdownEvent = DNCreateEvent( NULL, // pointer to security (none) TRUE, // manual reset TRUE, // start signalled (so close can be called without any endpoints being created) NULL // pointer to name (none) ); if ( m_hShutdownEvent == NULL ) { DWORD dwError; dwError = GetLastError(); DPFX(DPFPREP, 0, "Failed to create event for shutting down spdata!" ); DisplayErrorCode( 0, dwError ); } // // initialize critical sections // if ( DNInitializeCriticalSection( &m_Lock ) == FALSE ) { hr = DPNERR_OUTOFMEMORY; DPFX(DPFPREP, 0, "Failed to initialize SP lock!" ); goto Failure; } DebugSetCriticalSectionRecursionCount( &m_Lock, 0 ); DebugSetCriticalSectionGroup( &m_Lock, &g_blDPNModemCritSecsHeld ); // separate dpnmodem CSes from the rest of DPlay's CSes m_fLockInitialized = TRUE; hr = m_HandleTable.Initialize(); if ( hr != DPN_OK ) { DPFX(DPFPREP, 0, "Failed to initialize handle table!" ); DisplayDNError( 0, hr ); goto Failure; } m_fHandleTableInitialized = TRUE; if ( DNInitializeCriticalSection( &m_DataPortDataLock ) == FALSE ) { hr = DPNERR_OUTOFMEMORY; DPFX(DPFPREP, 0, "Failed to initialize data port data lock!" ); goto Failure; } DebugSetCriticalSectionRecursionCount( &m_DataPortDataLock, 0 ); DebugSetCriticalSectionGroup( &m_DataPortDataLock, &g_blDPNModemCritSecsHeld ); // separate dpnmodem CSes from the rest of DPlay's CSes m_fDataPortDataLockInitialized = TRUE; // // get a thread pool // DNASSERT( m_pThreadPool == NULL ); hr = InitializeInterfaceGlobals( this ); if ( hr != DPN_OK ) { DPFX(DPFPREP, 0, "Failed to create thread pool!" ); DisplayDNError( 0, hr ); goto Failure; } m_fInterfaceGlobalsInitialized = TRUE; Exit: if ( hr != DPN_OK ) { DPFX(DPFPREP, 0, "Problem with CModemSPData::Initialize" ); DisplayDNError( 0, hr ); } return hr; Failure: Deinitialize(); goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::Shutdown - shut down this set of SP data // // Entry: Nothing // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::Shutdown" void CModemSPData::Shutdown( void ) { BOOL fLooping; // // Unbind this interface from the globals. This will cause a closure of all // of the I/O which will release endpoints, socket ports and then this data. // if ( m_fInterfaceGlobalsInitialized != FALSE ) { DeinitializeInterfaceGlobals( this ); DNASSERT( GetThreadPool() != NULL ); m_fInterfaceGlobalsInitialized = FALSE; } SetState( SPSTATE_CLOSING ); DNASSERT( m_hShutdownEvent != NULL ); fLooping = TRUE; while ( fLooping != FALSE ) { switch ( DNWaitForSingleObjectEx( m_hShutdownEvent, INFINITE, TRUE ) ) { case WAIT_OBJECT_0: { fLooping = FALSE; break; } case WAIT_IO_COMPLETION: { break; } default: { DNASSERT( FALSE ); break; } } } if ( DNCloseHandle( m_hShutdownEvent ) == FALSE ) { DWORD dwError; dwError = GetLastError(); DPFX(DPFPREP, 0, "Failed to close shutdown event!" ); DisplayErrorCode( 0, dwError ); } m_hShutdownEvent = NULL; if ( DP8SPCallbackInterface() != NULL) { IDP8SPCallback_Release( DP8SPCallbackInterface() ); memset( &m_InitData, 0x00, sizeof( m_InitData ) ); } } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::Deinitialize - deinitialize // // Entry: Nothing // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::Deinitialize" void CModemSPData::Deinitialize( void ) { DPFX(DPFPREP, 9, "Entering CModemSPData::Deinitialize" ); // // deinitialize interface globals // if ( m_fInterfaceGlobalsInitialized != FALSE ) { DeinitializeInterfaceGlobals( this ); DNASSERT( GetThreadPool() != NULL ); m_fInterfaceGlobalsInitialized = FALSE; } if ( m_fDataPortDataLockInitialized != FALSE ) { DNDeleteCriticalSection( &m_DataPortDataLock ); m_fDataPortDataLockInitialized = FALSE; } if ( m_fHandleTableInitialized != FALSE ) { m_HandleTable.Deinitialize(); m_fHandleTableInitialized = FALSE; } if ( m_fLockInitialized != FALSE ) { DNDeleteCriticalSection( &m_Lock ); m_fLockInitialized = FALSE; } m_COMInterface.m_pCOMVtbl = NULL; SetState( SPSTATE_UNINITIALIZED ); m_SPType = TYPE_UNKNOWN; if ( GetThreadPool() != NULL ) { GetThreadPool()->DecRef(); SetThreadPool( NULL ); } if ( m_hShutdownEvent != NULL ) { if ( DNCloseHandle( m_hShutdownEvent ) == FALSE ) { DWORD dwError; dwError = GetLastError(); DPFX(DPFPREP, 0, "Failed to close shutdown handle!" ); DisplayErrorCode( 0, dwError ); } m_hShutdownEvent = NULL; } } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::SetCallbackData - set data for SP callbacks to application // // Entry: Pointer to initialization data // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::SetCallbackData" void CModemSPData::SetCallbackData( const SPINITIALIZEDATA *const pInitData ) { DNASSERT( pInitData != NULL ); DNASSERT( pInitData->dwFlags == SP_SESSION_TYPE_PEER || pInitData->dwFlags == SP_SESSION_TYPE_CLIENT || pInitData->dwFlags == SP_SESSION_TYPE_SERVER || pInitData->dwFlags == 0); m_InitData.dwFlags = pInitData->dwFlags; DNASSERT( pInitData->pIDP != NULL ); m_InitData.pIDP = pInitData->pIDP; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::BindEndpoint - bind endpoint to a data port // // Entry: Pointer to endpoint // DeviceID // Device context // // Exit: Error code // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::BindEndpoint" HRESULT CModemSPData::BindEndpoint( CModemEndpoint *const pEndpoint, const DWORD dwDeviceID, const void *const pDeviceContext ) { HRESULT hr; CDataPort *pDataPort; BOOL fDataPortDataLocked; BOOL fDataPortCreated; BOOL fDataPortBoundToNetwork; DPFX(DPFPREP, 9, "(0x%p) Parameters: (0x%p, %u, 0x%p)", this, pEndpoint, dwDeviceID, pDeviceContext); // // intialize // hr = DPN_OK; pDataPort = NULL; fDataPortDataLocked = FALSE; fDataPortCreated = FALSE; fDataPortBoundToNetwork = FALSE; LockDataPortData(); fDataPortDataLocked = TRUE; if ( m_DataPortList[ dwDeviceID ] != NULL ) { pDataPort = m_DataPortList[ dwDeviceID ]; } else { DATA_PORT_POOL_CONTEXT DataPortPoolContext; memset( &DataPortPoolContext, 0x00, sizeof( DataPortPoolContext ) ); DataPortPoolContext.pSPData = this; pDataPort = CreateDataPort( &DataPortPoolContext ); if ( pDataPort == NULL ) { hr = DPNERR_OUTOFMEMORY; DPFX(DPFPREP, 0, "Failed to create new data port!" ); goto Failure; } fDataPortCreated = TRUE; hr = GetThreadPool()->CreateDataPortHandle( pDataPort ); if ( hr != DPN_OK ) { DPFX(DPFPREP, 0, "Failed to create handle for data port!" ); DisplayDNError( 0, hr ); goto Failure; } hr = pDataPort->BindToNetwork( dwDeviceID, pDeviceContext ); if ( hr != DPN_OK ) { DPFX(DPFPREP, 0, "Failed to bind data port to network!" ); DisplayDNError( 0, hr ); goto Failure; } fDataPortBoundToNetwork = TRUE; // // update the list, keep the reference added by 'CreateDataPort' as it // will be cleaned when the data port is removed from the active list. // m_DataPortList[ dwDeviceID ] = pDataPort; } DNASSERT( pDataPort != NULL ); pDataPort->EndpointAddRef(); hr = pDataPort->BindEndpoint( pEndpoint, pEndpoint->GetType() ); if ( hr != DPN_OK ) { pDataPort->EndpointDecRef(); DPFX(DPFPREP, 0, "Failed to bind endpoint!" ); DisplayDNError( 0, hr ); goto Failure; } Exit: if ( fDataPortDataLocked != FALSE ) { UnlockDataPortData(); fDataPortDataLocked = FALSE; } DPFX(DPFPREP, 9, "(0x%p) Returning [0x%lx]", this, hr); return hr; Failure: if ( pDataPort != NULL ) { if ( fDataPortBoundToNetwork != FALSE ) { pDataPort->UnbindFromNetwork(); fDataPortBoundToNetwork = FALSE; } if ( fDataPortCreated != FALSE ) { if ( pDataPort->GetHandle() != 0 ) { GetThreadPool()->CloseDataPortHandle( pDataPort ); DNASSERT( pDataPort->GetHandle() == 0 ); } pDataPort->DecRef(); fDataPortCreated = FALSE; } pDataPort = NULL; } goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::UnbindEndpoint - unbind an endpoint from a dataport // // Entry: Pointer to endpoint // Endpoint type // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::UnbindEndpoint" void CModemSPData::UnbindEndpoint( CModemEndpoint *const pEndpoint, const ENDPOINT_TYPE EndpointType ) { CDataPort *pDataPort; DWORD dwDeviceID; BOOL fCleanUpDataPort; DPFX(DPFPREP, 9, "(0x%p) Parameters: (0x%p, %u)", this, pEndpoint, EndpointType); DNASSERT( pEndpoint != NULL ); // // initialize // pDataPort = NULL; fCleanUpDataPort = FALSE; pDataPort = pEndpoint->GetDataPort(); dwDeviceID = pDataPort->GetDeviceID(); LockDataPortData(); pDataPort->UnbindEndpoint( pEndpoint, EndpointType ); if ( pDataPort->EndpointDecRef() == 0 ) { DNASSERT( m_DataPortList[ dwDeviceID ] == pDataPort ); m_DataPortList[ dwDeviceID ] = NULL; fCleanUpDataPort = TRUE; } UnlockDataPortData(); if ( fCleanUpDataPort != FALSE ) { pDataPort->DecRef(); fCleanUpDataPort = FALSE; } DPFX(DPFPREP, 9, "(0x%p) Leave", this); } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::GetNewEndpoint - get a new endpoint // // Entry: Nothing // // Exit: Pointer to new endpoint // NULL = out of memory // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::GetNewEndpoint" CModemEndpoint *CModemSPData::GetNewEndpoint( void ) { HRESULT hTempResult; CModemEndpoint *pEndpoint; DPNHANDLE hEndpoint; ENDPOINT_POOL_CONTEXT PoolContext; DPFX(DPFPREP, 9, "(0x%p) Enter", this); // // initialize // pEndpoint = NULL; hEndpoint = 0; memset( &PoolContext, 0x00, sizeof( PoolContext ) ); PoolContext.pSPData = this; pEndpoint = CreateEndpoint( &PoolContext ); if ( pEndpoint == NULL ) { DPFX(DPFPREP, 0, "Failed to create endpoint!" ); goto Failure; } hTempResult = m_HandleTable.Create( pEndpoint, &hEndpoint ); if ( hTempResult != DPN_OK ) { DNASSERT( hEndpoint == 0 ); DPFX(DPFPREP, 0, "Failed to create endpoint handle!" ); DisplayErrorCode( 0, hTempResult ); goto Failure; } pEndpoint->SetHandle( hEndpoint ); pEndpoint->AddCommandRef(); pEndpoint->DecRef(); Exit: DPFX(DPFPREP, 9, "(0x%p) Returning [0x%p]", this, pEndpoint); return pEndpoint; Failure: if ( hEndpoint != 0 ) { m_HandleTable.Destroy( hEndpoint, NULL ); hEndpoint = 0; } if ( pEndpoint != NULL ) { pEndpoint->DecRef(); pEndpoint = NULL; } goto Exit; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::EndpointFromHandle - get endpoint from handle // // Entry: Handle // // Exit: Pointer to endpoint // NULL = invalid handle // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::EndpointFromHandle" CModemEndpoint *CModemSPData::EndpointFromHandle( const DPNHANDLE hEndpoint ) { CModemEndpoint *pEndpoint; DPFX(DPFPREP, 9, "(0x%p) Parameters: (0x%p)", this, hEndpoint); pEndpoint = NULL; m_HandleTable.Lock(); if (SUCCEEDED(m_HandleTable.Find( hEndpoint, (PVOID*)&pEndpoint ))) { pEndpoint->AddCommandRef(); } m_HandleTable.Unlock(); DPFX(DPFPREP, 9, "(0x%p) Returning [0x%p]", this, pEndpoint); return pEndpoint; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::CloseEndpointHandle - close endpoint handle // // Entry: Poiner to endpoint // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::CloseEndpointHandle" void CModemSPData::CloseEndpointHandle( CModemEndpoint *const pEndpoint ) { DPNHANDLE Handle; DNASSERT( pEndpoint != NULL ); Handle = pEndpoint->GetHandle(); DPFX(DPFPREP, 9, "(0x%p) Parameters: (0x%p {handle = 0x%p})", this, pEndpoint, Handle); if (SUCCEEDED(m_HandleTable.Destroy( Handle, NULL ))) { pEndpoint->DecCommandRef(); } DPFX(DPFPREP, 9, "(0x%p) Leave", this); } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::GetEndpointAndCloseHandle - get endpoint from handle and close the // handle // // Entry: Handle // // Exit: Pointer to endpoint (it needs a call to 'DecCommandRef' when done) // NULL = invalid handle // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::GetEndpointAndCloseHandle" CModemEndpoint *CModemSPData::GetEndpointAndCloseHandle( const DPNHANDLE hEndpoint ) { CModemEndpoint *pEndpoint; DPFX(DPFPREP, 9, "(0x%p) Parameters: (0x%p)", this, hEndpoint); // // initialize // pEndpoint = NULL; if (SUCCEEDED( m_HandleTable.Destroy( hEndpoint, (PVOID*)&pEndpoint ))) { pEndpoint->AddRef(); } DPFX(DPFPREP, 9, "(0x%p) Returning [0x%p]", this, pEndpoint); return pEndpoint; } //********************************************************************** //********************************************************************** // ------------------------------ // CModemSPData::DestroyThisObject - destroy this object // // Entry: Nothing // // Exit: Nothing // ------------------------------ #undef DPF_MODNAME #define DPF_MODNAME "CModemSPData::DestroyThisObject" void CModemSPData::DestroyThisObject( void ) { Deinitialize(); delete this; // maybe a little too extreme...... } //**********************************************************************