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.
 
 
 
 
 
 

1524 lines
41 KiB

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