/*========================================================================== * * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved. * * File: Caps.cpp * Content: Dplay8 caps routines *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 03/17/00 rmt Created * 03/23/00 rmt Removed unused local variables * 03/25/00 rmt Updated to make calls into SP's function * rmt Updated SP calls to Initialize SP (and create if required) * 03/31/00 rmt Hooked up the GetCaps/SetCaps calls to call the protocol * 04/17/00 rmt Strong param validation * 04/19/00 mjn Removed AddRef() for NameTableEntry in DN_GetConnectionInfoHelper() * 05/03/00 mjn Use GetHostPlayerRef() rather than GetHostPlayer() * 06/05/00 mjn Fixed DN_GetConnectionInfoHelper() to use GetConnectionRef * 06/09/00 rmt Updates to split CLSID and allow whistler compat * 07/06/00 mjn Use GetInterfaceRef for SP interface * mjn Fixed up DN_SetActualSPCaps() and DN_GetActualSPCaps() * 07/29/00 mjn Fixed SetSPCaps() recursion problem * 07/31/00 mjn Renamed dwDefaultEnumRetryCount to dwDefaultEnumCount in DPN_SP_CAPS * 08/03/2000 rmt Bug #41244 - Wrong return codes -- part 2 * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. * 08/05/00 mjn Added dwFlags to DN_GetConnectionInfoHelper() * 08/20/00 mjn DNSetActualSPCaps() uses CServiceProvider object instead of GUID * 01/22/01 mjn Fixed debug text in DN_GetConnectionInfoHelper() * 02/12/01 mjn Fixed CConnection::GetEndPt() to track calling thread * 03/30/01 mjn Changes to prevent multiple loading/unloading of SP's * mjn Removed cached caps functionallity * 07/24/01 mjn Added DPNBUILD_NOPARAMVAL compile flag *@@END_MSINTERNAL * ***************************************************************************/ #include "dncorei.h" // DN_SetCaps // // Set caps #undef DPF_MODNAME #define DPF_MODNAME "DN_SetCaps" STDMETHODIMP DN_SetCaps(PVOID pv, const DPN_CAPS *const pdnCaps, const DWORD dwFlags) { DIRECTNETOBJECT *pdnObject; HRESULT hResultCode; DPFX(DPFPREP, 3,"Parameters: pdnCaps [0x%p] dwFlags [0x%lx]", pdnCaps, dwFlags ); pdnObject = static_cast(GET_OBJECT_FROM_INTERFACE(pv)); DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_NOPARAMVAL if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateSetCaps( pv, pdnCaps, dwFlags ) ) ) { DPFERR( "Error validating SetCaps params" ); DPF_RETURN( hResultCode ); } } #endif // !DPNBUILD_NOPARAMVAL // Check to ensure message handler registered if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED)) { DPFERR( "Object is not initialized" ); DPF_RETURN(DPNERR_UNINITIALIZED); } hResultCode = DNPSetProtocolCaps( pdnObject->pdnProtocolData, (DPN_CAPS*)pdnCaps ); DPF_RETURN(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "DN_GetCaps" STDMETHODIMP DN_GetCaps(PVOID pv, DPN_CAPS *const pdnCaps, const DWORD dwFlags) { DPFX(DPFPREP, 2,"Parameters: pdnCaps [0x%p], dwFlags [0x%lx]", pdnCaps,dwFlags); DIRECTNETOBJECT *pdnObject; HRESULT hResultCode; pdnObject = static_cast(GET_OBJECT_FROM_INTERFACE(pv)); DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_NOPARAMVAL if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateGetCaps( pv, pdnCaps, dwFlags ) ) ) { DPFERR( "Error validating GetCaps params" ); DPF_RETURN( hResultCode ); } } #endif // DPNBUILD_NOPARAMVAL // Check to ensure message handler registered if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED)) { DPFERR( "Object is not initialized" ); DPF_RETURN(DPNERR_UNINITIALIZED); } hResultCode = DNPGetProtocolCaps( pdnObject->pdnProtocolData, pdnCaps ); DPF_RETURN(hResultCode); } #undef DPF_MODNAME #define DPF_MODNAME "DN_GetSPCaps" STDMETHODIMP DN_GetSPCaps(PVOID pv, const GUID * const pguidSP, DPN_SP_CAPS *const pdnSPCaps, const DWORD dwFlags) { DIRECTNETOBJECT *pdnObject; HRESULT hResultCode; CServiceProvider *pSP; DPFX(DPFPREP, 2,"Parameters: pdnSPCaps [0x%p], dwFlags [0x%lx]", pdnSPCaps, dwFlags ); pdnObject = static_cast(GET_OBJECT_FROM_INTERFACE(pv)); DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_NOPARAMVAL if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateGetSPCaps( pv, pguidSP, pdnSPCaps, dwFlags ) ) ) { DPFERR( "Error validating GetSPCaps params" ); DPF_RETURN( hResultCode ); } } #endif // !DPNBUILD_NOPARAMVAL // Check to ensure message handler registered if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED)) { DPFERR( "Object is not initialized" ); DPF_RETURN(DPNERR_UNINITIALIZED); } pSP = NULL; #if ((defined(DPNBUILD_ONLYONESP)) && (defined(DPNBUILD_LIBINTERFACE))) DNASSERT(pdnObject->pOnlySP != NULL); pdnObject->pOnlySP->AddRef(); pSP = pdnObject->pOnlySP; #else // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE // // Ensure SP is loaded // hResultCode = DN_SPEnsureLoaded(pdnObject, #ifndef DPNBUILD_ONLYONESP pguidSP, #endif // ! DPNBUILD_ONLYONESP #ifndef DPNBUILD_LIBINTERFACE NULL, #endif // ! DPNBUILD_LIBINTERFACE &pSP); if (hResultCode != DPN_OK) { DPFERR("Could not find or load SP"); DisplayDNError(0,hResultCode); goto Failure; } DNASSERT( pSP != NULL ); #endif // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE // // Get actual SP caps // hResultCode = DNGetActualSPCaps(pSP,pdnSPCaps); pSP->Release(); pSP = NULL; #if ((! defined(DPNBUILD_ONLYONESP)) || (! defined(DPNBUILD_LIBINTERFACE))) Exit: #endif // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE DNASSERT( pSP == NULL ); DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode); #if ((! defined(DPNBUILD_ONLYONESP)) || (! defined(DPNBUILD_LIBINTERFACE))) Failure: if (pSP) { pSP->Release(); pSP = NULL; } goto Exit; #endif // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE } #undef DPF_MODNAME #define DPF_MODNAME "DN_SetSPCaps" STDMETHODIMP DN_SetSPCaps(PVOID pv, const GUID * const pguidSP, const DPN_SP_CAPS *const pdnSPCaps, const DWORD dwFlags) { DPFX(DPFPREP, 2,"Parameters: pdnSPCaps [0x%p]", pdnSPCaps ); DIRECTNETOBJECT *pdnObject; CServiceProvider *pSP; HRESULT hResultCode; SPSETCAPSDATA spSetCapsData; IDP8ServiceProvider *pIDP8SP; pdnObject = static_cast(GET_OBJECT_FROM_INTERFACE(pv)); DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_NOPARAMVAL if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateSetSPCaps( pv, pguidSP, pdnSPCaps, dwFlags ) ) ) { DPFERR( "Error validating SetSPCaps params" ); DPF_RETURN( hResultCode ); } } #endif // !DPNBUILD_NOPARAMVAL // Check to ensure message handler registered if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED)) { DPFERR( "Object is not initialized" ); DPF_RETURN(DPNERR_UNINITIALIZED); } pSP = NULL; pIDP8SP = NULL; #if ((defined(DPNBUILD_ONLYONESP)) && (defined(DPNBUILD_LIBINTERFACE))) DNASSERT(pdnObject->pOnlySP != NULL); pdnObject->pOnlySP->AddRef(); pSP = pdnObject->pOnlySP; #else // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE // // Ensure the SP is loaded. If it's not currently loaded, we will load it now. // hResultCode = DN_SPEnsureLoaded(pdnObject, #ifndef DPNBUILD_ONLYONESP pguidSP, #endif // ! DPNBUILD_ONLYONESP #ifndef DPNBUILD_LIBINTERFACE NULL, #endif // ! DPNBUILD_LIBINTERFACE &pSP); if (hResultCode != DPN_OK) { DPFERR("Could not find or load SP"); DisplayDNError(0,hResultCode); goto Failure; } DNASSERT(pSP != NULL); #endif // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE // // Get the SP interface // if ((hResultCode = pSP->GetInterfaceRef( &pIDP8SP )) != DPN_OK) { DPFERR("Could not get SP interface reference"); DisplayDNError(0,hResultCode); goto Failure; } // // Set the SP caps // memset( &spSetCapsData, 0x00, sizeof( SPSETCAPSDATA ) ); spSetCapsData.dwSize = sizeof( SPSETCAPSDATA ); spSetCapsData.dwIOThreadCount = pdnSPCaps->dwNumThreads; spSetCapsData.dwBuffersPerThread = pdnSPCaps->dwBuffersPerThread; spSetCapsData.dwSystemBufferSize = pdnSPCaps->dwSystemBufferSize; if ((hResultCode = IDP8ServiceProvider_SetCaps( pIDP8SP, &spSetCapsData )) != DPN_OK) { DPFERR("Could not set SP caps"); DisplayDNError(0,hResultCode); goto Failure; } // // Clean up // IDP8ServiceProvider_Release( pIDP8SP ); pIDP8SP = NULL; pSP->Release(); pSP = NULL; hResultCode = DPN_OK; Exit: DNASSERT( pIDP8SP == NULL); DNASSERT( pSP == NULL); DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode); Failure: if (pIDP8SP) { IDP8ServiceProvider_Release( pIDP8SP ); pIDP8SP = NULL; } if (pSP) { pSP->Release(); pSP = NULL; } goto Exit; } #undef DPF_MODNAME #define DPF_MODNAME "DN_GetConnectionInfoHelper" STDMETHODIMP DN_GetConnectionInfoHelper(PVOID pv, const DPNID dpnid, DPN_CONNECTION_INFO *const pdpConnectionInfo, BOOL fServerPlayer, const DWORD dwFlags) { DIRECTNETOBJECT *pdnObject; HRESULT hResultCode; CNameTableEntry *pPlayerEntry; CConnection *pConnection; HANDLE hEndPoint; CCallbackThread CallbackThread; pPlayerEntry = NULL; pConnection = NULL; CallbackThread.Initialize(); pdnObject = static_cast(GET_OBJECT_FROM_INTERFACE(pv)); DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_NOPARAMVAL if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateGetConnectionInfoHelper( pv, dpnid, pdpConnectionInfo, fServerPlayer,dwFlags ) ) ) { DPFERR( "Error validating GetConnectionInfoHelper params" ); DPF_RETURN( hResultCode ); } } #endif // !DPNBUILD_NOPARAMVAL // Check to ensure message handler registered if (!(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED)) { DPFERR( "Object is not initialized" ); DPF_RETURN(DPNERR_UNINITIALIZED); } if( pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING ) { DPFERR("Object is connecting / starting to host" ); DPF_RETURN(DPNERR_CONNECTING); } if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED) ) { DPFERR("You must be connected / hosting to get connection info" ); DPF_RETURN(DPNERR_NOCONNECTION); } if( fServerPlayer ) { hResultCode = pdnObject->NameTable.GetHostPlayerRef( &pPlayerEntry ); if ( FAILED( hResultCode ) ) { DPFX(DPFPREP, 0, "No host player present" ); DPF_RETURN(DPNERR_INVALIDPLAYER); } } else { hResultCode = pdnObject->NameTable.FindEntry( dpnid, &pPlayerEntry ); if( FAILED( hResultCode ) ) { DPFX(DPFPREP, 0, "Could not find specified player" ); DPF_RETURN(DPNERR_INVALIDPLAYER); } } if( pPlayerEntry == NULL ) { DNASSERT(FALSE); DPFX(DPFPREP, 0, "Internal error" ); DPF_RETURN(DPNERR_GENERIC); } if( pPlayerEntry->IsGroup() ) { DPFX(DPFPREP, 0, "Cannot retrieve connection info on groups" ); hResultCode = DPNERR_INVALIDPLAYER; goto Failure; } if ((hResultCode = pPlayerEntry->GetConnectionRef( &pConnection )) != DPN_OK) { DPFERR("Could not get connection reference"); hResultCode = DPNERR_CONNECTIONLOST; goto Failure; } hResultCode = pConnection->GetEndPt(&hEndPoint,&CallbackThread); if( FAILED( hResultCode ) ) { DPFX(DPFPREP, 0, "Unable to get endpoint hr=[0x%08x]", hResultCode ); hResultCode = DPNERR_CONNECTIONLOST; goto Failure; } if (hEndPoint != NULL) { hResultCode = DNPGetEPCaps( pdnObject->pdnProtocolData, hEndPoint, pdpConnectionInfo ); } else { hResultCode = DPNERR_INVALIDENDPOINT; } pConnection->ReleaseEndPt(&CallbackThread); if( FAILED( hResultCode ) ) { DPFX(DPFPREP, 0, "Error getting connection info hr=[0x%08x]", hResultCode ); hResultCode = DPNERR_INVALIDPLAYER; goto Failure; } pConnection->Release(); pPlayerEntry->Release(); hResultCode = DPN_OK; Exit: CallbackThread.Deinitialize(); DPF_RETURN(hResultCode); Failure: if (pPlayerEntry) { pPlayerEntry->Release(); pPlayerEntry = NULL; } if (pConnection) { pConnection->Release(); pConnection = NULL; } goto Exit; } #undef DPF_MODNAME #define DPF_MODNAME "DN_GetConnectionInfo" STDMETHODIMP DN_GetConnectionInfo(PVOID pv, const DPNID dpnid, DPN_CONNECTION_INFO *const pdpConnectionInfo, const DWORD dwFlags) { DPFX(DPFPREP, 3,"Parameters: dpnid [0x%lx] pdpConnectionInfo [0x%p], dwFlags [0x%lx]", dpnid, pdpConnectionInfo,dwFlags ); return DN_GetConnectionInfoHelper( pv, dpnid, pdpConnectionInfo, FALSE, dwFlags ); } #undef DPF_MODNAME #define DPF_MODNAME "DN_GetConnectionInfo" STDMETHODIMP DN_GetServerConnectionInfo(PVOID pv, DPN_CONNECTION_INFO *const pdpConnectionInfo, const DWORD dwFlags) { DPFX(DPFPREP, 2,"Parameters: pdpConnectionInfo [0x%p], dwFlags [0x%lx]", pdpConnectionInfo, dwFlags); return DN_GetConnectionInfoHelper( pv, 0, pdpConnectionInfo, TRUE, dwFlags ); } HRESULT DNCAPS_QueryInterface( IDP8SPCallback *pSP, REFIID riid, LPVOID * ppvObj ) { *ppvObj = pSP; return DPN_OK; } ULONG DNCAPS_AddRef( IDP8SPCallback *pSP ) { return 1; } ULONG DNCAPS_Release( IDP8SPCallback *pSP ) { return 1; } HRESULT DNCAPS_IndicateEvent( IDP8SPCallback *pSP, SP_EVENT_TYPE spetEvent,LPVOID pvData ) { return DPN_OK; } HRESULT DNCAPS_CommandComplete( IDP8SPCallback *pSP,HANDLE hCommand,HRESULT hrResult,LPVOID pvData ) { return DPN_OK; } LPVOID dncapsspInterface[] = { (LPVOID)DNCAPS_QueryInterface, (LPVOID)DNCAPS_AddRef, (LPVOID)DNCAPS_Release, (LPVOID)DNCAPS_IndicateEvent, (LPVOID)DNCAPS_CommandComplete }; // SP should be loaded // #undef DPF_MODNAME #define DPF_MODNAME "DNGetActualSPCaps" HRESULT DNGetActualSPCaps(CServiceProvider *const pSP, DPN_SP_CAPS *const pCaps) { HRESULT hResultCode; SPGETCAPSDATA spGetCapsData; IDP8ServiceProvider *pIDP8SP; DPFX(DPFPREP, 4,"Parameters: pSP [0x%p], pCaps [0x%p]",pSP,pCaps); DNASSERT(pSP != NULL); pIDP8SP = NULL; // // Get the SP interface // if ((hResultCode = pSP->GetInterfaceRef( &pIDP8SP )) != DPN_OK) { DPFERR("Could not get SP interface reference"); DisplayDNError(0,hResultCode); goto Failure; } // // Get the SP caps // memset( &spGetCapsData, 0x00, sizeof( SPGETCAPSDATA ) ); spGetCapsData.dwSize = sizeof( SPGETCAPSDATA ); spGetCapsData.hEndpoint = INVALID_HANDLE_VALUE; if ((hResultCode = IDP8ServiceProvider_GetCaps( pIDP8SP, &spGetCapsData )) != DPN_OK) { DPFERR("Could not get SP caps"); DisplayDNError(0,hResultCode); goto Failure; } // // Clean up // IDP8ServiceProvider_Release( pIDP8SP ); pIDP8SP = NULL; // // Map from SP structure to our own // pCaps->dwFlags = spGetCapsData.dwFlags; pCaps->dwNumThreads = spGetCapsData.dwIOThreadCount; pCaps->dwDefaultEnumCount = spGetCapsData.dwDefaultEnumRetryCount; pCaps->dwDefaultEnumRetryInterval = spGetCapsData.dwDefaultEnumRetryInterval; pCaps->dwDefaultEnumTimeout = spGetCapsData.dwDefaultEnumTimeout; pCaps->dwMaxEnumPayloadSize = spGetCapsData.dwEnumFrameSize - sizeof( DN_ENUM_QUERY_PAYLOAD ); pCaps->dwBuffersPerThread = spGetCapsData.dwBuffersPerThread; pCaps->dwSystemBufferSize = spGetCapsData.dwSystemBufferSize; hResultCode = DPN_OK; Exit: DNASSERT( pIDP8SP == NULL ); DPFX(DPFPREP, 4,"Returning: [0x%lx]",hResultCode); return(hResultCode); Failure: if (pIDP8SP) { IDP8ServiceProvider_Release(pIDP8SP); pIDP8SP = NULL; } goto Exit; }