Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

625 lines
16 KiB

/*==========================================================================
*
* 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<DIRECTNETOBJECT*>(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<DIRECTNETOBJECT*>(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<DIRECTNETOBJECT*>(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<DIRECTNETOBJECT*>(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<DIRECTNETOBJECT*>(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;
}