290 lines
9.4 KiB
C++
290 lines
9.4 KiB
C++
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 2000 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
|
||
|
//**********************************************************************
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
// ------------------------------
|
||
|
// DNPEnumQuery - enum sessions
|
||
|
//
|
||
|
// Entry: Pointer to this interface
|
||
|
// Pointer to device address
|
||
|
// Pointer to host address
|
||
|
// Pointer to user data buffers
|
||
|
// Count of user data buffers
|
||
|
// Retry count
|
||
|
// Retry interval (milliseconds)
|
||
|
// Timeout (milliseconds)
|
||
|
// Command flags
|
||
|
// Pointer to user context
|
||
|
// Pointer to command handle destination
|
||
|
//
|
||
|
// Exit: Boolean inficating whether the GUID is a serial GUID
|
||
|
// ------------------------------
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DNPEnumQuery"
|
||
|
|
||
|
HRESULT DNPEnumQuery( PProtocolData pPData,
|
||
|
IDirectPlay8Address *const pHostAddress,
|
||
|
IDirectPlay8Address *const pDeviceAddress,
|
||
|
const HANDLE hSPHandle,
|
||
|
BUFFERDESC *const pBuffers,
|
||
|
const DWORD dwBufferCount,
|
||
|
const DWORD dwRetryCount,
|
||
|
const DWORD dwRetryInterval,
|
||
|
const DWORD dwTimeout,
|
||
|
const DWORD dwFlags,
|
||
|
void *const pUserContext,
|
||
|
HANDLE *const pCommandHandle )
|
||
|
{
|
||
|
PSPD pSPD;
|
||
|
PMSD pMSD;
|
||
|
SPENUMQUERYDATA EnumData;
|
||
|
HRESULT hr;
|
||
|
|
||
|
DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pPData[%p], pHostAddr[%p], pDeviceAddr[%p], hSPHandle[%x], pBuffers[%p], dwBufferCount[%x], dwRetryCount[%x], dwRetryInterval[%x], dwTimeout[%x], dwFlags[%x], pUserContext[%p], pCommandHandle[%p]", pPData, pHostAddress, pDeviceAddress, hSPHandle, pBuffers, dwBufferCount, dwRetryCount, dwRetryInterval, dwTimeout, dwFlags, pUserContext, pCommandHandle);
|
||
|
|
||
|
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 tho it
|
||
|
if((pMSD = static_cast<PMSD>( MSDPool->Get(MSDPool) )) == NULL)
|
||
|
{
|
||
|
DPFX(DPFPREP,0, "Failed to allocate MSD");
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
return DPNERR_OUTOFMEMORY; // .. isnt technically a message
|
||
|
}
|
||
|
|
||
|
pMSD->CommandID = COMMAND_ID_ENUM;
|
||
|
pMSD->pSPD = pSPD;
|
||
|
pMSD->Context = pUserContext;
|
||
|
|
||
|
EnumData.pAddressHost = pHostAddress;
|
||
|
EnumData.pAddressDeviceInfo = pDeviceAddress;
|
||
|
EnumData.pBuffers = pBuffers;
|
||
|
EnumData.dwBufferCount = dwBufferCount;
|
||
|
EnumData.dwTimeout = dwTimeout;
|
||
|
EnumData.dwRetryCount = dwRetryCount;
|
||
|
EnumData.dwRetryInterval = dwRetryInterval;
|
||
|
|
||
|
EnumData.dwFlags = 0;
|
||
|
if ( ( dwFlags & DN_ENUMQUERYFLAGS_OKTOQUERYFORADDRESSING ) != 0 )
|
||
|
{
|
||
|
EnumData.dwFlags |= DPNSPF_OKTOQUERY;
|
||
|
}
|
||
|
|
||
|
if ( ( dwFlags & DN_ENUMQUERYFLAGS_NOBROADCASTFALLBACK ) != 0 )
|
||
|
{
|
||
|
EnumData.dwFlags |= DPNSPF_NOBROADCASTFALLBACK;
|
||
|
}
|
||
|
|
||
|
if ( ( dwFlags & DN_ENUMQUERYFLAGS_ADDITIONALMULTIPLEXADAPTERS ) != 0 )
|
||
|
{
|
||
|
EnumData.dwFlags |= DPNSPF_ADDITIONALMULTIPLEXADAPTERS;
|
||
|
}
|
||
|
|
||
|
EnumData.pvContext = pMSD;
|
||
|
EnumData.hCommand = NULL;
|
||
|
|
||
|
*pCommandHandle = pMSD;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Lock(&pSPD->SPLock);
|
||
|
pMSD->blSPLinkage.InsertBefore( &pSPD->blMessageList); // Dont support timeouts for Listen
|
||
|
pMSD->ulMsgFlags1 |= MFLAGS_ONE_ON_GLOBAL_LIST;
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
#endif
|
||
|
|
||
|
pMSD->ulMsgFlags1 |= MFLAGS_ONE_IN_SERVICE_PROVIDER;
|
||
|
LOCK_MSD(pMSD, "SP Ref"); // AddRef for SP
|
||
|
LOCK_MSD(pMSD, "Temp Ref");
|
||
|
|
||
|
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);
|
||
|
|
||
|
Lock(&pMSD->CommandLock);
|
||
|
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_IN_SERVICE_PROVIDER);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Lock(&pSPD->SPLock);
|
||
|
pMSD->blSPLinkage.RemoveFromList(); // knock this off the pending list
|
||
|
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_ON_GLOBAL_LIST);
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
#endif
|
||
|
|
||
|
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
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
Lock(&pMSD->CommandLock);
|
||
|
|
||
|
pMSD->hCommand = EnumData.hCommand; // retain SP command handle
|
||
|
pMSD->dwCommandDesc = EnumData.dwCommandDescriptor;
|
||
|
|
||
|
RELEASE_MSD(pMSD, "Temp Ref"); // Unlocks CommandLock
|
||
|
|
||
|
DPFX(DPFPREP,DPF_CALLIN_LVL, "Returning DPNERR_PENDING, pMSD[%p]", pMSD);
|
||
|
return DPNERR_PENDING;
|
||
|
}
|
||
|
//**********************************************************************
|
||
|
|
||
|
|
||
|
//**********************************************************************
|
||
|
// ------------------------------
|
||
|
// DNPEnumRespond - respond to an enum query
|
||
|
//
|
||
|
// Entry: Pointer to this interface
|
||
|
// Handle of enum to respond to (pointer to SPIE_ENUMQUERY structure)
|
||
|
// Pointer data buffers to send
|
||
|
// Count of data buffers to send
|
||
|
// Flags
|
||
|
// User context for this operation
|
||
|
// Pointer to command handle destination
|
||
|
//
|
||
|
// Exit: Boolean inficating whether the GUID is a serial GUID
|
||
|
// ------------------------------
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "DNPEnumRespond"
|
||
|
|
||
|
HRESULT DNPEnumRespond( PProtocolData pPData,
|
||
|
const HANDLE hSPHandle,
|
||
|
const HANDLE hQueryHandle, // handle of enum query being responded to
|
||
|
BUFFERDESC *const pResponseBuffers,
|
||
|
const DWORD dwResponseBufferCount,
|
||
|
const DWORD dwFlags,
|
||
|
void *const pUserContext,
|
||
|
HANDLE *const pCommandHandle )
|
||
|
{
|
||
|
PSPD pSPD;
|
||
|
PMSD pMSD;
|
||
|
SPENUMRESPONDDATA EnumRespondData;
|
||
|
HRESULT hr;
|
||
|
|
||
|
DPFX(DPFPREP,DPF_CALLIN_LVL, "Parameters: pPData[%p], hSPHandle[%x], hQueryHandle[%x], pResponseBuffers[%p], dwResponseBufferCount[%x], dwFlags[%x], pUserContext[%p], pCommandHandle[%p]", pPData, hSPHandle, hQueryHandle, pResponseBuffers, dwResponseBufferCount, dwFlags, pUserContext, pCommandHandle);
|
||
|
EnumRespondData.pQuery = static_cast<SPIE_QUERY*>( hQueryHandle );
|
||
|
DNASSERT( EnumRespondData.pQuery != NULL );
|
||
|
|
||
|
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 tho it
|
||
|
if((pMSD = static_cast<PMSD>( MSDPool->Get(MSDPool) )) == NULL)
|
||
|
{
|
||
|
DPFX(DPFPREP,0, "Failed to allocate MSD");
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
return DPNERR_OUTOFMEMORY; // .. isnt technically a message
|
||
|
}
|
||
|
|
||
|
pMSD->CommandID = COMMAND_ID_ENUMRESP;
|
||
|
pMSD->pSPD = pSPD;
|
||
|
pMSD->Context = pUserContext;
|
||
|
|
||
|
EnumRespondData.pBuffers = pResponseBuffers;
|
||
|
EnumRespondData.dwBufferCount = dwResponseBufferCount;
|
||
|
EnumRespondData.dwFlags = dwFlags;
|
||
|
EnumRespondData.pvContext = pMSD;
|
||
|
EnumRespondData.hCommand = NULL;
|
||
|
|
||
|
*pCommandHandle = pMSD;
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Lock(&pSPD->SPLock);
|
||
|
pMSD->blSPLinkage.InsertBefore( &pSPD->blMessageList);
|
||
|
pMSD->ulMsgFlags1 |= MFLAGS_ONE_ON_GLOBAL_LIST;
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
#endif
|
||
|
|
||
|
pMSD->ulMsgFlags1 |= MFLAGS_ONE_IN_SERVICE_PROVIDER;
|
||
|
LOCK_MSD(pMSD, "SP Ref"); // AddRef for SP
|
||
|
LOCK_MSD(pMSD, "Temp Ref");
|
||
|
|
||
|
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);
|
||
|
|
||
|
Lock(&pMSD->CommandLock);
|
||
|
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_IN_SERVICE_PROVIDER);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
Lock(&pSPD->SPLock);
|
||
|
pMSD->blSPLinkage.RemoveFromList(); // knock this off the pending list
|
||
|
pMSD->ulMsgFlags1 &= ~(MFLAGS_ONE_ON_GLOBAL_LIST);
|
||
|
Unlock(&pSPD->SPLock);
|
||
|
#endif
|
||
|
|
||
|
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
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
Lock(&pMSD->CommandLock);
|
||
|
|
||
|
pMSD->hCommand = EnumRespondData.hCommand; // retain SP command handle
|
||
|
pMSD->dwCommandDesc = EnumRespondData.dwCommandDescriptor;
|
||
|
|
||
|
RELEASE_MSD(pMSD, "Temp Ref"); // Unlocks CommandLock
|
||
|
|
||
|
DPFX(DPFPREP,DPF_CALLIN_LVL, "Returning DPNERR_PENDING, pMSD[%p]", pMSD);
|
||
|
return DPNERR_PENDING;
|
||
|
}
|
||
|
//**********************************************************************
|
||
|
|