|
|
/*==========================================================================
* * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved. * * File: Enum.cpp * Content: This file contains support enuming sessions. * * History: * Date By Reason * ==== == ====== * 01/10/00 jtk Created * 07/01/2000 masonb Assumed Ownership * ****************************************************************************/
#include "dnproti.h"
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
//**********************************************************************
// Variable definitions
//**********************************************************************
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Function definitions
//**********************************************************************
/*
** Send Enum Query ** ** This routine will send out a broadcast to everyone that can hear ** indicating this side's interest in finding listening connections. ** Interested connections will respond through IndicateEnumResponse. */
#undef DPF_MODNAME
#define DPF_MODNAME "DNPEnumQuery"
HRESULT DNPEnumQuery(HANDLE hProtocolData, IDirectPlay8Address* paHostAddress, IDirectPlay8Address* paDeviceAddress, HANDLE hSPHandle, BUFFERDESC* pBuffers, DWORD dwBufferCount, DWORD dwRetryCount, DWORD dwRetryInterval, DWORD dwTimeout, DWORD dwFlags, VOID* pvUserContext, VOID* pvSessionData, DWORD dwSessionDataSize, HANDLE* phEnumHandle) { ProtocolData* pPData; PSPD pSPD; PMSD pMSD; SPENUMQUERYDATA EnumData; HRESULT hr; #ifdef DBG
ULONG ulAllowedFlags; #endif // DBG
DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: hProtocolData[%p], paHostAddress[%p], paDeviceAddress[%p], hSPHandle[%p], pBuffers[%p], dwBufferCount[%x], dwRetryCount[%x], dwRetryInterval[%x], dwTimeout[%x], dwFlags[%x], pvUserContext[%p], pvSessionData[%p], dwSessionDataSize[%u], phEnumHandle[%p]", hProtocolData, paHostAddress, paDeviceAddress, hSPHandle, pBuffers, dwBufferCount, dwRetryCount, dwRetryInterval, dwTimeout, dwFlags, pvUserContext, pvSessionData, dwSessionDataSize, phEnumHandle);
hr = DPNERR_PENDING; pPData = (ProtocolData*)hProtocolData; ASSERT_PPD(pPData);
pSPD = (PSPD) hSPHandle; ASSERT_SPD(pSPD);
// Core should not call any Protocol APIs after calling DNPRemoveServiceProvider
ASSERT(!(pSPD->ulSPFlags & SPFLAGS_TERMINATING));
// We use an MSD to describe this Op even though it isn't technically a message
if((pMSD = (PMSD)POOLALLOC(MEMID_ENUMQUERY_MSD, &MSDPool)) == NULL) { DPFX(DPFPREP,0, "Failed to allocate MSD"); hr = DPNERR_OUTOFMEMORY; goto Exit; }
pMSD->CommandID = COMMAND_ID_ENUM; pMSD->pSPD = pSPD; pMSD->Context = pvUserContext;
EnumData.pAddressHost = paHostAddress; EnumData.pAddressDeviceInfo = paDeviceAddress; EnumData.pBuffers = pBuffers; EnumData.dwBufferCount = dwBufferCount; EnumData.dwTimeout = dwTimeout; EnumData.dwRetryCount = dwRetryCount; EnumData.dwRetryInterval = dwRetryInterval;
#ifdef DBG
ulAllowedFlags = DN_ENUMQUERYFLAGS_NOBROADCASTFALLBACK | DN_ENUMQUERYFLAGS_SESSIONDATA; #ifndef DPNBUILD_NOSPUI
ulAllowedFlags |= DN_ENUMQUERYFLAGS_OKTOQUERYFORADDRESSING; #endif // ! DPNBUILD_NOSPUI
#ifndef DPNBUILD_ONLYONEADAPTER
ulAllowedFlags |= DN_ENUMQUERYFLAGS_ADDITIONALMULTIPLEXADAPTERS; #endif // ! DPNBUILD_ONLYONEADAPTER
DNASSERT( ( dwFlags & ~(ulAllowedFlags) ) == 0 ); #endif // DBG
EnumData.dwFlags = 0; #ifndef DPNBUILD_NOSPUI
if ( ( dwFlags & DN_ENUMQUERYFLAGS_OKTOQUERYFORADDRESSING ) != 0 ) { EnumData.dwFlags |= DPNSPF_OKTOQUERY; } #endif // ! DPNBUILD_NOSPUI
if ( ( dwFlags & DN_ENUMQUERYFLAGS_NOBROADCASTFALLBACK ) != 0 ) { EnumData.dwFlags |= DPNSPF_NOBROADCASTFALLBACK; }
#ifndef DPNBUILD_ONLYONEADAPTER
if ( ( dwFlags & DN_ENUMQUERYFLAGS_ADDITIONALMULTIPLEXADAPTERS ) != 0 ) { EnumData.dwFlags |= DPNSPF_ADDITIONALMULTIPLEXADAPTERS; } #endif // ! DPNBUILD_ONLYONEADAPTER
if ( ( dwFlags & DN_ENUMQUERYFLAGS_SESSIONDATA) != 0 ) { EnumData.dwFlags |= DPNSPF_SESSIONDATA; EnumData.pvSessionData = pvSessionData; EnumData.dwSessionDataSize = dwSessionDataSize; }
EnumData.pvContext = pMSD; EnumData.hCommand = NULL;
*phEnumHandle = pMSD;
#ifdef DBG
Lock(&pSPD->SPLock); pMSD->blSPLinkage.InsertBefore( &pSPD->blMessageList); // Dont support timeouts for Listen
pMSD->ulMsgFlags1 |= MFLAGS_ONE_ON_GLOBAL_LIST; Unlock(&pSPD->SPLock); #endif // DBG
pMSD->ulMsgFlags1 |= MFLAGS_ONE_IN_SERVICE_PROVIDER; LOCK_MSD(pMSD, "SP Ref"); // AddRef for SP
LOCK_MSD(pMSD, "Temp Ref");
AssertNoCriticalSectionsFromGroupTakenByThisThread(&g_blProtocolCritSecsHeld);
DPFX(DPFPREP,DPF_CALLOUT_LVL, "Calling SP->EnumQuery, pSPD[%p], pMSD[%p]", pSPD, pMSD); /**/hr = IDP8ServiceProvider_EnumQuery(pSPD->IISPIntf, &EnumData); /** CALL SP **/
if(hr != DPNERR_PENDING) { // This should always Pend or else be in error
DPFX(DPFPREP,1, "Calling SP->EnumQuery Failed, return is not DPNERR_PENDING, hr[%x], pMSD[%p], pSPD[%p]", hr, pMSD, pSPD);
// DPNERR_PENDING is the only success code we accept
ASSERT(FAILED(hr));
Lock(&pMSD->CommandLock); pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_IN_SERVICE_PROVIDER);
#ifdef DBG
Lock(&pSPD->SPLock); pMSD->blSPLinkage.RemoveFromList(); // knock this off the pending list
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_ON_GLOBAL_LIST); Unlock(&pSPD->SPLock); #endif // DBG
DECREMENT_MSD(pMSD, "Temp Ref"); DECREMENT_MSD(pMSD, "SP Ref"); // release once for SP
RELEASE_MSD(pMSD, "Release On Fail"); // release again to return resource
goto Exit; }
Lock(&pMSD->CommandLock);
pMSD->hCommand = EnumData.hCommand; // retain SP command handle
pMSD->dwCommandDesc = EnumData.dwCommandDescriptor;
RELEASE_MSD(pMSD, "Temp Ref"); // Unlocks CommandLock
Exit: DPFX(DPFPREP,DPF_CALLIN_LVL, "Returning hr[%x], pMSD[%p]", hr, pMSD);
AssertNoCriticalSectionsFromGroupTakenByThisThread(&g_blProtocolCritSecsHeld);
return hr; }
/*
** Enum Respond ** ** This routine will send out a response to a received enum query. */
#undef DPF_MODNAME
#define DPF_MODNAME "DNPEnumRespond"
HRESULT DNPEnumRespond(HANDLE hProtocolData, HANDLE hSPHandle, HANDLE hQueryHandle, BUFFERDESC* pBuffers, DWORD dwBufferCount, DWORD dwFlags, VOID* pvUserContext, HANDLE* phEnumHandle) { ProtocolData* pPData; PSPD pSPD; PMSD pMSD; SPENUMRESPONDDATA EnumRespondData; HRESULT hr;
DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: hProtocolData[%p], hSPHandle[%p], hQueryHandle[%p], pBuffers[%p], dwBufferCount[%x], dwFlags[%x], pvUserContext[%p], phEnumHandle[%p]", hProtocolData, hSPHandle, hQueryHandle, pBuffers, dwBufferCount, dwFlags, pvUserContext, phEnumHandle);
hr = DPNERR_PENDING; pPData = (ProtocolData*)hProtocolData; ASSERT_PPD(pPData);
pSPD = (PSPD)hSPHandle; ASSERT_SPD(pSPD);
ASSERT(hQueryHandle);
// Core should not call any Protocol APIs after calling DNPRemoveServiceProvider
ASSERT(!(pSPD->ulSPFlags & SPFLAGS_TERMINATING));
// We use an MSD to describe this Op even though it isn't technically a message
if((pMSD = (PMSD)POOLALLOC(MEMID_ENUMRESP_MSD, &MSDPool)) == NULL) { DPFX(DPFPREP,0, "Failed to allocate MSD"); hr = DPNERR_OUTOFMEMORY; goto Exit; }
pMSD->CommandID = COMMAND_ID_ENUMRESP; pMSD->pSPD = pSPD; pMSD->Context = pvUserContext;
EnumRespondData.pBuffers = pBuffers; EnumRespondData.dwBufferCount = dwBufferCount; EnumRespondData.dwFlags = dwFlags; EnumRespondData.pvContext = pMSD; EnumRespondData.hCommand = NULL; EnumRespondData.pQuery = (SPIE_QUERY*)hQueryHandle;
*phEnumHandle = pMSD;
#ifdef DBG
Lock(&pSPD->SPLock); pMSD->blSPLinkage.InsertBefore( &pSPD->blMessageList); pMSD->ulMsgFlags1 |= MFLAGS_ONE_ON_GLOBAL_LIST; Unlock(&pSPD->SPLock); #endif // DBG
pMSD->ulMsgFlags1 |= MFLAGS_ONE_IN_SERVICE_PROVIDER; LOCK_MSD(pMSD, "SP Ref"); // AddRef for SP
LOCK_MSD(pMSD, "Temp Ref");
AssertNoCriticalSectionsFromGroupTakenByThisThread(&g_blProtocolCritSecsHeld);
DPFX(DPFPREP,DPF_CALLOUT_LVL, "Calling SP->EnumRespond, pSPD[%p], pMSD[%p]", pSPD, pMSD); /**/hr = IDP8ServiceProvider_EnumRespond(pSPD->IISPIntf, &EnumRespondData); /** CALL SP **/
// This should always Pend or else be in error
if(hr != DPNERR_PENDING) { DPFX(DPFPREP,1, "Calling SP->EnumRespond, return is not DPNERR_PENDING, hr[%x], pMSD[%p], pSPD[%p]", hr, pMSD, pSPD);
// DPNERR_PENDING is the only success code we accept
ASSERT(FAILED(hr));
Lock(&pMSD->CommandLock); pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_IN_SERVICE_PROVIDER);
#ifdef DBG
Lock(&pSPD->SPLock); pMSD->blSPLinkage.RemoveFromList(); // knock this off the pending list
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_ON_GLOBAL_LIST); Unlock(&pSPD->SPLock); #endif // DBG
DECREMENT_MSD(pMSD, "Temp Ref"); DECREMENT_MSD(pMSD, "SP Ref"); // release once for SP
RELEASE_MSD(pMSD, "Release On Non-Pend"); // release again to return resource
goto Exit; }
Lock(&pMSD->CommandLock);
pMSD->hCommand = EnumRespondData.hCommand; // retain SP command handle
pMSD->dwCommandDesc = EnumRespondData.dwCommandDescriptor;
RELEASE_MSD(pMSD, "Temp Ref"); // Unlocks CommandLock
Exit: DPFX(DPFPREP,DPF_CALLIN_LVL, "Returning hr[%x], pMSD[%p]", hr, pMSD);
AssertNoCriticalSectionsFromGroupTakenByThisThread(&g_blProtocolCritSecsHeld);
return hr; } //**********************************************************************
|