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.
 
 
 
 
 
 

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