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.
309 lines
10 KiB
309 lines
10 KiB
/*==========================================================================
|
|
*
|
|
* 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;
|
|
}
|
|
//**********************************************************************
|
|
|