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