|
|
/***************************************************************************
* * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved. * * File: spcallbackobj.cpp * * Content: DP8SIM callback interface object class. * * History: * Date By Reason * ======== ======== ========= * 04/23/01 VanceO Created. * ***************************************************************************/
#include "dp8simi.h"
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::CDP8SimCB"
//=============================================================================
// CDP8SimCB constructor
//-----------------------------------------------------------------------------
//
// Description: Initializes the new CDP8SimCB object.
//
// Arguments:
// CDP8SimSP * pOwningDP8SimSP - Pointer to owning CDP8SimSP object.
// IDP8SPCallback * pDP8SPCB - Pointer to real DPlay callback interface
// being intercepted.
//
// Returns: None (the object).
//=============================================================================
CDP8SimCB::CDP8SimCB(CDP8SimSP * pOwningDP8SimSP, IDP8SPCallback * pDP8SPCB) { this->m_Sig[0] = 'S'; this->m_Sig[1] = 'P'; this->m_Sig[2] = 'C'; this->m_Sig[3] = 'B';
this->m_lRefCount = 1; // someone must have a pointer to this object
pOwningDP8SimSP->AddRef(); this->m_pOwningDP8SimSP = pOwningDP8SimSP;
pDP8SPCB->AddRef(); this->m_pDP8SPCB = pDP8SPCB; } // CDP8SimCB::CDP8SimCB
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::~CDP8SimCB"
//=============================================================================
// CDP8SimCB destructor
//-----------------------------------------------------------------------------
//
// Description: Frees the CDP8SimCB object.
//
// Arguments: None.
//
// Returns: None.
//=============================================================================
CDP8SimCB::~CDP8SimCB(void) { DNASSERT(this->m_lRefCount == 0);
this->m_pOwningDP8SimSP->Release(); this->m_pOwningDP8SimSP = NULL;
this->m_pDP8SPCB->Release(); this->m_pDP8SPCB = NULL;
//
// For grins, change the signature before deleting the object.
//
this->m_Sig[3] = 'b'; } // CDP8SimCB::~CDP8SimCB
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::QueryInterface"
//=============================================================================
// CDP8SimCB::QueryInterface
//-----------------------------------------------------------------------------
//
// Description: Retrieves a new reference for an interfaces supported by this
// CDP8SimCB object.
//
// Arguments:
// REFIID riid - Reference to interface ID GUID.
// LPVOID * ppvObj - Place to store pointer to object.
//
// Returns: HRESULT
// S_OK - Returning a valid interface pointer.
// DPNHERR_INVALIDOBJECT - The interface object is invalid.
// DPNHERR_INVALIDPOINTER - The destination pointer is invalid.
// E_NOINTERFACE - Invalid interface was specified.
//=============================================================================
STDMETHODIMP CDP8SimCB::QueryInterface(REFIID riid, LPVOID * ppvObj) { HRESULT hr = DPN_OK;
DPFX(DPFPREP, 3, "(0x%p) Parameters: (REFIID, 0x%p)", this, ppvObj);
//
// Validate the object.
//
if (! this->IsValidObject()) { DPFX(DPFPREP, 0, "Invalid DP8Sim object!"); hr = DPNERR_INVALIDOBJECT; goto Failure; }
//
// Validate the parameters.
//
if ((! IsEqualIID(riid, IID_IUnknown)) && (! IsEqualIID(riid, IID_IDP8SPCallback))) { DPFX(DPFPREP, 0, "Unsupported interface!"); hr = E_NOINTERFACE; goto Failure; }
if ((ppvObj == NULL) || (IsBadWritePtr(ppvObj, sizeof(void*)))) { DPFX(DPFPREP, 0, "Invalid interface pointer specified!"); hr = DPNERR_INVALIDPOINTER; goto Failure; }
//
// Add a reference, and return the interface pointer (which is actually
// just the object pointer, they line up because CDP8SimCB inherits from
// the interface declaration).
//
this->AddRef(); (*ppvObj) = this;
Exit:
DPFX(DPFPREP, 3, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
goto Exit; } // CDP8SimCB::QueryInterface
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::AddRef"
//=============================================================================
// CDP8SimCB::AddRef
//-----------------------------------------------------------------------------
//
// Description: Adds a reference to this CDP8SimCB object.
//
// Arguments: None.
//
// Returns: New refcount.
//=============================================================================
STDMETHODIMP_(ULONG) CDP8SimCB::AddRef(void) { LONG lRefCount;
DNASSERT(this->IsValidObject());
//
// There must be at least 1 reference to this object, since someone is
// calling AddRef.
//
DNASSERT(this->m_lRefCount > 0);
lRefCount = InterlockedIncrement(&this->m_lRefCount);
DPFX(DPFPREP, 3, "[0x%p] RefCount [0x%lx]", this, lRefCount);
return lRefCount; } // CDP8SimCB::AddRef
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::Release"
//=============================================================================
// CDP8SimCB::Release
//-----------------------------------------------------------------------------
//
// Description: Removes a reference to this CDP8SimCB object. When the
// refcount reaches 0, this object is destroyed.
// You must NULL out your pointer to this object after calling
// this function.
//
// Arguments: None.
//
// Returns: New refcount.
//=============================================================================
STDMETHODIMP_(ULONG) CDP8SimCB::Release(void) { LONG lRefCount;
DNASSERT(this->IsValidObject());
//
// There must be at least 1 reference to this object, since someone is
// calling Release.
//
DNASSERT(this->m_lRefCount > 0);
lRefCount = InterlockedDecrement(&this->m_lRefCount);
//
// Was that the last reference? If so, we're going to destroy this object.
//
if (lRefCount == 0) { DPFX(DPFPREP, 3, "[0x%p] RefCount hit 0, destroying object.", this);
//
// Uninitialize the object.
//
this->UninitializeObject();
//
// Finally delete this (!) object.
//
delete this; } else { DPFX(DPFPREP, 3, "[0x%p] RefCount [0x%lx]", this, lRefCount); }
return lRefCount; } // CDP8SimCB::Release
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::IndicateEvent"
//=============================================================================
// CDP8SimCB::IndicateEvent
//-----------------------------------------------------------------------------
//
// Description: ?
//
// Arguments:
// SP_EVENT_TYPE EventType - Event being indicated.
// PVOID pvMessage - Event specific message.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimCB::IndicateEvent(SP_EVENT_TYPE EventType, PVOID pvMessage) { HRESULT hr; CDP8SimEndpoint * pDP8SimEndpoint; CDP8SimCommand * pDP8SimCommand;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (%u, 0x%p)", this, EventType, pvMessage);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Switch on the type of event being indicated.
//
switch (EventType) { case SPEV_DATA: { SPIE_DATA * pData; DP8SIM_PARAMETERS dp8sp; SPIE_DATA DataModified; CDP8SimReceive * pDP8SimReceive; DWORD dwBandwidthDelay; DWORD dwLatencyDelay;
pData = (SPIE_DATA*) pvMessage;
DNASSERT(pData->pReceivedData->pNext == NULL);
pDP8SimEndpoint = (CDP8SimEndpoint*) pData->pEndpointContext; DNASSERT(pDP8SimEndpoint->IsValidObject());
//
// If the endpoint is disconnecting, drop the receive.
//
pDP8SimEndpoint->Lock(); if (pDP8SimEndpoint->IsDisconnecting()) { pDP8SimEndpoint->Unlock();
DPFX(DPFPREP, 1, "Endpoint 0x%p is disconnecting, dropping receive.", pDP8SimEndpoint);
hr = DPN_OK; } else { pDP8SimEndpoint->Unlock();
//
// Get the current receive settings.
//
ZeroMemory(&dp8sp, sizeof(dp8sp)); dp8sp.dwSize = sizeof(dp8sp); this->m_pOwningDP8SimSP->GetAllReceiveParameters(&dp8sp);
//
// Determine if we need to drop this receive.
//
if (this->m_pOwningDP8SimSP->ShouldDrop(dp8sp.fPacketLossPercent)) { DPFX(DPFPREP, 2, "Dropping %u bytes of data from endpoint 0x%p.", pData->pReceivedData->BufferDesc.dwBufferSize, pDP8SimEndpoint);
//
// Update the statistics.
//
this->m_pOwningDP8SimSP->IncrementStatsReceiveDropped(pData->pReceivedData->BufferDesc.dwBufferSize);
//
// Let the SP reclaim the buffer.
//
hr = DPN_OK; } else { //
// Figure out how much latency needs to be added based on
// the bandwidth and random latency settings.
//
// If we're not supposed to delay the receives, indicate it
// now. Otherwise submit a timed job to be performed
// later.
//
if (! this->m_pOwningDP8SimSP->GetDelay(dp8sp.dwBandwidthBPS, dp8sp.dwPacketHeaderSize, pData->pReceivedData->BufferDesc.dwBufferSize, dp8sp.dwMinLatencyMS, dp8sp.dwMaxLatencyMS, &dwBandwidthDelay, &dwLatencyDelay)) { //
// Modify the message before indicating to the caller.
//
ZeroMemory(&DataModified, sizeof(DataModified)); DataModified.hEndpoint = (HANDLE) pDP8SimEndpoint; DataModified.pEndpointContext = pDP8SimEndpoint->GetUserContext(); DataModified.pReceivedData = pData->pReceivedData;
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating event SPEV_DATA (message = 0x%p, data size = %u) to interface 0x%p.", pData, pData->pReceivedData->BufferDesc.dwBufferSize, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_DATA, &DataModified);
DPFX(DPFPREP, 2, "Returning from event SPEV_DATA [0x%lx].", hr);
//
// Update the statistics.
//
this->m_pOwningDP8SimSP->IncrementStatsReceiveTransmitted(pData->pReceivedData->BufferDesc.dwBufferSize, 0); } else { DPFX(DPFPREP, 6, "Delaying %u byte receive for %u + %u ms.", pData->pReceivedData->BufferDesc.dwBufferSize, dwBandwidthDelay, dwLatencyDelay);
//
// Get a receive object, duplicating the received data
// structure given to us by our caller for indication
// some time in the future.
//
pDP8SimReceive = (CDP8SimReceive*)g_FPOOLReceive.Get(pData); if (pDP8SimReceive == NULL) { hr = DPNERR_OUTOFMEMORY; } else { DPFX(DPFPREP, 7, "New delayed receive 0x%p.", pDP8SimReceive);
//
// Store the latency that is about be added to this
// receive.
//
pDP8SimReceive->SetLatencyAdded(dwBandwidthDelay + dwLatencyDelay);
//
// Transfer local pDP8SimReceive reference to the
// job queue.
//
//
// Increment the receive counter.
//
this->m_pOwningDP8SimSP->IncReceivesPending();
//
// Queue it to be indicated at a later time,
// depending on the latency value requested. If
// there's a bandwidth restriction, enforce the
// receiving order as well so that earlier messages
// that are still pending hold up later ones.
//
hr = AddWorkerJob(DP8SIMJOBTYPE_DELAYEDRECEIVE, pDP8SimReceive, this->m_pOwningDP8SimSP, dwBandwidthDelay, dwLatencyDelay, DP8SIMJOBFLAG_PERFORMBLOCKINGPHASELAST); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't add delayed receive worker job (0x%p)!", pDP8SimReceive);
//
// Remove the receive counter.
//
this->m_pOwningDP8SimSP->DecReceivesPending();
//
// Release the delayed receive reference.
//
DPFX(DPFPREP, 7, "Releasing aborted delayed receive 0x%p.", pDP8SimReceive); pDP8SimReceive->Release(); pDP8SimReceive = NULL; } else { //
// Let the real SP know that we're keeping the
// buffer.
//
hr = DPNSUCCESS_PENDING; } } // end else (successfully got receive object)
} // end else (delaying receives)
} // end else (not dropping receive)
} // end else (endpoint is not disconnecting yet)
break; }
case SPEV_CONNECT: { SPIE_CONNECT * pConnect; SPIE_CONNECT ConnectModified;
pConnect = (SPIE_CONNECT*) pvMessage;
pDP8SimCommand = (CDP8SimCommand*) pConnect->pCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT((pDP8SimCommand->GetType() == CMDTYPE_CONNECT) || (pDP8SimCommand->GetType() == CMDTYPE_LISTEN));
//
// Get a new endpoint object from the pool.
//
pDP8SimEndpoint = (CDP8SimEndpoint*)g_FPOOLEndpoint.Get(pConnect->hEndpoint); if (pDP8SimEndpoint == NULL) { hr = DPNERR_OUTOFMEMORY; } else { DPFX(DPFPREP, 7, "New %s endpoint 0x%p.", ((pDP8SimCommand->GetType() == CMDTYPE_CONNECT) ? _T("outbound") : _T("inbound")), pDP8SimEndpoint);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&ConnectModified, sizeof(ConnectModified)); ConnectModified.hEndpoint = (HANDLE) pDP8SimEndpoint; //ConnectModified.pEndpointContext = NULL; // the user fills this in
ConnectModified.pCommandContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating event SPEV_CONNECT (message = 0x%p) to interface 0x%p.", &ConnectModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_CONNECT, &ConnectModified);
DPFX(DPFPREP, 2, "Returning from event SPEV_CONNECT [0x%lx].", hr);
if (hr == DPN_OK) { //
// Update the endpoint context with what the user returned.
//
pDP8SimEndpoint->SetUserContext(ConnectModified.pEndpointContext);
//
// Return our endpoint context.
//
pConnect->pEndpointContext = pDP8SimEndpoint; } else { //
// Release the endpoint reference.
//
DPFX(DPFPREP, 7, "Releasing aborted endpoint 0x%p.", pDP8SimEndpoint); pDP8SimEndpoint->Release(); pDP8SimEndpoint = NULL; } }
break; }
case SPEV_DISCONNECT: { SPIE_DISCONNECT * pDisconnect; SPIE_DISCONNECT DisconnectModified;
pDisconnect = (SPIE_DISCONNECT*) pvMessage;
pDP8SimEndpoint = (CDP8SimEndpoint*) pDisconnect->pEndpointContext; DNASSERT(pDP8SimEndpoint->IsValidObject());
//
// Mark the endpoint as disconnecting to prevent additional sends
// or receives.
//
pDP8SimEndpoint->Lock(); pDP8SimEndpoint->NoteDisconnecting(); pDP8SimEndpoint->Unlock();
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&DisconnectModified, sizeof(DisconnectModified)); DisconnectModified.hEndpoint = (HANDLE) pDP8SimEndpoint; DisconnectModified.pEndpointContext = pDP8SimEndpoint->GetUserContext();
//
// Quickly indicate any delayed receives from this endpoint that
// are still pending.
//
FlushAllDelayedReceivesFromEndpoint(pDP8SimEndpoint, FALSE);
//
// Kill off any delayed sends that would have gone to this
// endpoint.
//
FlushAllDelayedSendsToEndpoint(pDP8SimEndpoint, TRUE);
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating event SPEV_DISCONNECT (message = 0x%p) to interface 0x%p.", &DisconnectModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_DISCONNECT, &DisconnectModified);
DPFX(DPFPREP, 2, "Returning from event SPEV_DISCONNECT [0x%lx].", hr);
//
// Release the endpoint reference.
//
DPFX(DPFPREP, 7, "Releasing endpoint 0x%p.", pDP8SimEndpoint); pDP8SimEndpoint->Release(); pDP8SimEndpoint = NULL;
break; }
case SPEV_LISTENSTATUS: { SPIE_LISTENSTATUS * pListenStatus; SPIE_LISTENSTATUS ListenStatusModified;
pListenStatus = (SPIE_LISTENSTATUS*) pvMessage;
pDP8SimCommand = (CDP8SimCommand*) pListenStatus->pUserContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_LISTEN);
//
// Get a new endpoint object from the pool.
//
pDP8SimEndpoint = (CDP8SimEndpoint*)g_FPOOLEndpoint.Get(pListenStatus->hEndpoint); if (pDP8SimEndpoint == NULL) { hr = DPNERR_OUTOFMEMORY; } else { DPFX(DPFPREP, 7, "New listen endpoint 0x%p, adding reference for listen command.", pDP8SimEndpoint);
//
// Store an endpoint reference with the command.
//
pDP8SimEndpoint->AddRef(); pDP8SimCommand->SetListenEndpoint(pDP8SimEndpoint);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&ListenStatusModified, sizeof(ListenStatusModified)); ListenStatusModified.ListenAdapter = pListenStatus->ListenAdapter; ListenStatusModified.hResult = pListenStatus->hResult; ListenStatusModified.hCommand = (HANDLE) pDP8SimCommand; ListenStatusModified.pUserContext = pDP8SimCommand->GetUserContext(); ListenStatusModified.hEndpoint = (HANDLE) pDP8SimEndpoint;
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating event SPEV_LISTENSTATUS (message = 0x%p) to interface 0x%p.", &ListenStatusModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_LISTENSTATUS, &ListenStatusModified);
DPFX(DPFPREP, 2, "Returning from event SPEV_LISTENSTATUS [0x%lx].", hr);
//
// Release the reference we got from new, since we only needed
// it while we indicated the endpoint up to the user. The
// listen command object has the reference it needs.
//
DPFX(DPFPREP, 7, "Releasing local listen endpoint 0x%p reference.", pDP8SimEndpoint); pDP8SimEndpoint->Release(); pDP8SimEndpoint = NULL; }
break; }
case SPEV_ENUMQUERY: { SPIE_QUERY * pQuery; ENUMQUERYDATAWRAPPER QueryWrapper;
pQuery = (SPIE_QUERY*) pvMessage;
DNASSERT(pQuery->pAddressSender != NULL); DNASSERT(pQuery->pAddressDevice != NULL);
pDP8SimCommand = (CDP8SimCommand*) pQuery->pUserContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_LISTEN);
//
// Modify the message before indicating to the caller. We need a
// wrapper so that ProxyEnumQuery can parse back out the original
// query data pointer.
//
ZeroMemory(&QueryWrapper, sizeof(QueryWrapper)); QueryWrapper.m_Sig[0] = 'E'; QueryWrapper.m_Sig[1] = 'Q'; QueryWrapper.m_Sig[2] = 'E'; QueryWrapper.m_Sig[3] = 'W';
QueryWrapper.pOriginalQuery = pQuery;
hr = pQuery->pAddressSender->Duplicate(&QueryWrapper.QueryForUser.pAddressSender); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate enum query sender's address!"); } else { hr = QueryWrapper.QueryForUser.pAddressSender->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change enum query sender's address' SP!"); } else { hr = pQuery->pAddressDevice->Duplicate(&QueryWrapper.QueryForUser.pAddressDevice); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate enum query device address!"); } else { hr = QueryWrapper.QueryForUser.pAddressDevice->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change enum query device address' SP!"); } else { QueryWrapper.QueryForUser.pReceivedData = pQuery->pReceivedData; QueryWrapper.QueryForUser.pUserContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_ENUMQUERY (message = 0x%p) to interface 0x%p.", &QueryWrapper.QueryForUser, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_ENUMQUERY, &QueryWrapper.QueryForUser);
DPFX(DPFPREP, 2, "Returning from SPEV_ENUMQUERY [0x%lx].", hr); }
QueryWrapper.QueryForUser.pAddressDevice->Release(); QueryWrapper.QueryForUser.pAddressDevice = NULL; } }
QueryWrapper.QueryForUser.pAddressSender->Release(); QueryWrapper.QueryForUser.pAddressSender = NULL; } break; }
case SPEV_QUERYRESPONSE: { SPIE_QUERYRESPONSE * pQueryResponse; SPIE_QUERYRESPONSE QueryResponseModified;
pQueryResponse = (SPIE_QUERYRESPONSE*) pvMessage;
DNASSERT(pQueryResponse->pAddressSender != NULL); DNASSERT(pQueryResponse->pAddressDevice != NULL);
pDP8SimCommand = (CDP8SimCommand*) pQueryResponse->pUserContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_ENUMQUERY);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&QueryResponseModified, sizeof(QueryResponseModified));
hr = pQueryResponse->pAddressSender->Duplicate(&QueryResponseModified.pAddressSender); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate query response sender's address!"); } else { hr = QueryResponseModified.pAddressSender->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change query response sender's address' SP!"); } else { hr = pQueryResponse->pAddressDevice->Duplicate(&QueryResponseModified.pAddressDevice); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate query response device address!"); } else { hr = QueryResponseModified.pAddressDevice->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change query response device address' SP!"); } else { QueryResponseModified.pReceivedData = pQueryResponse->pReceivedData; QueryResponseModified.dwRoundTripTime = pQueryResponse->dwRoundTripTime; QueryResponseModified.pUserContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_QUERYRESPONSE (message = 0x%p) to interface 0x%p.", &QueryResponseModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_QUERYRESPONSE, &QueryResponseModified);
DPFX(DPFPREP, 2, "Returning from SPEV_QUERYRESPONSE [0x%lx].", hr); }
QueryResponseModified.pAddressDevice->Release(); QueryResponseModified.pAddressDevice = NULL; } }
QueryResponseModified.pAddressSender->Release(); QueryResponseModified.pAddressSender = NULL; } break; }
case SPEV_LISTENADDRESSINFO: { SPIE_LISTENADDRESSINFO * pListenAddressInfo; SPIE_LISTENADDRESSINFO ListenAddressInfoModified;
pListenAddressInfo = (SPIE_LISTENADDRESSINFO*) pvMessage;
DNASSERT(pListenAddressInfo->pDeviceAddress != NULL);
pDP8SimCommand = (CDP8SimCommand*) pListenAddressInfo->pCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_LISTEN);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&ListenAddressInfoModified, sizeof(ListenAddressInfoModified));
hr = pListenAddressInfo->pDeviceAddress->Duplicate(&ListenAddressInfoModified.pDeviceAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate listen address info device address!"); } else { hr = ListenAddressInfoModified.pDeviceAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change listen address info device address' SP!"); } else { ListenAddressInfoModified.hCommandStatus = pListenAddressInfo->hCommandStatus; ListenAddressInfoModified.pCommandContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_LISTENADDRESSINFO (message = 0x%p) to interface 0x%p.", &ListenAddressInfoModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_LISTENADDRESSINFO, &ListenAddressInfoModified);
DPFX(DPFPREP, 2, "Returning from SPEV_LISTENADDRESSINFO [0x%lx].", hr); }
ListenAddressInfoModified.pDeviceAddress->Release(); ListenAddressInfoModified.pDeviceAddress = NULL; } break; }
case SPEV_ENUMADDRESSINFO: { SPIE_ENUMADDRESSINFO * pEnumAddressInfo; SPIE_ENUMADDRESSINFO EnumAddressInfoModified;
pEnumAddressInfo = (SPIE_ENUMADDRESSINFO*) pvMessage;
DNASSERT(pEnumAddressInfo->pHostAddress != NULL); DNASSERT(pEnumAddressInfo->pDeviceAddress != NULL);
pDP8SimCommand = (CDP8SimCommand*) pEnumAddressInfo->pCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_ENUMQUERY);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&EnumAddressInfoModified, sizeof(EnumAddressInfoModified));
hr = pEnumAddressInfo->pHostAddress->Duplicate(&EnumAddressInfoModified.pHostAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate enum address info host's address!"); } else { hr = EnumAddressInfoModified.pHostAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change enum address info host's address' SP!"); } else { hr = pEnumAddressInfo->pDeviceAddress->Duplicate(&EnumAddressInfoModified.pDeviceAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate enum address info device address!"); } else { hr = EnumAddressInfoModified.pDeviceAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change enum address info device address' SP!"); } else { EnumAddressInfoModified.hCommandStatus = pEnumAddressInfo->hCommandStatus; EnumAddressInfoModified.pCommandContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_ENUMADDRESSINFO (message = 0x%p) to interface 0x%p.", &EnumAddressInfoModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_ENUMADDRESSINFO, &EnumAddressInfoModified);
DPFX(DPFPREP, 2, "Returning from SPEV_ENUMADDRESSINFO [0x%lx].", hr); }
EnumAddressInfoModified.pDeviceAddress->Release(); EnumAddressInfoModified.pDeviceAddress = NULL; } }
EnumAddressInfoModified.pHostAddress->Release(); EnumAddressInfoModified.pHostAddress = NULL; } break; }
case SPEV_CONNECTADDRESSINFO: { SPIE_CONNECTADDRESSINFO * pConnectAddressInfo; SPIE_CONNECTADDRESSINFO ConnectAddressInfoModified;
pConnectAddressInfo = (SPIE_CONNECTADDRESSINFO*) pvMessage;
DNASSERT(pConnectAddressInfo->pHostAddress != NULL); DNASSERT(pConnectAddressInfo->pDeviceAddress != NULL);
pDP8SimCommand = (CDP8SimCommand*) pConnectAddressInfo->pCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_CONNECT);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&ConnectAddressInfoModified, sizeof(ConnectAddressInfoModified));
hr = pConnectAddressInfo->pHostAddress->Duplicate(&ConnectAddressInfoModified.pHostAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate connect address info host's address!"); } else { hr = ConnectAddressInfoModified.pHostAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change connect address info host's address' SP!"); } else { hr = pConnectAddressInfo->pDeviceAddress->Duplicate(&ConnectAddressInfoModified.pDeviceAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate connect address info device address!"); } else { hr = ConnectAddressInfoModified.pDeviceAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change connect address info device address' SP!"); } else { ConnectAddressInfoModified.hCommandStatus = pConnectAddressInfo->hCommandStatus; ConnectAddressInfoModified.pCommandContext = pDP8SimCommand->GetUserContext();
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_CONNECTADDRESSINFO (message = 0x%p) to interface 0x%p.", &ConnectAddressInfoModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_CONNECTADDRESSINFO, &ConnectAddressInfoModified);
DPFX(DPFPREP, 2, "Returning from SPEV_CONNECTADDRESSINFO [0x%lx].", hr); }
ConnectAddressInfoModified.pDeviceAddress->Release(); ConnectAddressInfoModified.pDeviceAddress = NULL; } }
ConnectAddressInfoModified.pHostAddress->Release(); ConnectAddressInfoModified.pHostAddress = NULL; } break; }
case SPEV_DATA_UNCONNECTED: { SPIE_DATA_UNCONNECTED * pDataUnconnected; SPIE_DATA_UNCONNECTED DataUnconnectedModified;
pDataUnconnected = (SPIE_DATA_UNCONNECTED*) pvMessage; DNASSERT(pDataUnconnected->pvReplyBuffer != NULL); DNASSERT(pDataUnconnected->dwReplyBufferSize > 0);
pDP8SimCommand = (CDP8SimCommand*) pDataUnconnected->pvListenCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_LISTEN);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&DataUnconnectedModified, sizeof(DataUnconnectedModified)); DataUnconnectedModified.pvListenCommandContext = pDP8SimCommand->GetUserContext(); DataUnconnectedModified.pReceivedData = pDataUnconnected->pReceivedData; DataUnconnectedModified.dwSenderAddressHash = pDataUnconnected->dwSenderAddressHash; DataUnconnectedModified.pvReplyBuffer = pDataUnconnected->pvReplyBuffer; DataUnconnectedModified.dwReplyBufferSize = pDataUnconnected->dwReplyBufferSize;
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating event SPEV_DATA_UNCONNECTED (message = 0x%p) to interface 0x%p.", &DataUnconnectedModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_DATA_UNCONNECTED, &DataUnconnectedModified);
DPFX(DPFPREP, 2, "Returning from event SPEV_DATA_UNCONNECTED [0x%lx].", hr);
if (hr == DPNSUCCESS_PENDING) { //
// Update the reply buffer size with what the user returned.
//
DNASSERT(DataUnconnectedModified.dwReplyBufferSize > 0); DNASSERT(DataUnconnectedModified.dwReplyBufferSize <= pDataUnconnected->dwReplyBufferSize); pDataUnconnected->dwReplyBufferSize = DataUnconnectedModified.dwReplyBufferSize; }
break; }
#ifndef DPNBUILD_NOMULTICAST
case SPEV_DATA_UNKNOWNSENDER: { SPIE_DATA_UNKNOWNSENDER * pDataUnknownSender; SPIE_DATA_UNKNOWNSENDER DataUnknownSenderModified;
pDataUnknownSender = (SPIE_DATA_UNKNOWNSENDER*) pvMessage;
DNASSERT(pDataUnknownSender->pSenderAddress != NULL);
pDP8SimCommand = (CDP8SimCommand*) pDataUnknownSender->pvListenCommandContext; DNASSERT(pDP8SimCommand->IsValidObject()); DNASSERT(pDP8SimCommand->GetType() == CMDTYPE_LISTEN);
//
// Modify the message before indicating to the caller.
//
ZeroMemory(&DataUnknownSenderModified, sizeof(DataUnknownSenderModified));
hr = pDataUnknownSender->pSenderAddress->Duplicate(&DataUnknownSenderModified.pSenderAddress); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't duplicate listen address info device address!"); } else { hr = DataUnknownSenderModified.pSenderAddress->SetSP(this->m_pOwningDP8SimSP->GetFakeSP()); if (hr != DPN_OK) { DPFX(DPFPREP, 0, "Couldn't change listen address info device address' SP!"); } else { DataUnknownSenderModified.pvListenCommandContext = pDP8SimCommand->GetUserContext(); DataUnknownSenderModified.pReceivedData = pDataUnknownSender->pReceivedData;
//
// Indicate the event to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating SPEV_DATA_UNKNOWNSENDER (message = 0x%p) to interface 0x%p.", &DataUnknownSenderModified, this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->IndicateEvent(SPEV_DATA_UNKNOWNSENDER, &DataUnknownSenderModified);
DPFX(DPFPREP, 2, "Returning from SPEV_DATA_UNKNOWNSENDER [0x%lx].", hr); }
DataUnknownSenderModified.pSenderAddress->Release(); DataUnknownSenderModified.pSenderAddress = NULL; } break; } #endif // ! DPNBUILD_NOMULTICAST
default: { DPFX(DPFPREP, 0, "Unrecognized event type %u!", EventType); DNASSERT(FALSE); hr = E_NOTIMPL; break; } }
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr; } // CDP8SimCB::IndicateEvent
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::CommandComplete"
//=============================================================================
// CDP8SimCB::CommandComplete
//-----------------------------------------------------------------------------
//
// Description: ?
//
// Arguments:
// HANDLE hCommand - Handle of command that's completing.
// HRESULT hrResult - Result code for completing operation.
// PVOID pvContext - Pointer to user context for command.
//
// Returns: HRESULT
//=============================================================================
STDMETHODIMP CDP8SimCB::CommandComplete(HANDLE hCommand, HRESULT hrResult, PVOID pvContext) { HRESULT hr; CDP8SimCommand * pDP8SimCommand = (CDP8SimCommand*) pvContext;
DPFX(DPFPREP, 2, "(0x%p) Parameters: (0x%p, 0x%lx, 0x%p)", this, hCommand, hrResult, pvContext);
//
// Validate (actually assert) the object.
//
DNASSERT(this->IsValidObject());
//
// Assert the parameters.
//
DNASSERT(pDP8SimCommand->IsValidObject());
//
// Switch on the command type.
//
switch (pDP8SimCommand->GetType()) { case CMDTYPE_SENDDATA_IMMEDIATE: { //
// Update the statistics.
//
if (hrResult == DPN_OK) { this->m_pOwningDP8SimSP->IncrementStatsSendTransmitted(pDP8SimCommand->GetMessageSize(), 0); } else { //
// The send failed. Currently we don't track this.
//
} pDP8SimCommand->SetMessageSize(0);
//
// Indicate the completion to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating immediate send command 0x%p complete (result = 0x%lx, context = 0x%p) to interface 0x%p.", pDP8SimCommand, hrResult, pDP8SimCommand->GetUserContext(), this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->CommandComplete(pDP8SimCommand, hrResult, pDP8SimCommand->GetUserContext());
DPFX(DPFPREP, 2, "Returning from command complete [0x%lx].", hr);
//
// Remove the send counter.
//
this->m_pOwningDP8SimSP->DecSendsPending();
break; }
case CMDTYPE_SENDDATA_DELAYED: { CDP8SimSend * pDP8SimSend;
//
// Handle the completion. It never gets indicated to the user
// though.
//
pDP8SimSend = (CDP8SimSend*) pDP8SimCommand->GetUserContext(); DNASSERT(pDP8SimSend->IsValidObject());
DPFX(DPFPREP, 5, "Send 0x%p (command 0x%p) completed.", pDP8SimSend, pDP8SimCommand);
//
// Update the statistics.
//
if (hrResult == DPN_OK) { this->m_pOwningDP8SimSP->IncrementStatsSendTransmitted(pDP8SimSend->GetMessageSize(), pDP8SimSend->GetLatencyAdded()); } else { //
// The send failed. We don't truly track this, but since we
// already indicated a successful send to the user, we'll count
// it as a drop.
//
this->m_pOwningDP8SimSP->IncrementStatsSendDropped(pDP8SimSend->GetMessageSize()); }
//
// Remove the send counter.
//
this->m_pOwningDP8SimSP->DecSendsPending();
pDP8SimSend->Release(); pDP8SimSend = NULL;
hr = DPN_OK;
break; }
case CMDTYPE_CONNECT: case CMDTYPE_DISCONNECT: case CMDTYPE_LISTEN: case CMDTYPE_ENUMQUERY: case CMDTYPE_ENUMRESPOND: { //
// Indicate the completion to the real callback interface.
//
DPFX(DPFPREP, 2, "Indicating command 0x%p complete (type = %u, result = 0x%lx, context = 0x%p) to interface 0x%p.", pDP8SimCommand, pDP8SimCommand->GetType(), hrResult, pDP8SimCommand->GetUserContext(), this->m_pDP8SPCB);
hr = this->m_pDP8SPCB->CommandComplete(pDP8SimCommand, hrResult, pDP8SimCommand->GetUserContext());
DPFX(DPFPREP, 2, "Returning from command complete [0x%lx].", hr);
//
// If this was a listen, we need to kill the listen endpoint.
//
if (pDP8SimCommand->GetType() == CMDTYPE_LISTEN) { CDP8SimEndpoint * pDP8SimEndpoint;
pDP8SimEndpoint = pDP8SimCommand->GetListenEndpoint(); DNASSERT(pDP8SimEndpoint != NULL);
pDP8SimCommand->SetListenEndpoint(NULL);
DPFX(DPFPREP, 7, "Releasing listen endpoint 0x%p.", pDP8SimEndpoint);
pDP8SimEndpoint->Release(); pDP8SimEndpoint = NULL; } break; } default: { DPFX(DPFPREP, 0, "Unrecognized command type %u!", pDP8SimCommand->GetType()); DNASSERT(FALSE); hr = E_NOTIMPL; break; } }
//
// Destroy the object.
//
DPFX(DPFPREP, 7, "Releasing completed command 0x%p.", pDP8SimCommand); pDP8SimCommand->Release(); pDP8SimCommand = NULL;
DPFX(DPFPREP, 2, "(0x%p) Returning: [0x%lx]", this, hr);
return hr; } // CDP8SimCB::CommandComplete
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::InitializeObject"
//=============================================================================
// CDP8SimCB::InitializeObject
//-----------------------------------------------------------------------------
//
// Description: Sets up the object for use like the constructor, but may
// fail with OUTOFMEMORY. Should only be called by class factory
// creation routine.
//
// Arguments: None.
//
// Returns: HRESULT
// S_OK - Initialization was successful.
// E_OUTOFMEMORY - There is not enough memory to initialize.
//=============================================================================
HRESULT CDP8SimCB::InitializeObject(void) { HRESULT hr;
DPFX(DPFPREP, 5, "(0x%p) Enter", this);
DNASSERT(this->IsValidObject());
//
// Create the lock.
//
if (! DNInitializeCriticalSection(&this->m_csLock)) { hr = E_OUTOFMEMORY; goto Failure; }
//
// Don't allow critical section reentry.
//
DebugSetCriticalSectionRecursionCount(&this->m_csLock, 0);
hr = S_OK;
Exit:
DPFX(DPFPREP, 5, "(0x%p) Returning: [0x%lx]", this, hr);
return hr;
Failure:
goto Exit; } // CDP8SimCB::InitializeObject
#undef DPF_MODNAME
#define DPF_MODNAME "CDP8SimCB::UninitializeObject"
//=============================================================================
// CDP8SimCB::UninitializeObject
//-----------------------------------------------------------------------------
//
// Description: Cleans up the object like the destructor, mostly to balance
// InitializeObject.
//
// Arguments: None.
//
// Returns: None.
//=============================================================================
void CDP8SimCB::UninitializeObject(void) { DPFX(DPFPREP, 5, "(0x%p) Enter", this);
DNASSERT(this->IsValidObject());
DNDeleteCriticalSection(&this->m_csLock);
DPFX(DPFPREP, 5, "(0x%p) Returning", this); } // CDP8SimCB::UninitializeObject
|