|
|
/*==========================================================================
* * Copyright (C) 2001-2002 Microsoft Corporation. All Rights Reserved. * * File: mcast.cpp * Content: DirectPlay8 Mcast interface routines *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 10/08/01 vanceo Created *@@END_MSINTERNAL * ***************************************************************************/
#include "dncorei.h"
#ifndef DPNBUILD_NOMULTICAST
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
//**********************************************************************
// Variable definitions
//**********************************************************************
typedef STDMETHODIMP McastQueryInterface(IDirectPlay8Multicast *pInterface, DP8REFIID riid, LPVOID *ppvObj); typedef STDMETHODIMP_(ULONG) McastAddRef(IDirectPlay8Multicast *pInterface); typedef STDMETHODIMP_(ULONG) McastRelease(IDirectPlay8Multicast *pInterface); typedef STDMETHODIMP McastInitialize(IDirectPlay8Multicast *pInterface, PVOID const pvUserContext, const PFNDPNMESSAGEHANDLER pfn, const DWORD dwFlags); typedef STDMETHODIMP McastJoin(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pGroupAddr, IUnknown *const pDeviceInfo, const DPN_SECURITY_DESC *const pdnSecurity, const DPN_SECURITY_CREDENTIALS *const pdnCredentials, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags); typedef STDMETHODIMP McastClose(IDirectPlay8Multicast *pInterface, const DWORD dwFlags); typedef STDMETHODIMP McastCreateSenderContext(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, void *const pvSenderContext, const DWORD dwFlags); typedef STDMETHODIMP McastDestroySenderContext(IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, const DWORD dwFlags); typedef STDMETHODIMP McastSend(IDirectPlay8Multicast *pInterface, const DPN_BUFFER_DESC *const prgBufferDesc,const DWORD cBufferDesc,const DWORD dwTimeOut, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags); typedef STDMETHODIMP McastGetGroupAddress(IDirectPlay8Multicast *pInterface, IDirectPlay8Address **const ppAddress, const DWORD dwFlags); typedef STDMETHODIMP McastGetSendQueueInfo( IDirectPlay8Multicast *pInterface, DWORD *const lpdwNumMsgs, DWORD *const lpdwNumBytes, const DWORD dwFlags); typedef STDMETHODIMP McastCancelAsyncOperation( IDirectPlay8Multicast *pInterface, const DPNHANDLE hAsyncHandle, const DWORD dwFlags); typedef STDMETHODIMP McastReturnBuffer( IDirectPlay8Multicast *pInterface, const DPNHANDLE hBufferHandle,const DWORD dwFlags); typedef STDMETHODIMP McastEnumServiceProviders( IDirectPlay8Multicast *pInterface, const GUID *const pguidServiceProvider, const GUID *const pguidApplication, DPN_SERVICE_PROVIDER_INFO *const pSPInfoBuffer, DWORD *const pcbEnumData, DWORD *const pcReturned, const DWORD dwFlags); typedef STDMETHODIMP McastEnumMulticastScopes( IDirectPlay8Multicast *pInterface, const GUID *const pguidServiceProvider, const GUID *const pguidDevice, const GUID *const pguidApplication, DPN_MULTICAST_SCOPE_INFO *const pScopeInfoBuffer, PDWORD const pcbEnumData, PDWORD const pcReturned, const DWORD dwFlags); typedef STDMETHODIMP McastGetSPCaps(IDirectPlay8Multicast *pInterface, const GUID * const pguidSP, DPN_SP_CAPS *const pdpspCaps,const DWORD dwFlags); typedef STDMETHODIMP McastSetSPCaps(IDirectPlay8Multicast *pInterface, const GUID * const pguidSP, const DPN_SP_CAPS *const pdpspCaps, const DWORD dwFlags);
IDirectPlay8MulticastVtbl DNMcast_Vtbl = { (McastQueryInterface*) DN_QueryInterface, (McastAddRef*) DN_AddRef, (McastRelease*) DN_Release, (McastInitialize*) DN_Initialize, (McastJoin*) DN_Join, (McastClose*) DN_Close, (McastCreateSenderContext*) DN_CreateSenderContext, (McastDestroySenderContext*) DN_DestroySenderContext, (McastSend*) DN_Send, (McastGetGroupAddress*) DN_GetGroupAddress, (McastGetSendQueueInfo*) DN_GetHostSendQueueInfo, (McastCancelAsyncOperation*) DN_CancelAsyncOperation, (McastReturnBuffer*) DN_ReturnBuffer, (McastEnumServiceProviders*) DN_EnumServiceProviders, (McastEnumMulticastScopes*) DN_EnumMulticastScopes, (McastGetSPCaps*) DN_GetSPCaps, (McastSetSPCaps*) DN_SetSPCaps };
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Function definitions
//**********************************************************************
//
// Completion for join connect parent
//
#undef DPF_MODNAME
#define DPF_MODNAME "DNCompleteJoinOperation"
void DNCompleteJoinOperation(DIRECTNETOBJECT *const pdnObject, CAsyncOp *const pAsyncOp) { CServiceProvider *pSP; IDirectPlay8Address *pIDevice;
pSP = NULL; pIDevice = NULL;
//
// Save the result code on the parent (if it exists - it will be the CONNECT handle)
//
if (pAsyncOp->GetParent()) { pAsyncOp->GetParent()->Lock(); pAsyncOp->GetParent()->SetResult( pAsyncOp->GetResult() ); pAsyncOp->GetParent()->Unlock();
if (SUCCEEDED(pdnObject->HandleTable.Destroy( pAsyncOp->GetParent()->GetHandle(), NULL ))) { // Release the HandleTable reference
pAsyncOp->GetParent()->Release(); } }
//
// Clear CONNECTING flag, and DISCONNECTING flag in case this was aborted.
// If the connect succeeded, set the CONNECTED flag.
//
DPFX(DPFPREP, 8,"Clearing CONNECTING and DISCONNECTING flags"); DNEnterCriticalSection(&pdnObject->csDirectNetObject); pdnObject->dwFlags &= (~DN_OBJECT_FLAG_CONNECTING | DN_OBJECT_FLAG_DISCONNECTING); if (pAsyncOp->GetResult() == DPN_OK) { pdnObject->dwFlags |= DN_OBJECT_FLAG_CONNECTED; } else { //
// Clean up DirectNet object
//
pSP = pdnObject->pConnectSP; pdnObject->pConnectSP = NULL; pIDevice = pdnObject->pIDP8ADevice; pdnObject->pIDP8ADevice = NULL; } DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
if (pSP) { pSP->Release(); pSP = NULL; } if (pIDevice) { IDirectPlay8Address_Release(pIDevice); pIDevice = NULL; }
DNASSERT( pSP == NULL ); DNASSERT( pIDevice == NULL ); }
//
// Completion for join handle parent
//
#undef DPF_MODNAME
#define DPF_MODNAME "DNCompleteUserJoin"
void DNCompleteUserJoin(DIRECTNETOBJECT *const pdnObject, CAsyncOp *const pAsyncOp) { DNUserJoinComplete( pdnObject, pAsyncOp->GetHandle(), pAsyncOp->GetContext(), pAsyncOp->GetResult()); }
#undef DPF_MODNAME
#define DPF_MODNAME "DN_Join"
STDMETHODIMP DN_Join( IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pGroupAddr, IUnknown *const pDeviceInfo, const DPN_SECURITY_DESC *const pdnSecurity, const DPN_SECURITY_CREDENTIALS *const pdnCredentials, void *const pvAsyncContext, DPNHANDLE *const phAsyncHandle, const DWORD dwFlags) { HRESULT hResultCode; HRESULT volatile hrOperation; DIRECTNETOBJECT *pdnObject; IDirectPlay8Address *pIGroup; IDirectPlay8Address *pIDevice; #ifndef DPNBUILD_ONLYONESP
GUID guidSP; #endif // ! DPNBUILD_ONLYONESP
#ifndef DPNBUILD_ONLYONEADAPTER
GUID guidAdapter; #endif // ! DPNBUILD_ONLYONEADAPTER
PVOID pvNewInterface; DWORD dwListenFlags; CAsyncOp *pListenParent; CAsyncOp *pParent; CAsyncOp *pAsyncOp; CAsyncOp *pConnectParent; CAsyncOp *pHandleParent; CServiceProvider *pSP; CSyncEvent *pSyncEvent; HANDLE hEndpoint; SPGETADDRESSINFODATA spInfoData; // Variables used when device interface is a DIRECTNETOBJECT
DIRECTNETOBJECT *pdnDeviceObject; CConnection *pExistingConnection; CNameTableEntry *pNTEntry; CServiceProvider *pShareSP; IDP8ServiceProvider *pShareDP8ServiceProvider; HANDLE hEndPt; CCallbackThread CallbackThread; CAsyncOp *pShareListenParent; CBilink *pBilink; CAsyncOp *pShareParent; IDP8ServiceProvider *pLocalDP8ServiceProvider; SPSHAREENDPOINTINFODATA spShareData;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pGroupAddr [0x%p], pDeviceInfo [0x%p], pdnSecurity [0x%p], pdnCredentials [0x%p], pvAsyncContext [0x%p], phAsyncHandle [0x%p], dwFlags [0x%lx]", pInterface,pGroupAddr,pDeviceInfo,pdnSecurity,pdnCredentials,pvAsyncContext,phAsyncHandle,dwFlags);
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface); DNASSERT(pdnObject != NULL);
#ifndef DPNBUILD_NOPARAMVAL
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateJoin( pInterface, pGroupAddr, pDeviceInfo, pdnSecurity, pdnCredentials, pvAsyncContext,phAsyncHandle,dwFlags ) ) ) { DPFERR( "Error validating join 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); }
// Check to ensure not already connected/connecting
if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTING) { DPFERR( "Object is already connecting" ); DPF_RETURN(DPNERR_CONNECTING); } if (pdnObject->dwFlags & DN_OBJECT_FLAG_CONNECTED) { DPFERR( "Object is already connected" ); DPF_RETURN(DPNERR_ALREADYCONNECTED); } if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING)) { DPFERR( "Object is closing or disconnecting" ); DPF_RETURN(DPNERR_ALREADYCLOSING); }
pIGroup = NULL; pIDevice = NULL; pvNewInterface = NULL; pListenParent = NULL; pParent = NULL; pConnectParent = NULL; pHandleParent = NULL; pSP = NULL; pSyncEvent = NULL;
pdnDeviceObject = NULL; pExistingConnection = NULL; pNTEntry = NULL; pShareSP = NULL; pShareDP8ServiceProvider = NULL; CallbackThread.Deinitialize(); pShareListenParent = NULL; pShareParent = NULL; pLocalDP8ServiceProvider = NULL;
//
// Flag as CONNECTING to prevent other operations here
//
DNEnterCriticalSection(&pdnObject->csDirectNetObject); if (pdnObject->dwFlags & (DN_OBJECT_FLAG_CONNECTING | DN_OBJECT_FLAG_CONNECTED)) { DNLeaveCriticalSection(&pdnObject->csDirectNetObject); hResultCode = DPNERR_ALREADYCONNECTED; goto Failure; } pdnObject->dwFlags |= DN_OBJECT_FLAG_CONNECTING;
// Adding local host flag
//pdnObject->dwFlags |= DN_OBJECT_FLAG_LOCALHOST;
DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
//
// Duplicate specified Group Address, or create a blank one if NULL
//
if (pGroupAddr != NULL) { if ((hResultCode = IDirectPlay8Address_Duplicate(pGroupAddr,&pIGroup)) != DPN_OK) { DPFERR("Could not duplicate group address"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } } else { #ifdef DPNBUILD_LIBINTERFACE
hResultCode = DP8ACF_CreateInstance(IID_IDirectPlay8Address, reinterpret_cast<void**>(&pIGroup)); #else // ! DPNBUILD_LIBINTERFACE
hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay8Address, reinterpret_cast<void**>(&pIGroup), FALSE); #endif // ! DPNBUILD_LIBINTERFACE
if (hResultCode != S_OK) { DPFERR("Could not create Group Address"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } }
//
// Generate a Device Address from the DPlay interface, or duplicate
// the user's. Start by finding out which type of interface it is.
//
if (((IDirectPlay8Peer_QueryInterface((IDirectPlay8Peer*) pDeviceInfo, IID_IDirectPlay8Peer, &pvNewInterface)) == S_OK) || #ifndef DPNBUILD_NOSERVER
((IDirectPlay8Server_QueryInterface((IDirectPlay8Server*) pDeviceInfo, IID_IDirectPlay8Server, &pvNewInterface)) == S_OK) || #endif // ! DPNBUILD_NOSERVER
((IDirectPlay8Client_QueryInterface((IDirectPlay8Client*) pDeviceInfo, IID_IDirectPlay8Client, &pvNewInterface)) == S_OK) || ((IDirectPlay8Multicast_QueryInterface((IDirectPlay8Multicast*) pDeviceInfo, IID_IDirectPlay8Multicast, &pvNewInterface)) == S_OK)) { //
// It's a DIRECTNETOBJECT.
//
pdnDeviceObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pvNewInterface);
DNEnterCriticalSection(&pdnDeviceObject->csDirectNetObject); if (! (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_CONNECTED)) { DPFERR("DirectPlay device object is not connected or hosting" ); DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; } DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject);
//
// Get the host player's connection (if not a multicast object).
//
if (! (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_MULTICAST)) { if ((hResultCode = pdnDeviceObject->NameTable.GetHostPlayerRef(&pNTEntry)) != DPN_OK) { DPFERR("Could not find device object's Host player"); DisplayDNError(0,hResultCode); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; }
//
// If we're the host, then the name table entry won't have a valid
// connection object.
//
if (! pNTEntry->IsLocal()) { hResultCode = pNTEntry->GetConnectionRef(&pExistingConnection); if (hResultCode != DPN_OK) { DPFX(DPFPREP, 0, "Could not find device object's Host player (err = 0x%lx)! Ignoring.", pdnDeviceObject, pExistingConnection); DNASSERT(pExistingConnection == NULL); } }
pNTEntry->Release(); pNTEntry = NULL; }
//
// If we got a connection, simply extract its device address.
// If we couldn't get the non-local host player's connection, we
// have to select the device a different way.
//
if (pExistingConnection != NULL) { if ((hResultCode = pExistingConnection->GetEndPt(&hEndPt,&CallbackThread)) != DPN_OK) { DPFERR( "Couldn't retrieve host player's endpoint" ); DisplayDNError(0, hResultCode); goto Failure; } spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER;
//
// Note that we are calling our Protocol object with the other
// interface's endpoint.
//
hResultCode = DNPCrackEndPointDescriptor(pdnObject->pdnProtocolData, hEndPt,&spInfoData); if (hResultCode != DPN_OK) { DPFERR("Unknown error from DNPCrackEndPointDescriptor"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); pExistingConnection->ReleaseEndPt(&CallbackThread); goto Failure; }
pIDevice = spInfoData.pAddress; spInfoData.pAddress = NULL; pExistingConnection->ReleaseEndPt(&CallbackThread); pShareSP = pExistingConnection->GetSP(); if (pShareSP == NULL) { DPFERR("Could not get host player connection's SP!"); DNASSERT(FALSE); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; }
pExistingConnection->Release(); pExistingConnection = NULL; } else { //
// Get the listen operation.
//
DNEnterCriticalSection(&pdnDeviceObject->csDirectNetObject); if (pdnDeviceObject->pListenParent == NULL) { DNLeaveCriticalSection(&pdnObject->csDirectNetObject); DPFERR("Could not find device object's listen parent operation!"); DNASSERT(FALSE); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; } pdnDeviceObject->pListenParent->AddRef(); pShareListenParent = pdnDeviceObject->pListenParent; DNLeaveCriticalSection(&pdnDeviceObject->csDirectNetObject);
//
// Get the first SP listen.
//
pShareListenParent->Lock(); pBilink = pShareListenParent->m_bilinkParent.GetNext(); if (pBilink == &pShareListenParent->m_bilinkParent) { DPFERR("Could not find device object's first listen operation!"); DNASSERT(FALSE); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; } pShareParent = CONTAINING_OBJECT(pBilink,CAsyncOp,m_bilinkChildren); pShareSP = pShareParent->GetSP(); if (pShareSP == NULL) { DPFERR("Could not get first listen operation's SP!"); DNASSERT(FALSE); hResultCode = DPNERR_INVALIDDEVICEADDRESS; goto Failure; }
pShareSP->AddRef();
pShareListenParent->Unlock(); pShareListenParent->Release(); pShareListenParent = NULL;
#ifndef DPNBUILD_ONLYONESP
//
// Get the share SP's GUID.
//
pShareSP->GetGUID(&guidSP); #endif // ! DPNBUILD_ONLYONESP
//
// Build a device address object.
//
#ifdef DPNBUILD_LIBINTERFACE
hResultCode = DP8ACF_CreateInstance(IID_IDirectPlay8Address, reinterpret_cast<void**>(&pIDevice)); #else // ! DPNBUILD_LIBINTERFACE
hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8Address, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay8Address, reinterpret_cast<void**>(&pIDevice), FALSE); #endif // ! DPNBUILD_LIBINTERFACE
if (hResultCode != S_OK) { DPFERR("Could not create Device Address"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } #ifndef DPNBUILD_ONLYONESP
if ((hResultCode = IDirectPlay8Address_SetSP(pIDevice,&guidSP)) != DPN_OK) { DPFERR("Could not set SP on Device Address"); DisplayDNError(0,hResultCode); goto Failure; } #endif // ! DPNBUILD_ONLYONESP
#ifndef DPNBUILD_ONLYONEADAPTER
//
// For multicast objects we can reuse the same device GUID, too,
// since we know there will be only one.
//
if (pdnDeviceObject->dwFlags & DN_OBJECT_FLAG_MULTICAST) { pShareParent->Lock(); DNASSERT(! pShareParent->IsCancelled()); DNASSERT(! pShareParent->m_bilinkParent.IsEmpty()); pAsyncOp = CONTAINING_OBJECT(pParent->m_bilinkParent.GetNext(),CAsyncOp,m_bilinkChildren); pAsyncOp->Lock(); DNASSERT((! pAsyncOp->IsCancelled()) && (! pAsyncOp->IsComplete())); DNASSERT(pAsyncOp->m_bilinkChildren.GetNext() == &pShareParent->m_bilinkParent); hEndpoint = pAsyncOp->GetProtocolHandle(); pAsyncOp->Unlock(); pShareParent->Unlock();
spInfoData.hEndpoint = hEndpoint; spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER; //
// Note that we are calling our Protocol object with the other
// interface's endpoint.
//
if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK) { DPFERR("Could not get LISTEN device address!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; }
//
// Retrieve the device GUID from the listen address.
//
if ((hResultCode = IDirectPlay8Address_GetDevice(spInfoData.pAddress, &guidAdapter)) != DPN_OK) { DPFERR("Could not get adapter GUID!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); IDirectPlay8Address_Release(spInfoData.pAddress); spInfoData.pAddress = NULL; goto Failure; }
IDirectPlay8Address_Release(spInfoData.pAddress); spInfoData.pAddress = NULL;
//
// Store the device GUID on our device address.
//
if ((hResultCode = IDirectPlay8Address_SetDevice(pIDevice, &guidAdapter)) != DPN_OK) { DPFERR("Could not set adapter GUID!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } } #endif // ! DPNBUILD_ONLYONEADAPTER
}
//
// Get the share SP's COM interface.
//
if ((hResultCode = pShareSP->GetInterfaceRef(&pShareDP8ServiceProvider)) != DPN_OK) { DPFERR("Could not get shared SP interface"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } pShareSP->Release(); pShareSP = NULL;
//
// Load our own local instance of that SP.
//
hResultCode = DN_SPEnsureLoaded(pdnObject, #ifndef DPNBUILD_ONLYONESP
&guidSP, #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; }
//
// Get the local SP's COM interface.
//
if ((hResultCode = pSP->GetInterfaceRef(&pLocalDP8ServiceProvider)) != DPN_OK) { DPFERR("Could not get local SP interface"); DisplayDNError(0,hResultCode); goto Failure; }
//
// Tell our SP interface to get its endpoint information from the
// other interface's SP.
//
spShareData.pDP8ServiceProvider = pShareDP8ServiceProvider; spShareData.dwFlags = 0; hResultCode = IDP8ServiceProvider_ShareEndpointInfo(pLocalDP8ServiceProvider, &spShareData); if (hResultCode != DPN_OK) { DPFERR("Could not have SPs share endpoint info"); DisplayDNError(0,hResultCode); goto Failure; } IDP8ServiceProvider_Release(pLocalDP8ServiceProvider); pLocalDP8ServiceProvider = NULL; IDP8ServiceProvider_Release(pShareDP8ServiceProvider); pShareDP8ServiceProvider = NULL;
//
// Release the ref we held on the device object.
//
IDirectPlay8Peer_Release((IDirectPlay8Peer*) pvNewInterface); // all core objects have Release in same location in Vtbl
pvNewInterface = NULL; } else if ((IDirectPlay8Address_QueryInterface((IDirectPlay8Address*) pDeviceInfo, IID_IDirectPlay8Address, &pvNewInterface)) == S_OK) { //
// It's an address.
//
IDirectPlay8Address_Release((IDirectPlay8Address*) pvNewInterface); pvNewInterface = NULL; if ((hResultCode = IDirectPlay8Address_Duplicate(reinterpret_cast<IDirectPlay8Address*>(pDeviceInfo),&pIDevice)) != DPN_OK) { DPFERR("Could not duplicate device info"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } } else { DPFERR( "Invalid device address, it must be an IDirectPlay8Peer, IDirectPlay8Server, IDirectPlay8Client, IDirectPlay8Multicast, or IDirectPlay8Address object" ); return( DPNERR_INVALIDDEVICEADDRESS ); }
#ifndef DPNBUILD_ONLYONESP
//
// If there is no SP on the group address, then steal it from the device address
//
if ((hResultCode = IDirectPlay8Address_GetSP(pIGroup,&guidSP)) != DPN_OK) { if ((hResultCode = IDirectPlay8Address_GetSP(pIDevice,&guidSP)) != DPN_OK) { DPFERR("Could not retrieve SP from Device Address"); DisplayDNError(0,hResultCode); goto Failure; } if ((hResultCode = IDirectPlay8Address_SetSP(pIGroup,&guidSP)) != DPN_OK) { DPFERR("Could not set SP on Group Address"); DisplayDNError(0,hResultCode); goto Failure; } } #endif // ! DPNBUILD_ONLYONESP
//
// Ensure SP is loaded, if we haven't already.
//
if (pSP == NULL) { hResultCode = DN_SPEnsureLoaded(pdnObject, #ifndef DPNBUILD_ONLYONESP
&guidSP, #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; } }
#ifndef DPNBUILD_ONLYONEADAPTER
//
// Multicast listen device addresses are formed by taking the adapter GUID from
// the user's device address, combined with the entire user specified group address.
// If there is no adapter, then we will pick the best one as reported by the service
// provider (that part occurs inside DNPerformSPListen).
//
if ((hResultCode = IDirectPlay8Address_GetDevice(pIDevice,&guidAdapter)) == DPN_OK) { if ((hResultCode = IDirectPlay8Address_SetDevice(pIGroup,&guidAdapter)) != DPN_OK) { DPFERR("Could not set SP on Group Address"); DisplayDNError(0,hResultCode); goto Failure; } } #endif // ! DPNBUILD_ONLYONEADAPTER
dwListenFlags = DN_LISTENFLAGS_MULTICAST; if (dwFlags & DPNJOIN_ALLOWUNKNOWNSENDERS) { dwListenFlags |= DN_LISTENFLAGS_ALLOWUNKNOWNSENDERS; }
//
// Start multicast listen
//
if ((hResultCode = AsyncOpNew(pdnObject,&pListenParent)) != DPN_OK) { DPFERR("Could not create AsyncOp"); DisplayDNError(0,hResultCode); goto Failure; } pListenParent->SetOpType( ASYNC_OP_LISTEN_MULTICAST ); pListenParent->SetOpFlags( dwListenFlags ); pListenParent->MakeParent(); pListenParent->SetCompletion( DNCompleteListen );
// See note above about why it's pIGroup instead of pIDevice.
if ((hResultCode = DNPerformSPListen(pdnObject,pIGroup,pListenParent,&pParent)) != DPN_OK) { DPFERR("Could not start LISTEN"); DisplayDNError(0,hResultCode); goto Failure; }
pListenParent->AddRef(); DNEnterCriticalSection(&pdnObject->csDirectNetObject); pdnObject->pListenParent = pListenParent; DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
pListenParent->Release(); pListenParent = NULL;
//
// Multicast send endpoints are created using the user specified device address for the
// device, and what the SP reports it's using for the multicast listen as the group
// address.
//
pParent->Lock(); DNASSERT(! pParent->IsCancelled()); DNASSERT(! pParent->m_bilinkParent.IsEmpty()); pAsyncOp = CONTAINING_OBJECT(pParent->m_bilinkParent.GetNext(),CAsyncOp,m_bilinkChildren); pAsyncOp->Lock(); DNASSERT((! pAsyncOp->IsCancelled()) && (! pAsyncOp->IsComplete())); DNASSERT(pAsyncOp->m_bilinkChildren.GetNext() == &pParent->m_bilinkParent); hEndpoint = pAsyncOp->GetProtocolHandle(); pAsyncOp->Unlock(); pParent->Unlock();
spInfoData.hEndpoint = hEndpoint; spInfoData.Flags = SP_GET_ADDRESS_INFO_MULTICAST_GROUP; if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK) { DPFERR("Could not get LISTEN multicast group address!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } // Release the old group address and save this new one.
IDirectPlay8Address_Release(pIGroup); pIGroup = spInfoData.pAddress; spInfoData.pAddress = NULL;
//
// If the user did not specify an adapter GUID, we selected one and we need to
// copy that selection over to the connect operation's device address. If the user
// did specify an adapter GUID, then this DNPGetListenAddressInfo will just be
// echoing it back, so there's no harm in copying it in either case.
//
spInfoData.hEndpoint = hEndpoint; spInfoData.Flags = SP_GET_ADDRESS_INFO_LOCAL_ADAPTER; if ((hResultCode = DNPGetListenAddressInfo(pdnObject->pdnProtocolData, spInfoData.hEndpoint,&spInfoData)) != DPN_OK) { DPFERR("Could not get LISTEN device address!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } #ifndef DPNBUILD_ONLYONEADAPTER
if ((hResultCode = IDirectPlay8Address_GetDevice(spInfoData.pAddress,&guidAdapter)) != DPN_OK) { DPFERR("Could not get LISTEN device GUID!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); IDirectPlay8Address_Release(spInfoData.pAddress); spInfoData.pAddress = NULL; goto Failure; } if ((hResultCode = IDirectPlay8Address_SetDevice(pIDevice,&guidAdapter)) != DPN_OK) { DPFERR("Could not set CONNECT device GUID!"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); IDirectPlay8Address_Release(spInfoData.pAddress); spInfoData.pAddress = NULL; goto Failure; } #endif // ! DPNBUILD_ONLYONEADAPTER
//
// Keep device address and connect SP on DirectNet object
//
pSP->AddRef(); DNEnterCriticalSection(&pdnObject->csDirectNetObject); pdnObject->pIDP8ADevice = spInfoData.pAddress; // Transfering reference
spInfoData.pAddress = NULL; pdnObject->pConnectSP = pSP; DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
pParent->Release(); pParent = NULL;
//
// Create parent async op, which will be released when the ENTIRE connection is finished
//
if ((hResultCode = AsyncOpNew(pdnObject,&pConnectParent)) != DPN_OK) { DPFERR("Could not create AsyncOp"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } pConnectParent->SetOpType( ASYNC_OP_CONNECT_MULTICAST_SEND ); pConnectParent->MakeParent(); pConnectParent->SetResult( DPNERR_NOCONNECTION ); pConnectParent->SetCompletion( DNCompleteJoinOperation ); // pConnectParent->SetReserved(1);
if (dwFlags & DPNCONNECT_SYNC) { DPFX(DPFPREP, 5,"Sync operation - create sync event"); if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK) { DPFERR("Could not create synchronization event"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } pConnectParent->SetSyncEvent( pSyncEvent ); pConnectParent->SetResultPointer( &hrOperation ); } else { DPFX(DPFPREP, 5,"Async operation - create handle parent"); if ((hResultCode = DNCreateUserHandle(pdnObject,&pHandleParent)) != DPN_OK) { DPFERR("Could not create handle parent"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); goto Failure; } pHandleParent->SetContext( pvAsyncContext );
pHandleParent->Lock(); if (pHandleParent->IsCancelled()) { pHandleParent->Unlock(); pConnectParent->SetResult( DPNERR_USERCANCEL ); hResultCode = DPNERR_USERCANCEL; goto Failure; } pConnectParent->MakeChild( pHandleParent ); pHandleParent->Unlock(); }
hResultCode = DNPerformConnect(pdnObject, 0, pIDevice, pIGroup, pSP, DN_CONNECTFLAGS_MULTICAST_SEND, pConnectParent); if (hResultCode != DPN_OK) { DPFERR("Could not start CONNECT"); goto Failure; }
pConnectParent->Release(); pConnectParent = NULL;
pSP->Release(); pSP = NULL;
if (pIGroup) { IDirectPlay8Address_Release(pIGroup); pIGroup = NULL; }
if (pIDevice) { IDirectPlay8Address_Release(pIDevice); pIDevice = NULL; }
if (dwFlags & DPNCONNECT_SYNC) { if ((hResultCode = pSyncEvent->WaitForEvent()) != DPN_OK) { DPFERR("DNSyncEventWait() terminated bizarrely"); DNASSERT(FALSE); } else { hResultCode = hrOperation; } pSyncEvent->ReturnSelfToPool(); pSyncEvent = NULL; } else { pHandleParent->SetCompletion( DNCompleteUserJoin ); if (phAsyncHandle) { *phAsyncHandle = pHandleParent->GetHandle(); } pHandleParent->Release(); pHandleParent = NULL;
hResultCode = DPNERR_PENDING; }
Exit:
CallbackThread.Deinitialize(); DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode);
Failure:
if (pIGroup) { IDirectPlay8Address_Release(pIGroup); pIGroup = NULL; } if (pIDevice) { IDirectPlay8Address_Release(pIDevice); pIDevice = NULL; } if (pExistingConnection != NULL) { pExistingConnection->Release(); pExistingConnection = NULL; } if (pShareListenParent != NULL) { pShareListenParent->Unlock(); pShareListenParent->Release(); pShareListenParent = NULL; } if (pShareSP != NULL) { pShareSP->Release(); pShareSP = NULL; } if (pShareDP8ServiceProvider != NULL) { IDP8ServiceProvider_Release(pShareDP8ServiceProvider); pShareDP8ServiceProvider = NULL; } if (pLocalDP8ServiceProvider != NULL) { IDP8ServiceProvider_Release(pLocalDP8ServiceProvider); pLocalDP8ServiceProvider = NULL; } if (pvNewInterface != NULL) { // Even if it's not an address, the Vtbl should be the same.
IDirectPlay8Address_Release((IDirectPlay8Address*) pvNewInterface); pvNewInterface = NULL; } if (pSP) { pSP->Release(); pSP = NULL; } if (pListenParent) { pListenParent->Release(); pListenParent = NULL; } if (pListenParent) { pParent->Release(); pParent = NULL; } if (pConnectParent) { if (SUCCEEDED(pdnObject->HandleTable.Destroy( pConnectParent->GetHandle(), NULL ))) { // Release the HandleTable reference
pConnectParent->Release(); } pConnectParent->Release(); pConnectParent = NULL; } if (pHandleParent) { pHandleParent->Release(); pHandleParent = NULL; } if (pSyncEvent) { pSyncEvent->ReturnSelfToPool(); pSyncEvent = NULL; }
DNEnterCriticalSection(&pdnObject->csDirectNetObject); pListenParent = pdnObject->pListenParent; pdnObject->pListenParent = NULL; pSP = pdnObject->pConnectSP; pdnObject->pConnectSP = NULL; pIDevice = pdnObject->pIDP8ADevice; pdnObject->pIDP8ADevice = NULL; DNLeaveCriticalSection(&pdnObject->csDirectNetObject); if (pListenParent) { DNCancelChildren(pdnObject,pListenParent); pListenParent->Release(); pListenParent = NULL; } if (pSP) { pSP->Release(); pSP = NULL; } if (pIDevice) { IDirectPlay8Address_Release(pIDevice); pIDevice = NULL; }
DNEnterCriticalSection(&pdnObject->csDirectNetObject); pdnObject->dwFlags &= ~(DN_OBJECT_FLAG_CONNECTING|DN_OBJECT_FLAG_CONNECTED|DN_OBJECT_FLAG_LOCALHOST); DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
goto Exit; } // DN_Join
//
// Completion for create sender context
//
#undef DPF_MODNAME
#define DPF_MODNAME "DNCompleteCreateSenderContext"
void DNCompleteCreateSenderContext(DIRECTNETOBJECT *const pdnObject, CAsyncOp *const pAsyncOp) { }
//
// Associate a context value with a given multicast sender's address
//
#undef DPF_MODNAME
#define DPF_MODNAME "DN_CreateSenderContext"
STDMETHODIMP DN_CreateSenderContext( IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, void *const pvSenderContext, const DWORD dwFlags ) { HRESULT hResultCode; PDIRECTNETOBJECT pdnObject; IDirectPlay8Address *pIDevice; CServiceProvider *pSP; CAsyncOp *pConnectParent; CSyncEvent *pSyncEvent; HRESULT hrConnect;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pSenderAddress [0x%p], pvSenderContext [0x%p], dwFlags [0x%lx]", pInterface,pSenderAddress,pvSenderContext,dwFlags);
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface); DNASSERT(pdnObject != NULL);
#ifndef DPNBUILD_NOPARAMVAL
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateCreateSenderContext( pInterface, pSenderAddress, pvSenderContext, dwFlags ) ) ) { DPFERR( "Error validating params" ); DPF_RETURN(hResultCode); } } #endif // DPNBUILD_NOPARAMVAL
if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) ) { DPFERR( "Object is not initialized" ); DPF_RETURN( DPNERR_UNINITIALIZED ); }
pIDevice = NULL; pSP = NULL; pConnectParent = NULL; pSyncEvent = NULL;
#pragma BUGBUG( minara, "Need to ensure not closing" )
//
// Extract device and SP from DirectNet object
//
DNEnterCriticalSection(&pdnObject->csDirectNetObject); DNASSERT( pdnObject->pConnectSP != NULL ); DNASSERT( pdnObject->pIDP8ADevice != NULL ); if (pdnObject->pConnectSP) { pdnObject->pConnectSP->AddRef(); pSP = pdnObject->pConnectSP; } if (pdnObject->pIDP8ADevice) { IDirectPlay8Address_AddRef(pdnObject->pIDP8ADevice); pIDevice = pdnObject->pIDP8ADevice; } DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
if (pSP == NULL || pIDevice == NULL) { DPFERR("Invalid connect SP or device address"); hResultCode = DPNERR_GENERIC; goto Failure; }
//
// Create SyncEvent
//
if ((hResultCode = SyncEventNew(pdnObject,&pSyncEvent)) != DPN_OK) { DPFERR("Could not create SyncEvent"); goto Failure; }
//
// Create AsyncOp parent
//
if ((hResultCode = AsyncOpNew(pdnObject,&pConnectParent)) != DPN_OK) { DPFERR("Could not create AsyncOp"); goto Failure; } pConnectParent->SetOpType( ASYNC_OP_CONNECT_MULTICAST_RECEIVE ); pConnectParent->SetSyncEvent( pSyncEvent ); pConnectParent->SetResultPointer( &hrConnect ); pConnectParent->SetContext( pvSenderContext );
//
// We will call connect on the Protocol to associate the sender's endpoint with a context
// This call to connect must be turned into a synchronous operation since this API call is synchronous
//
if ((hResultCode = DNPerformConnect(pdnObject, 0, pIDevice, pSenderAddress, pSP, DN_CONNECTFLAGS_MULTICAST_RECEIVE, pConnectParent)) != DPN_OK) { DPFERR("Failed to connect"); DisplayDNError(0,hResultCode); goto Failure; }
//
// Release references and wait for completion
//
pConnectParent->SetCompletion( DNCompleteCreateSenderContext ); pConnectParent->Release(); pConnectParent = NULL; pSP->Release(); pSP = NULL; IDirectPlay8Address_Release(pIDevice); pIDevice = NULL;
pSyncEvent->WaitForEvent(); pSyncEvent->ReturnSelfToPool(); pSyncEvent = NULL;
if (hrConnect == DPN_OK) { DNUserCreateSenderContext(pdnObject,pvSenderContext); }
hResultCode = hrConnect; Exit: DNASSERT( pIDevice == NULL ); DNASSERT( pSP == NULL ); DNASSERT( pConnectParent == NULL ); DNASSERT( pSyncEvent == NULL );
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode);
Failure: if (pIDevice) { IDirectPlay8Address_Release(pIDevice); pIDevice = NULL; } if (pSP) { pSP->Release(); pSP = NULL; } if (pConnectParent) { pConnectParent->Release(); pConnectParent = NULL; } if (pSyncEvent) { pSyncEvent->ReturnSelfToPool(); pSyncEvent = NULL; } goto Exit; } // DN_CreateSenderContext
//
// Removes a previously associated context value from a given multicast sender's address
//
#undef DPF_MODNAME
#define DPF_MODNAME "DN_DestroySenderContext"
STDMETHODIMP DN_DestroySenderContext( IDirectPlay8Multicast *pInterface, IDirectPlay8Address *const pSenderAddress, const DWORD dwFlags ) { HRESULT hResultCode; DIRECTNETOBJECT *pdnObject; CServiceProvider *pSP; CConnection *pConnection; IDirectPlay8Address *pDevice;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pSenderAddress [0x%p], dwFlags [0x%lx]", pInterface,pSenderAddress,dwFlags);
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface); DNASSERT(pdnObject != NULL);
#ifndef DPNBUILD_NOPARAMVAL
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateDestroySenderContext( pInterface, pSenderAddress, dwFlags ) ) ) { DPFERR( "Error validating params" ); DPF_RETURN(hResultCode); } } #endif // DPNBUILD_NOPARAMVAL
if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) ) { DPFERR( "Object is not initialized" ); DPF_RETURN( DPNERR_UNINITIALIZED ); }
pSP = NULL; pConnection = NULL;
DNEnterCriticalSection(&pdnObject->csDirectNetObject); if (pdnObject->pIDP8ADevice) { IDirectPlay8Address_AddRef(pdnObject->pIDP8ADevice); pDevice = pdnObject->pIDP8ADevice; } if (pdnObject->pConnectSP) { pdnObject->pConnectSP->AddRef(); pSP = pdnObject->pConnectSP; } DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
//
// Get endpoint from address
//
if ((hResultCode = DNPGetEndPointContextFromAddress(pdnObject->pdnProtocolData, pSP->GetHandle(),pSenderAddress,pDevice,reinterpret_cast<void**>(&pConnection))) == DPN_OK) { pConnection->AddRef();
pConnection->Disconnect(); pConnection->Release(); pConnection = NULL; }
//
// Clean up
//
IDirectPlay8Address_Release(pDevice); pDevice = NULL;
pSP->Release(); pSP = NULL;
hResultCode = DPN_OK;
DNASSERT( pSP == NULL ); DNASSERT( pConnection == NULL );
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode); } // DN_DestroySenderContext
//
// Retrieves the current multicast group address
//
#undef DPF_MODNAME
#define DPF_MODNAME "DN_GetGroupAddress"
STDMETHODIMP DN_GetGroupAddress(IDirectPlay8Multicast *pInterface, IDirectPlay8Address **const ppAddress, const DWORD dwFlags) { HRESULT hResultCode; DIRECTNETOBJECT *pdnObject; CConnection *pConnection; HANDLE hEndPt; SPGETADDRESSINFODATA spInfoData; CCallbackThread CallbackThread;
DPFX(DPFPREP, 2,"Parameters : pInterface [0x%p], ppAddress [0x%p], dwFlags [0x%lx]", pInterface,ppAddress,dwFlags);
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface); DNASSERT(pdnObject != NULL);
#ifndef DPNBUILD_NOPARAMVAL
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateGetGroupAddress( pInterface, ppAddress, dwFlags ) ) ) { DPFX(DPFPREP, 0, "Error validating get group address info hr=[0x%lx]", hResultCode ); 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 | DN_OBJECT_FLAG_CLOSING | DN_OBJECT_FLAG_DISCONNECTING) ) ) { DPFERR("You must be connected / disconnecting to use this function" ); DPF_RETURN(DPNERR_NOCONNECTION); }
CallbackThread.Initialize();
DNEnterCriticalSection(&pdnObject->csDirectNetObject); if (pdnObject->pMulticastSend != NULL) { pdnObject->pMulticastSend->AddRef(); pConnection = pdnObject->pMulticastSend; } else { pConnection = NULL; } DNLeaveCriticalSection(&pdnObject->csDirectNetObject);
if (pConnection == NULL) { DPFERR( "Couldn't retrieve multicast send connection" ); hResultCode = DPNERR_INVALIDGROUP; goto Failure; }
//
// Get the remote multicast address address
//
if ((hResultCode = pConnection->GetEndPt(&hEndPt,&CallbackThread)) != DPN_OK) { DPFERR( "Couldn't retrieve multicast send endpoint" ); DisplayDNError(0, hResultCode); goto Failure; } spInfoData.Flags = SP_GET_ADDRESS_INFO_MULTICAST_GROUP;
hResultCode = DNPCrackEndPointDescriptor(pdnObject->pdnProtocolData, hEndPt,&spInfoData); if (hResultCode != DPN_OK) { DPFERR("Unknown error from DNPCrackEndPointDescriptor"); DisplayDNError(0,hResultCode); DNASSERT(FALSE);
// Drop through...
} pConnection->ReleaseEndPt(&CallbackThread);
pConnection->Release(); pConnection = NULL;
*ppAddress = spInfoData.pAddress; spInfoData.pAddress = NULL;
Exit: CallbackThread.Deinitialize(); DPF_RETURN(hResultCode);
Failure: if (pConnection) { pConnection->Release(); pConnection = NULL; }
goto Exit; } // DN_GetGroupAddress
//
// Enumerate multicast scopes reported by SP
//
#undef DPF_MODNAME
#define DPF_MODNAME "DN_EnumMulticastScopes"
STDMETHODIMP DN_EnumMulticastScopes( IDirectPlay8Multicast *pInterface, const GUID *const pguidServiceProvider, const GUID *const pguidDevice, const GUID *const pguidApplication, DPN_MULTICAST_SCOPE_INFO *const pScopeInfoBuffer, DWORD *const pcbEnumData, DWORD *const pcReturned, const DWORD dwFlags ) { HRESULT hResultCode; PDIRECTNETOBJECT pdnObject;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], pguidServiceProvider [0x%p], pguidDevice [0x%p], pguidApplication [0x%p], pScopeInfoBuffer [0x%p], pcbEnumData [0x%p], pcReturned [0x%p], dwFlags [0x%lx]", pInterface,pguidServiceProvider,pguidDevice,pguidApplication,pScopeInfoBuffer,pcbEnumData,pcReturned,dwFlags);
pdnObject = (DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(pInterface); DNASSERT(pdnObject != NULL);
#ifndef DPNBUILD_NOPARAMVAL
if( pdnObject->dwFlags & DN_OBJECT_FLAG_PARAMVALIDATION ) { if( FAILED( hResultCode = DN_ValidateEnumMulticastScopes( pInterface, pguidServiceProvider, pguidDevice, pguidApplication, pScopeInfoBuffer, pcbEnumData, pcReturned, dwFlags ) ) ) { DPFERR( "Error validating params" ); DPF_RETURN(hResultCode); } } #endif // DPNBUILD_NOPARAMVAL
if( !(pdnObject->dwFlags & DN_OBJECT_FLAG_INITIALIZED) ) { DPFERR( "Object is not initialized" ); DPF_RETURN( DPNERR_UNINITIALIZED ); }
hResultCode = DN_EnumMulticastScopes(pdnObject, dwFlags, #ifndef DPNBUILD_ONLYONESP
pguidServiceProvider, #endif // ! DPNBUILD_ONLYONESP
#ifndef DPNBUILD_ONLYONEADAPTER
pguidDevice, #endif // ! DPNBUILD_ONLYONEADAPTER
#ifndef DPNBUILD_LIBINTERFACE
pguidApplication, #endif // ! DPNBUILD_LIBINTERFACE
pScopeInfoBuffer, pcbEnumData, pcReturned);
DPFX(DPFPREP, 3,"Set: *pcbEnumData [%ld], *pcReturned [%ld]",*pcbEnumData,*pcReturned);
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode); return(hResultCode); } // DN_EnumMulticastScopes
#endif // ! DPNBUILD_NOMULTICAST
|