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.
 
 
 
 
 
 

1698 lines
46 KiB

/*==========================================================================
*
* Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
*
* File: ClassFac.cpp
* Content: DNET COM class factory
*@@BEGIN_MSINTERNAL
* History:
* Date By Reason
* ==== == ======
* 07/21/99 mjn Created
* 12/23/99 mjn Fixed Host and AllPlayers short-cut pointer use
* 12/28/99 mjn Moved Async Op stuff to Async.h
* 01/06/00 mjn Moved NameTable stuff to NameTable.h
* 01/08/00 mjn Fixed DN_APPLICATION_DESC in DIRECTNETOBJECT
* 01/13/00 mjn Added CFixedPools and CRefCountBuffers
* 01/14/00 mjn Removed pvUserContext from DN_NAMETABLE_ENTRY
* 01/15/00 mjn Replaced DN_COUNT_BUFFER with CRefCountBuffer
* 01/16/00 mjn Removed User message fixed pool
* 01/18/00 mjn Fixed bug in ref count.
* 01/19/00 mjn Replaced DN_SYNC_EVENT with CSyncEvent
* 01/19/00 mjn Initialize structures for NameTable Operation List
* 01/25/00 mjn Added NameTable pending operation list
* 01/31/00 mjn Added Internal FPM's for RefCountBuffers
* 03/17/00 rmt Added calls to init/free SP Caps cache
* 03/23/00 mjn Implemented RegisterLobby()
* 04/04/00 rmt Enabled "Enable Parameter Validation" flag on object by default
* 04/09/00 mjn Added support for CAsyncOp
* 04/11/00 mjn Added DIRECTNETOBJECT bilink for CAsyncOps
* 04/26/00 mjn Removed DN_ASYNC_OP and related functions
* 04/28/00 mjn Code cleanup - removed hsAsyncHandles,blAsyncOperations
* 05/04/00 mjn Cleaned up and made multi-thread safe
* 05/23/00 RichGr IA64: Substituted %p format specifier whereever
* %x was being used to format pointers. %p is 32-bit
* in a 32-bit build, and 64-bit in a 64-bit build.
* 06/09/00 rmt Updates to split CLSID and allow whistler compat
* 06/09/00 rmt Updates to split CLSID and allow whistler compat and support external create funcs
* 06/20/00 mjn Fixed QueryInterface bug
* 06/27/00 rmt Fixed bug which was causing interfaces to always be created as peer interfaces
* 07/05/00 rmt Bug #38478 - Could QI for peer interfaces from client object
* (All interfaces could be queried from all types of objects).
* mjn Initialize pConnect element of DIRECNETOBJECT to NULL
* 07/07/00 mjn Added pNewHost for DirectNetObject
* 07/08/00 mjn Call DN_Close when object is about to be free'd
* 07/09/00 rmt Added code to free interface set by RegisterLobby (if there is one)
* 07/17/00 mjn Add signature to DirectNetObject
* 07/21/00 RichGr IA64: Use %p format specifier for 32/64-bit pointers.
* 07/26/00 mjn DN_QueryInterface returns E_POINTER if NULL destination pointer specified
* 07/28/00 mjn Added m_bilinkConnections to DirectNetObject
* 07/30/00 mjn Added CPendingDeletion
* 07/31/00 mjn Added CQueuedMsg
* 08/05/00 mjn Added m_bilinkActiveList and csActiveList
* 08/06/00 mjn Added CWorkerJob
* 08/23/00 mjn Added CNameTableOp
* 09/04/00 mjn Added CApplicationDesc
* 01/11/2001 rmt MANBUG #48487 - DPLAY: Crashes if CoCreate() isn't called
* 02/05/01 mjn Removed unused debug members from DIRECTNETOBJECT
* mjn Added CCallbackThread
* 03/14/2001 rmt WINBUG #342420 - Restore COM emulation layer to operation
* 03/30/01 mjn Changes to prevent multiple loading/unloading of SP's
* mjn Added pConnectSP,dwMaxFrameSize
* mjn Removed blSPCapsList
* 04/04/01 mjn Added voice and lobby sigs
* 04/13/01 mjn Added m_bilinkRequestList
* 05/17/01 mjn Added dwRunningOpCount,hRunningOpEvent,dwWaitingThreadID to track threads performing NameTable operations
* 07/24/01 mjn Added DPNBUILD_NOSERVER compile flag
* 10/05/01 vanceo Added multicast object
*@@END_MSINTERNAL
*
***************************************************************************/
#include "dncorei.h"
//**********************************************************************
// Constant definitions
//**********************************************************************
//**********************************************************************
// Macro definitions
//**********************************************************************
//**********************************************************************
// Structure definitions
//**********************************************************************
#ifndef DPNBUILD_LIBINTERFACE
typedef STDMETHODIMP IUnknownQueryInterface( IUnknown *pInterface, REFIID riid, LPVOID *ppvObj );
typedef STDMETHODIMP_(ULONG) IUnknownAddRef( IUnknown *pInterface );
typedef STDMETHODIMP_(ULONG) IUnknownRelease( IUnknown *pInterface );
//
// VTable for IUnknown interface
//
IUnknownVtbl DN_UnknownVtbl =
{
(IUnknownQueryInterface*) DN_QueryInterface,
(IUnknownAddRef*) DN_AddRef,
(IUnknownRelease*) DN_Release
};
//
// VTable for Class Factory
//
IClassFactoryVtbl DNCF_Vtbl =
{
DPCF_QueryInterface, // dplay8\common\classfactory.cpp will implement these
DPCF_AddRef,
DPCF_Release,
DNCORECF_CreateInstance,
DPCF_LockServer
};
#endif // ! DPNBUILD_LIBINTERFACE
//**********************************************************************
// Variable definitions
//**********************************************************************
#ifndef DPNBUILD_NOVOICE
extern IDirectPlayVoiceTransportVtbl DN_VoiceTbl;
#endif // DPNBUILD_NOVOICE
//**********************************************************************
// Function prototypes
//**********************************************************************
//**********************************************************************
// Function definitions
//**********************************************************************
#undef DPF_MODNAME
#define DPF_MODNAME "DNCF_CreateObject"
HRESULT DNCF_CreateObject(
#ifndef DPNBUILD_LIBINTERFACE
IClassFactory* pInterface,
#endif // ! DPNBUILD_LIBINTERFACE
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
XDP8CREATE_PARAMS * pDP8CreateParams,
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DP8REFIID riid,
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
LPVOID *lplpv
)
{
HRESULT hResultCode = S_OK;
DIRECTNETOBJECT *pdnObject = NULL;
#ifndef DPNBUILD_LIBINTERFACE
const _IDirectPlayClassFactory* pDPClassFactory = (_IDirectPlayClassFactory*) pInterface;
#endif // ! DPNBUILD_LIBINTERFACE
DPFX(DPFPREP, 4,"Parameters: lplpv [%p]", lplpv);
/*
*
* TIME BOMB
*
*/
#if ((! defined(DX_FINAL_RELEASE)) && (! defined(DPNBUILD_LIBINTERFACE)))
{
#pragma message("BETA EXPIRATION TIME BOMB! Remove for final build!")
SYSTEMTIME st;
GetSystemTime(&st);
if ( st.wYear > DX_EXPIRE_YEAR || ((st.wYear == DX_EXPIRE_YEAR) && (MAKELONG(st.wDay, st.wMonth) > MAKELONG(DX_EXPIRE_DAY, DX_EXPIRE_MONTH))) )
{
MessageBox(0, DX_EXPIRE_TEXT,TEXT("Microsoft Direct Play"), MB_OK);
// return E_FAIL;
}
}
#endif // ! DX_FINAL_RELEASE and ! DPNBUILD_LIBINTERFACE
#ifndef DPNBUILD_LIBINTERFACE
if( pDPClassFactory->clsid == CLSID_DirectPlay8Client )
{
if( riid != IID_IDirectPlay8Client &&
riid != IID_IUnknown
#ifndef DPNBUILD_NOVOICE
&& riid != IID_IDirectPlayVoiceTransport
#endif // DPNBUILD_NOVOICE
)
{
DPFX(DPFPREP, 0, "Requesting unknown interface from client CLSID" );
return E_NOINTERFACE;
}
}
#ifndef DPNBUILD_NOSERVER
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Server )
{
if( riid != IID_IDirectPlay8Server &&
riid != IID_IUnknown
#ifndef DPNBUILD_NOVOICE
&& riid != IID_IDirectPlayVoiceTransport
#endif // ! DPNBUILD_NOVOICE
#ifndef DPNBUILD_NOPROTOCOLTESTITF
&& riid != IID_IDirectPlay8Protocol
#endif // ! DPNBUILD_NOPROTOCOLTESTITF
)
{
DPFX(DPFPREP, 0, "Requesting unknown interface from server CLSID" );
return E_NOINTERFACE;
}
}
#endif // ! DPNBUILD_NOSERVER
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Peer )
{
if( riid != IID_IDirectPlay8Peer &&
riid != IID_IUnknown
#ifndef DPNBUILD_NOVOICE
&& riid != IID_IDirectPlayVoiceTransport
#endif // ! DPNBUILD_NOVOICE
)
{
DPFX(DPFPREP, 0, "Requesting unknown interface from peer CLSID" );
return E_NOINTERFACE;
}
}
#ifndef DPNBUILD_NOMULTICAST
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Multicast )
{
if( riid != IID_IDirectPlay8Multicast &&
riid != IID_IUnknown
#ifndef DPNBUILD_NOPROTOCOLTESTITF
&& riid != IID_IDirectPlay8Protocol
#endif // ! DPNBUILD_NOPROTOCOLTESTITF
)
{
DPFX(DPFPREP, 0, "Requesting unknown interface from server CLSID" );
return E_NOINTERFACE;
}
}
#endif // ! DPNBUILD_NOMULTICAST
else
{
DNASSERT(FALSE);
}
#endif // ! DPNBUILD_LIBINTERFACE
// Allocate object
pdnObject = (DIRECTNETOBJECT*) DNMalloc(sizeof(DIRECTNETOBJECT));
if (pdnObject == NULL)
{
DPFERR("Creating DIRECTNETOBJECT failed!");
return(E_OUTOFMEMORY);
}
DPFX(DPFPREP, 0,"pdnObject [%p]",pdnObject);
// Zero out the new object so we don't have to individually zero many members
memset(pdnObject, 0, sizeof(DIRECTNETOBJECT));
//
// Signatures
//
pdnObject->Sig[0] = 'D';
pdnObject->Sig[1] = 'N';
pdnObject->Sig[2] = 'E';
pdnObject->Sig[3] = 'T';
#ifndef DPNBUILD_NOVOICE
pdnObject->VoiceSig[0] = 'V';
pdnObject->VoiceSig[1] = 'O';
pdnObject->VoiceSig[2] = 'I';
pdnObject->VoiceSig[3] = 'C';
#endif // !DPNBUILD_NOVOICE
#ifndef DPNBUILD_NOLOBBY
pdnObject->LobbySig[0] = 'L';
pdnObject->LobbySig[1] = 'O';
pdnObject->LobbySig[2] = 'B';
pdnObject->LobbySig[3] = 'B';
#endif // ! DPNBUILD_NOLOBBY
// Initialize Critical Section
if (!DNInitializeCriticalSection(&(pdnObject->csDirectNetObject)))
{
DPFERR("DNInitializeCriticalSection() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
if (!DNInitializeCriticalSection(&(pdnObject->csServiceProviders)))
{
DPFERR("DNInitializeCriticalSection() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
if (!DNInitializeCriticalSection(&(pdnObject->csNameTableOpList)))
{
DPFERR("DNInitializeCriticalSection() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#ifdef DBG
if (!DNInitializeCriticalSection(&(pdnObject->csAsyncOperations)))
{
DPFERR("DNInitializeCriticalSection() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#endif // DBG
#ifndef DPNBUILD_NOVOICE
if (!DNInitializeCriticalSection(&(pdnObject->csVoice)))
{
DPFERR("DNInitializeCriticalSection() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#endif // !DPNBUILD_NOVOICE
#ifndef DPNBUILD_NONSEQUENTIALWORKERQUEUE
if (!DNInitializeCriticalSection(&(pdnObject->csWorkerQueue)))
{
DPFERR("DNInitializeCriticalSection(worker queue) failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#endif // ! DPNBUILD_NONSEQUENTIALWORKERQUEUE
if (!DNInitializeCriticalSection(&(pdnObject->csActiveList)))
{
DPFERR("DNInitializeCriticalSection(csActiveList) failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
if (!DNInitializeCriticalSection(&(pdnObject->csConnectionList)))
{
DPFERR("DNInitializeCriticalSection(csConnectionList) failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
if (!DNInitializeCriticalSection(&(pdnObject->csCallbackThreads)))
{
DPFERR("DNInitializeCriticalSection(csCallbackThreads) failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#ifndef DPNBUILD_NOPARAMVAL
pdnObject->dwFlags = DN_OBJECT_FLAG_PARAMVALIDATION;
#endif // !DPNBUILD_NOPARAMVAL
//
// Initialize NameTable
//
if ((hResultCode = pdnObject->NameTable.Initialize(pdnObject)) != DPN_OK)
{
DPFERR("Could not initialize NameTable");
DisplayDNError(0,hResultCode);
DNCF_FreeObject(pdnObject);
return(hResultCode);
}
//
// Create a thread pool work interface
//
#ifdef DPNBUILD_LIBINTERFACE
#if ((defined(DPNBUILD_ONLYONETHREAD)) && (! defined(DPNBUILD_MULTIPLETHREADPOOLS)))
DPTPCF_GetObject(reinterpret_cast<void**>(&pdnObject->pIDPThreadPoolWork));
hResultCode = S_OK;
#else // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
hResultCode = DPTPCF_CreateObject(reinterpret_cast<void**>(&pdnObject->pIDPThreadPoolWork));
#endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS
#else // ! DPNBUILD_LIBINTERFACE
hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8ThreadPool,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlay8ThreadPoolWork,
reinterpret_cast<void**>(&pdnObject->pIDPThreadPoolWork),
FALSE);
#endif // ! DPNBUILD_LIBINTERFACE
if (hResultCode != S_OK)
{
DPFX(DPFPREP, 0, "Could not create Thread Pool Work interface (err = 0x%lx)!", hResultCode);
DisplayDNError(0,hResultCode);
DNCF_FreeObject(pdnObject);
return(hResultCode);
}
//
// Create Protocol Object
//
hResultCode = DNPProtocolCreate(
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
pDP8CreateParams,
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
&pdnObject->pdnProtocolData
);
if (FAILED(hResultCode))
{
DPFERR("DNPProtocolCreate() failed");
DNCF_FreeObject(pdnObject);
return(E_OUTOFMEMORY);
}
#if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONESP)))
if ((hResultCode = DNPProtocolInitialize( pdnObject->pdnProtocolData, pdnObject, &g_ProtocolVTBL,
pdnObject->pIDPThreadPoolWork, FALSE)) != DPN_OK)
{
DPFERR("DNPProtocolInitialize() failed");
DisplayDNError(0,hResultCode);
return(E_OUTOFMEMORY);
}
#endif // DPNBUILD_LIBINTERFACE and DPNBUILD_ONLYONESP
pdnObject->hProtocolShutdownEvent = NULL;
pdnObject->lProtocolRefCount = 0;
#ifndef DPNBUILD_ONLYONESP
// Initialize SP List
pdnObject->m_bilinkServiceProviders.Initialize();
#endif // ! DPNBUILD_ONLYONESP
#ifdef DBG
//
// Initialize AsyncOp List
//
pdnObject->m_bilinkAsyncOps.Initialize();
#endif // DBG
//
// Initialize outstanding CConection list
//
pdnObject->m_bilinkConnections.Initialize();
//
// Initialize pending deletion list
//
pdnObject->m_bilinkPendingDeletions.Initialize();
//
// Initialize active AsyncOp list
//
pdnObject->m_bilinkActiveList.Initialize();
//
// Initialize request AsyncOp list
//
pdnObject->m_bilinkRequestList.Initialize();
#ifndef DPNBUILD_NONSEQUENTIALWORKERQUEUE
//
// Initialize worker thread job list
//
pdnObject->m_bilinkWorkerJobs.Initialize();
pdnObject->fProcessingWorkerJobs = FALSE;
#endif // ! DPNBUILD_NONSEQUENTIALWORKERQUEUE
//
// Initialize indicated connection list
//
pdnObject->m_bilinkIndicated.Initialize();
//
// Initialize callback thread list
//
pdnObject->m_bilinkCallbackThreads.Initialize();
// Setup Flags
#ifdef DPNBUILD_LIBINTERFACE
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
switch (pDP8CreateParams->riidInterfaceType)
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
switch (riid)
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
{
case IID_IDirectPlay8Client:
{
DPFX(DPFPREP, 5,"DirectPlay8 CLIENT");
pdnObject->dwFlags |= DN_OBJECT_FLAG_CLIENT;
pdnObject->lpVtbl = &DN_ClientVtbl;
break;
}
#ifndef DPNBUILD_NOSERVER
case IID_IDirectPlay8Server:
{
DPFX(DPFPREP, 5,"DirectPlay8 SERVER");
pdnObject->dwFlags |= DN_OBJECT_FLAG_SERVER;
pdnObject->lpVtbl = &DN_ServerVtbl;
break;
}
#endif // ! DPNBUILD_NOSERVER
case IID_IDirectPlay8Peer:
{
DPFX(DPFPREP, 5,"DirectPlay8 PEER");
pdnObject->dwFlags |= DN_OBJECT_FLAG_PEER;
pdnObject->lpVtbl = &DN_PeerVtbl;
break;
}
#ifndef DPNBUILD_NOMULTICAST
case IID_IDirectPlay8Multicast:
{
DPFX(DPFPREP, 5,"DirectPlay8 MULTICAST");
pdnObject->dwFlags |= DN_OBJECT_FLAG_MULTICAST;
pdnObject->lpVtbl = &DNMcast_Vtbl;
break;
}
#endif // ! DPNBUILD_NOMULTICAST
default:
{
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
DPFX(DPFPREP, 0, "Requesting unknown interface type %x!",
pDP8CreateParams->riidInterfaceType);
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DPFX(DPFPREP, 0, "Requesting unknown interface type %x!",
riid);
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
return E_NOINTERFACE;
break;
}
}
#else // ! DPNBUILD_LIBINTERFACE
if (IsEqualIID(riid,IID_IDirectPlay8Client))
{
DPFX(DPFPREP, 5,"DirectPlay8 CLIENT");
pdnObject->dwFlags |= DN_OBJECT_FLAG_CLIENT;
}
#ifndef DPNBUILD_NOSERVER
else if (IsEqualIID(riid,IID_IDirectPlay8Server))
{
DPFX(DPFPREP, 5,"DirectPlay8 SERVER");
pdnObject->dwFlags |= DN_OBJECT_FLAG_SERVER;
}
#endif // DPNBUILD_NOSERVER
else if (IsEqualIID(riid,IID_IDirectPlay8Peer))
{
DPFX(DPFPREP, 5,"DirectPlay8 PEER");
pdnObject->dwFlags |= DN_OBJECT_FLAG_PEER;
}
#ifndef DPNBUILD_NOMULTICAST
else if (IsEqualIID(riid,IID_IDirectPlay8Multicast))
{
DPFX(DPFPREP, 5,"DirectPlay8 MULTICAST");
pdnObject->dwFlags |= DN_OBJECT_FLAG_MULTICAST;
}
#endif // DPNBUILD_NOMULTICAST
#ifndef DPNBUILD_NOPROTOCOLTESTITF
else if (IsEqualIID(riid,IID_IDirectPlay8Protocol))
{
DPFX(DPFPREP, 5,"IDirectPlay8Protocol");
pdnObject->dwFlags |= DN_OBJECT_FLAG_SERVER;
}
#endif // !DPNBUILD_NOPROTOCOLTESTITF
else if( riid == IID_IUnknown )
{
if( pDPClassFactory->clsid == CLSID_DirectPlay8Client )
{
DPFX(DPFPREP, 5,"DirectPlay8 CLIENT via IUnknown");
pdnObject->dwFlags |= DN_OBJECT_FLAG_CLIENT;
}
#ifndef DPNBUILD_NOSERVER
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Server )
{
DPFX(DPFPREP, 5,"DirectPlay8 SERVER via IUnknown");
pdnObject->dwFlags |= DN_OBJECT_FLAG_SERVER;
}
#endif // DPNBUILD_NOSERVER
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Peer )
{
DPFX(DPFPREP, 5,"DirectPlay8 PEER via IUnknown");
pdnObject->dwFlags |= DN_OBJECT_FLAG_PEER;
}
#ifndef DPNBUILD_NOMULTICAST
else if( pDPClassFactory->clsid == CLSID_DirectPlay8Multicast )
{
DPFX(DPFPREP, 5,"DirectPlay8 MULTICAST via IUnknown");
pdnObject->dwFlags |= DN_OBJECT_FLAG_MULTICAST;
}
#endif // DPNBUILD_NOMULTICAST
else
{
DPFX(DPFPREP, 0,"Unknown CLSID!");
DNASSERT( FALSE );
DNCF_FreeObject(pdnObject);
return(E_NOTIMPL);
}
}
else
{
DPFX(DPFPREP, 0,"Invalid DirectPlay8 Interface");
DNCF_FreeObject(pdnObject);
return(E_NOTIMPL);
}
#endif // ! DPNBUILD_LIBINTERFACE
//
// Create lock event
//
if ((pdnObject->hLockEvent = DNCreateEvent(NULL,TRUE,FALSE,NULL)) == NULL)
{
DPFERR("Unable to create lock event");
DNCF_FreeObject(pdnObject);
return(DPNERR_OUTOFMEMORY);
}
//
// Create running operation event (for host migration)
//
if ( pdnObject->dwFlags & DN_OBJECT_FLAG_PEER )
{
if ((pdnObject->hRunningOpEvent = DNCreateEvent(NULL,TRUE,FALSE,NULL)) == NULL)
{
DPFERR("Unable to create running operation event");
DNCF_FreeObject(pdnObject);
return(DPNERR_OUTOFMEMORY);
}
}
#ifndef DPNBUILD_NOMULTICAST
pdnObject->pMulticastSend = NULL;
pdnObject->m_bilinkMulticast.Initialize();
#endif // DPNBUILD_NOMULTICAST
#ifdef DPNBUILD_LIBINTERFACE
#ifdef DPNBUILD_ONLYONESP
hResultCode = DN_SPInstantiate(
pdnObject
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
,pDP8CreateParams
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
);
if (hResultCode != S_OK)
{
DPFX(DPFPREP, 0, "Could not instantiate SP (err = 0x%lx)!", hResultCode);
DisplayDNError(0,hResultCode);
DNCF_FreeObject(pdnObject);
return(hResultCode);
}
#endif // DPNBUILD_ONLYONESP
//
// For lib interface builds, the refcount is embedded in object.
//
pdnObject->lRefCount = 1;
#endif // DPNBUILD_LIBINTERFACE
*lplpv = pdnObject;
DPFX(DPFPREP, 4,"Returning: hResultCode = [%lx], *lplpv = [%p]",hResultCode,*lplpv);
return(hResultCode);
}
#ifndef WINCE
#ifdef _XBOX
#undef DPF_MODNAME
#define DPF_MODNAME "XDirectPlay8Create"
HRESULT WINAPI XDirectPlay8Create(
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
const XDP8CREATE_PARAMS * const pDP8CreateParams,
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DP8REFIID riidInterfaceType,
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
void **ppvInterface
)
{
HRESULT hr;
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
XDP8CREATE_PARAMS CreateParamsAdjusted;
DPFX(DPFPREP, 5, "Parameters: pDP8CreateParams[0x%p], ppvInterface[0x%p]", pDP8CreateParams, ppvInterface);
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DPFX(DPFPREP, 5, "Parameters: riidInterfaceType[0x%x], ppvInterface[0x%p]", riidInterfaceType, ppvInterface);
#endif // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
#ifndef DPNBUILD_NOPARAMVAL
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
if ((pDP8CreateParams == NULL) ||
(! DNVALID_READPTR(pDP8CreateParams, sizeof(CreateParamsAdjusted))))
{
DPFX(DPFPREP, 0, "Invalid pointer to Create parameters!");
return DPNERR_INVALIDPOINTER;
}
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
{
DPFX(DPFPREP, 0, "Invalid pointer specified to receive interface!");
return DPNERR_INVALIDPOINTER;
}
#endif // ! DPNBUILD_NOPARAMVAL
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
memcpy(&CreateParamsAdjusted, pDP8CreateParams, sizeof(CreateParamsAdjusted));
switch (CreateParamsAdjusted.riidInterfaceType)
{
case IID_IDirectPlay8Client:
{
CreateParamsAdjusted.dwMaxNumPlayers = 1;
break;
}
#ifndef DPNBUILD_NOSERVER
case IID_IDirectPlay8Server:
#endif // ! DPNBUILD_NOSERVER
case IID_IDirectPlay8Peer:
{
//
// Include room for hidden All Players group.
//
CreateParamsAdjusted.dwMaxNumGroups++;
break;
}
#ifndef DPNBUILD_NOMULTICAST
case IID_IDirectPlay8Multicast:
{
CreateParamsAdjusted.dwMaxNumGroups = 0;
break;
}
#endif // ! DPNBUILD_NOMULTICAST
#ifndef DPNBUILD_NOPARAMVAL
default:
{
DPFX(DPFPREP, 0, "Requesting unknown interface type %u!", CreateParamsAdjusted.riidInterfaceType);
return E_NOINTERFACE;
break;
}
#endif // ! DPNBUILD_NOPARAMVAL
}
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(! DNMemoryTrackAreAllocationsAllowed());
DNMemoryTrackAllowAllocations(TRUE);
hr = DNCF_CreateObject(&CreateParamsAdjusted, ppvInterface);
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(DNMemoryTrackAreAllocationsAllowed());
hr = DNCF_CreateObject(riidInterfaceType, ppvInterface);
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
if (hr != S_OK)
{
DPFX(DPFPREP, 0, "Couldn't create interface!");
return hr;
}
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
//
// Pre-allocate the requested memory.
//
hr = DN_PopulateCorePools((DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(*ppvInterface),
&CreateParamsAdjusted);
if (hr != DPN_OK)
{
DPFX(DPFPREP, 0, "Couldn't populate core pools!");
DNCF_FreeObject((DIRECTNETOBJECT*) GET_OBJECT_FROM_INTERFACE(*ppvInterface));
*ppvInterface = NULL;
return hr;
}
DNASSERT(DNMemoryTrackAreAllocationsAllowed());
DNMemoryTrackAllowAllocations(FALSE);
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
return DPN_OK;
}
extern STDMETHODIMP DPTP_DoWork(const DWORD dwAllowedTimeSlice,
const DWORD dwFlags);
HRESULT WINAPI XDirectPlay8DoWork(const DWORD dwAllowedTimeSlice)
{
return DPTP_DoWork(dwAllowedTimeSlice, 0);
}
HRESULT WINAPI XDirectPlay8BuildAppDescReservedData(const XNKID * const pSessionID,
const XNKEY * const pKeyExchangeKey,
PVOID pvReservedData,
DWORD * const pcbReservedDataSize)
{
SPSESSIONDATA_XNET * pSessionDataXNet;
#ifndef DPNBUILD_NOPARAMVAL
if ((pSessionID == NULL) ||
(! DNVALID_READPTR(pSessionID, sizeof(XNKID))))
{
DPFERR("Invalid session key ID specified");
return DPNERR_INVALIDPOINTER;
}
if ((pKeyExchangeKey == NULL) ||
(! DNVALID_READPTR(pKeyExchangeKey, sizeof(XNKEY))))
{
DPFERR("Invalid key exchange key specified");
return DPNERR_INVALIDPOINTER;
}
if ((pcbReservedDataSize == NULL) ||
(! DNVALID_WRITEPTR(pcbReservedDataSize, sizeof(DWORD))))
{
DPFERR("Invalid pointer specified for data size");
return DPNERR_INVALIDPOINTER;
}
if ((*pcbReservedDataSize > 0) &&
((pvReservedData == NULL) || (! DNVALID_WRITEPTR(pvReservedData, *pcbReservedDataSize))))
{
DPFERR("Invalid pointer specified for reserved data buffer");
return DPNERR_INVALIDPOINTER;
}
#endif // ! DPNBUILD_NOPARAMVAL
if (*pcbReservedDataSize < DPN_MAX_APPDESC_RESERVEDDATA_SIZE)
{
*pcbReservedDataSize = DPN_MAX_APPDESC_RESERVEDDATA_SIZE;
return DPNERR_BUFFERTOOSMALL;
}
DBG_CASSERT(sizeof(SPSESSIONDATA_XNET) < DPN_MAX_APPDESC_RESERVEDDATA_SIZE);
pSessionDataXNet = (SPSESSIONDATA_XNET*) pvReservedData;
pSessionDataXNet->dwInfo = SPSESSIONDATAINFO_XNET;
DBG_CASSERT(sizeof(pSessionDataXNet->guidKey) == sizeof(*pKeyExchangeKey));
memcpy(&pSessionDataXNet->guidKey, pKeyExchangeKey, sizeof(pSessionDataXNet->guidKey));
DBG_CASSERT(sizeof(pSessionDataXNet->ullKeyID) == sizeof(*pSessionID));
memcpy(&pSessionDataXNet->ullKeyID, pSessionID, sizeof(pSessionDataXNet->ullKeyID));
//
// Fill in the remainder of the data with deterministic but non-obvious bytes so
// that we can:
// a) overwrite potential stack garbage
// b) prevent the app from being able to assume there will always be less than
// DPN_MAX_APPDESC_RESERVEDDATA_SIZE bytes of data. This gives us a little
// flexibility for forward compatibility.
//
memset((pSessionDataXNet + 1),
(((BYTE*) pSessionID)[1] ^ ((BYTE*) pKeyExchangeKey)[2]),
(DPN_MAX_APPDESC_RESERVEDDATA_SIZE - sizeof(SPSESSIONDATA_XNET)));
*pcbReservedDataSize = DPN_MAX_APPDESC_RESERVEDDATA_SIZE;
return DPN_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XDirectPlay8AddressCreate"
HRESULT WINAPI XDirectPlay8AddressCreate( DPNAREFIID riid, void **ppvInterface )
{
HRESULT hr;
DPFX(DPFPREP, 5, "Parameters: riid[0x%p], ppvInterface[0x%p]", &riid, ppvInterface);
#ifndef DPNBUILD_NOPARAMVAL
if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
{
DPFERR( "Invalid pointer specified to receive interface" );
return DPNERR_INVALIDPOINTER;
}
switch (riid)
{
case IID_IDirectPlay8Address:
{
break;
}
case IID_IDirectPlay8AddressIP:
{
#ifdef DPNBUILD_NOADDRESSIPINTERFACE
DPFX(DPFPREP, 0, "The IDirectPlay8AddressIP interface is not supported!");
return DPNERR_UNSUPPORTED;
#endif // DPNBUILD_NOADDRESSIPINTERFACE
break;
}
default:
{
DPFX(DPFPREP, 0, "Requesting unknown interface type %u!", riid);
return E_NOINTERFACE;
break;
}
}
#endif // ! DPNBUILD_NOPARAMVAL
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(! DNMemoryTrackAreAllocationsAllowed());
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(DNMemoryTrackAreAllocationsAllowed());
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
hr = DP8ACF_CreateInstance(riid, ppvInterface);
if (hr != S_OK)
{
DPFX(DPFPREP, 0, "Couldn't create interface!");
return hr;
}
return S_OK;
}
#undef DPF_MODNAME
#define DPF_MODNAME "XDirectPlay8AddressCreateFromXnAddr"
HRESULT WINAPI XDirectPlay8AddressCreateFromXnAddr( XNADDR *pxnaddr, IDirectPlay8Address **ppInterface )
{
HRESULT hr;
TCHAR tszHostname[(sizeof(XNADDR) * 2) + 1]; // 2 characters for every byte + NULL termination
TCHAR * ptszCurrent;
BYTE * pbCurrent;
DWORD dwTemp;
DPFX(DPFPREP, 5, "Parameters: pxnaddr[0x%p], ppInterface[0x%p]", pxnaddr, ppInterface);
#ifndef DPNBUILD_NOPARAMVAL
if( pxnaddr == NULL )
{
DPFERR( "Invalid XNADDR" );
return DPNERR_INVALIDPOINTER;
}
if( ppInterface == NULL || !DNVALID_WRITEPTR( ppInterface, sizeof( IDirectPlay8Address * ) ) )
{
DPFERR( "Invalid pointer specified to receive interface" );
return DPNERR_INVALIDPOINTER;
}
#endif // ! DPNBUILD_NOPARAMVAL
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(! DNMemoryTrackAreAllocationsAllowed());
#else // ! DPNBUILD_PREALLOCATEDMEMORYMODEL
DNASSERT(DNMemoryTrackAreAllocationsAllowed());
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
hr = DP8ACF_CreateInstance(IID_IDirectPlay8Address, (PVOID*) ppInterface);
if (hr != S_OK)
{
DPFX(DPFPREP, 0, "Couldn't create interface!");
return hr;
}
ptszCurrent = tszHostname;
pbCurrent = (BYTE*) pxnaddr;
for(dwTemp = 0; dwTemp < sizeof(XNADDR); dwTemp++)
{
ptszCurrent += wsprintf(tszHostname, _T("%02X"), (*pbCurrent));
pbCurrent++;
}
DNASSERT(((_tcslen(tszHostname) + 1) * sizeof(TCHAR)) == sizeof(tszHostname));
#ifdef UNICODE
hr = IDirectPlay8Address_AddComponent((*ppInterface),
DPNA_KEY_HOSTNAME,
tszHostname,
sizeof(tszHostname),
DPNA_DATATYPE_STRING);
#else // ! UNICODE
hr = IDirectPlay8Address_AddComponent((*ppInterface),
DPNA_KEY_HOSTNAME,
tszHostname,
sizeof(tszHostname),
DPNA_DATATYPE_STRING_ANSI);
#endif // ! UNICODE
if (hr != DPN_OK)
{
DPFX(DPFPREP, 0, "Couldn't add hostname component!");
IDirectPlay8Address_Release(*ppInterface);
*ppInterface = NULL;
return hr;
}
return S_OK;
}
#else // ! _XBOX
#undef DPF_MODNAME
#define DPF_MODNAME "DirectPlay8Create"
HRESULT WINAPI DirectPlay8Create( const GUID * pcIID, void **ppvInterface, IUnknown *pUnknown)
{
GUID clsid;
DPFX(DPFPREP, 5, "Parameters: pcIID[0x%p], ppvInterface[0x%p], pUnknown[0x%p]", pcIID, ppvInterface, pUnknown);
#ifndef DPNBUILD_NOPARAMVAL
if( pcIID == NULL ||
!DNVALID_READPTR( pcIID, sizeof( GUID ) ) )
{
DPFERR( "Invalid pointer specified for interface GUID" );
return DPNERR_INVALIDPOINTER;
}
if( ppvInterface == NULL || !DNVALID_WRITEPTR( ppvInterface, sizeof( void * ) ) )
{
DPFERR( "Invalid pointer specified to receive interface" );
return DPNERR_INVALIDPOINTER;
}
if( pUnknown != NULL )
{
DPFERR( "Aggregation is not supported by this object yet" );
return DPNERR_INVALIDPARAM;
}
#endif // ! DPNBUILD_NOPARAMVAL
if( *pcIID == IID_IDirectPlay8Client )
{
clsid = CLSID_DirectPlay8Client;
}
#ifndef DPNBUILD_NOSERVER
else if( *pcIID == IID_IDirectPlay8Server )
{
clsid = CLSID_DirectPlay8Server;
}
#endif // ! DPNBUILD_NOSERVER
else if( *pcIID == IID_IDirectPlay8Peer )
{
clsid = CLSID_DirectPlay8Peer;
}
#ifndef DPNBUILD_NOMULTICAST
else if( *pcIID == IID_IDirectPlay8Multicast )
{
clsid = CLSID_DirectPlay8Multicast;
}
#endif // ! DPNBUILD_NOMULTICAST
#ifndef DPNBUILD_NOLOBBY
else if( *pcIID == IID_IDirectPlay8LobbyClient )
{
clsid = CLSID_DirectPlay8LobbyClient;
}
else if( *pcIID == IID_IDirectPlay8LobbiedApplication )
{
clsid = CLSID_DirectPlay8LobbiedApplication;
}
#endif // ! DPNBUILD_NOLOBBY
else if( *pcIID == IID_IDirectPlay8Address )
{
clsid = CLSID_DirectPlay8Address;
}
#ifndef DPNBUILD_NOADDRESSIPINTERFACE
else if( *pcIID == IID_IDirectPlay8AddressIP )
{
clsid = CLSID_DirectPlay8Address;
}
#endif // ! DPNBUILD_NOADDRESSIPINTERFACE
else
{
DPFERR( "Invalid IID specified" );
return DPNERR_INVALIDPARAM;
}
return COM_CoCreateInstance( clsid, NULL, CLSCTX_INPROC_SERVER, *pcIID, ppvInterface, TRUE );
}
#endif // ! _XBOX
#endif // ! WINCE
#undef DPF_MODNAME
#define DPF_MODNAME "DNCF_FreeObject"
HRESULT DNCF_FreeObject(PVOID pInterface)
{
HRESULT hResultCode = S_OK;
DIRECTNETOBJECT *pdnObject;
DPFX(DPFPREP, 4,"Parameters: pInterface [0x%p]",pInterface);
#pragma BUGBUG(minara,"Do I need to delete the fixed pools here ?")
if (pInterface == NULL)
{
return(DPNERR_INVALIDPARAM);
}
pdnObject = static_cast<DIRECTNETOBJECT*>(pInterface);
DNASSERT(pdnObject != NULL);
#ifdef DPNBUILD_LIBINTERFACE
//
// For lib interface builds, the reference is embedded in the object directly.
//
DNASSERT(pdnObject->lRefCount == 0);
#ifdef DPNBUILD_ONLYONESP
DN_SPReleaseAll(pdnObject);
#endif // DPNBUILD_ONLYONESP
#endif // DPNBUILD_LIBINTERFACE
//
// No connect SP
//
DNASSERT(pdnObject->pConnectSP == NULL);
//
// No outstanding listens
//
DNASSERT(pdnObject->pListenParent == NULL);
//
// No outstanding connect
//
DNASSERT(pdnObject->pConnectParent == NULL);
//
// Host migration target
//
DNASSERT(pdnObject->pNewHost == NULL);
//
// Protocol shutdown event
//
DNASSERT(pdnObject->hProtocolShutdownEvent == NULL);
//
// Lock event
//
if (pdnObject->hLockEvent)
{
DNCloseHandle(pdnObject->hLockEvent);
}
//
// Running operations
//
if (pdnObject->hRunningOpEvent)
{
DNCloseHandle(pdnObject->hRunningOpEvent);
}
#ifdef DPNBUILD_ONLYONETHREAD
#ifndef DPNBUILD_NONSEQUENTIALWORKERQUEUE
DNASSERT(pdnObject->ThreadPoolShutDownEvent == NULL);
DNASSERT(pdnObject->lThreadPoolRefCount == 0);
#endif // DPNBUILD_NONSEQUENTIALWORKERQUEUE
#endif // DPNBUILD_ONLYONETHREAD
// pIDPThreadPoolWork will be NULL if we failed CoCreate'ing the thread pool in DNCF_CreateObject
if (pdnObject->pIDPThreadPoolWork != NULL)
{
IDirectPlay8ThreadPoolWork_Release(pdnObject->pIDPThreadPoolWork);
pdnObject->pIDPThreadPoolWork = NULL;
}
#ifndef DPNBUILD_NONSEQUENTIALWORKERQUEUE
DNDeleteCriticalSection(&pdnObject->csWorkerQueue);
#endif // ! DPNBUILD_NONSEQUENTIALWORKERQUEUE
//
// Protocol
//
#if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONESP)))
if ((hResultCode = DNPProtocolShutdown(pdnObject->pdnProtocolData)) != DPN_OK)
{
DPFERR("Could not shut down Protocol Layer !");
DisplayDNError(0,hResultCode);
DNASSERT(FALSE);
}
#endif // DPNBUILD_LIBINTERFACE and DPNBUILD_ONLYONESP
DNPProtocolDestroy(pdnObject->pdnProtocolData);
pdnObject->pdnProtocolData = NULL;
//
// Deinitialize NameTable
//
DPFX(DPFPREP, 3,"Deinitializing NameTable");
pdnObject->NameTable.Deinitialize();
// Active AsyncOp List Critical Section
DNDeleteCriticalSection(&pdnObject->csActiveList);
// NameTable operation list Critical Section
DNDeleteCriticalSection(&pdnObject->csNameTableOpList);
// Service Providers Critical Section
DNDeleteCriticalSection(&pdnObject->csServiceProviders);
#ifdef DBG
// Async Ops Critical Section
DNDeleteCriticalSection(&pdnObject->csAsyncOperations);
#endif // DBG
// Connection Critical Section
DNDeleteCriticalSection(&pdnObject->csConnectionList);
#ifndef DPNBUILD_NOVOICE
// Voice Critical Section
DNDeleteCriticalSection(&pdnObject->csVoice);
#endif // !DPNBUILD_NOVOICE
// Callback Thread List Critical Section
DNDeleteCriticalSection(&pdnObject->csCallbackThreads);
#ifndef DPNBUILD_NOLOBBY
if( pdnObject->pIDP8LobbiedApplication)
{
IDirectPlay8LobbiedApplication_Release( pdnObject->pIDP8LobbiedApplication );
pdnObject->pIDP8LobbiedApplication = NULL;
}
#endif // ! DPNBUILD_NOLOBBY
// Delete DirectNet critical section
DNDeleteCriticalSection(&pdnObject->csDirectNetObject);
#ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL
if (pdnObject->fPoolsPrepopulated)
{
pdnObject->EnumReplyMemoryBlockPool.DeInitialize();
pdnObject->fPoolsPrepopulated = FALSE;
}
#endif // DPNBUILD_PREALLOCATEDMEMORYMODEL
DPFX(DPFPREP, 5,"free pdnObject [%p]",pdnObject);
DNFree(pdnObject);
DPFX(DPFPREP, 4,"Returning: [%lx]",hResultCode);
return(hResultCode);
}
#ifdef DPNBUILD_LIBINTERFACE
#undef DPF_MODNAME
#define DPF_MODNAME "DN_QueryInterface"
STDMETHODIMP DN_QueryInterface(void *pInterface,
DP8REFIID riid,
void **ppv)
{
HRESULT hResultCode;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], riid [0x%p], ppv [0x%p]",pInterface,&riid,ppv);
DPFX(DPFPREP, 0, "Querying for an interface is not supported!");
hResultCode = DPNERR_UNSUPPORTED;
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
return(hResultCode);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_AddRef"
STDMETHODIMP_(ULONG) DN_AddRef(void *pInterface)
{
DIRECTNETOBJECT *pdnObject;
LONG lRefCount;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pInterface);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
lRefCount = 0;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
pdnObject = static_cast<DIRECTNETOBJECT*>(pInterface);
lRefCount = DNInterlockedIncrement( &pdnObject->lRefCount );
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
#ifndef DPNBUILD_NOPARAMVAL
Exit:
#endif // ! DPNBUILD_NOPARAMVAL
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
return(lRefCount);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_Release"
STDMETHODIMP_(ULONG) DN_Release(void *pInterface)
{
DIRECTNETOBJECT *pdnObject;
LONG lRefCount;
DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pInterface);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
lRefCount = 0;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
pdnObject = static_cast<DIRECTNETOBJECT*>(pInterface);
lRefCount = DNInterlockedDecrement( &pdnObject->lRefCount );
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
if (lRefCount == 0)
{
//
// Ensure we're properly closed
//
DN_Close(pdnObject, 0);
// Free object here
DPFX(DPFPREP, 5,"Free object");
DNCF_FreeObject(pdnObject);
}
#ifndef DPNBUILD_NOPARAMVAL
Exit:
#endif // ! DPNBUILD_NOPARAMVAL
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
return(lRefCount);
}
#else // ! DPNBUILD_LIBINTERFACE
#undef DPF_MODNAME
#define DPF_MODNAME "DNCORECF_CreateInstance"
STDMETHODIMP DNCORECF_CreateInstance(IClassFactory *pInterface,
LPUNKNOWN lpUnkOuter,
REFIID riid,
void **ppv)
{
HRESULT hResultCode;
INTERFACE_LIST *pIntList;
OBJECT_DATA *pObjectData;
DPFX(DPFPREP, 6,"Parameters: pInterface [%p], lpUnkOuter [%p], riid [%p], ppv [%p]",pInterface,lpUnkOuter,&riid,ppv);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
hResultCode = E_INVALIDARG;
goto Exit;
}
if (lpUnkOuter != NULL)
{
hResultCode = CLASS_E_NOAGGREGATION;
goto Exit;
}
if (ppv == NULL)
{
DPFERR("Invalid target interface pointer specified");
hResultCode = E_INVALIDARG;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
pObjectData = NULL;
pIntList = NULL;
if ((pObjectData = static_cast<OBJECT_DATA*>(DNMalloc(sizeof(OBJECT_DATA)))) == NULL)
{
DPFERR("Could not allocate object");
hResultCode = E_OUTOFMEMORY;
goto Failure;
}
// Object creation and initialization
if ((hResultCode = DNCF_CreateObject(pInterface, riid, &pObjectData->pvData)) != S_OK)
{
DPFERR("Could not create object");
goto Failure;
}
DPFX(DPFPREP, 7,"Created and initialized object");
// Get requested interface
if ((hResultCode = DN_CreateInterface(pObjectData,riid,&pIntList)) != S_OK)
{
DNCF_FreeObject(pObjectData->pvData);
goto Failure;
}
DPFX(DPFPREP, 7,"Found interface");
pObjectData->pIntList = pIntList;
pObjectData->lRefCount = 1;
DN_AddRef( pIntList );
DNInterlockedIncrement(&g_lCoreObjectCount);
*ppv = pIntList;
DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
hResultCode = S_OK;
Exit:
DPFX(DPFPREP, 6,"Returning: [0x%lx]",hResultCode);
return(hResultCode);
Failure:
if (pObjectData)
{
DNFree(pObjectData);
pObjectData = NULL;
}
goto Exit;
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_CreateInterface"
HRESULT DN_CreateInterface(OBJECT_DATA *pObject,
REFIID riid,
INTERFACE_LIST **const ppv)
{
INTERFACE_LIST *pIntNew;
PVOID lpVtbl;
HRESULT hResultCode;
DPFX(DPFPREP, 6,"Parameters: pObject [%p], riid [%p], ppv [%p]",pObject,&riid,ppv);
DNASSERT(pObject != NULL);
DNASSERT(ppv != NULL);
const DIRECTNETOBJECT* pdnObject = ((DIRECTNETOBJECT *)pObject->pvData);
if (IsEqualIID(riid,IID_IUnknown))
{
DPFX(DPFPREP, 7,"riid = IID_IUnknown");
lpVtbl = &DN_UnknownVtbl;
}
#ifndef DPNBUILD_NOVOICE
else if (IsEqualIID(riid,IID_IDirectPlayVoiceTransport))
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlayVoiceTransport");
lpVtbl = &DN_VoiceTbl;
}
#endif // !DPNBUILD_NOVOICE
#ifndef DPNBUILD_NOPROTOCOLTESTITF
else if (IsEqualIID(riid,IID_IDirectPlay8Protocol))
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8Protocol");
lpVtbl = &DN_ProtocolVtbl;
}
#endif // !DPNBUILD_NOPROTOCOLTESTITF
else if (IsEqualIID(riid,IID_IDirectPlay8Client) &&
pdnObject->dwFlags & DN_OBJECT_FLAG_CLIENT )
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8Client");
lpVtbl = &DN_ClientVtbl;
}
#ifndef DPNBUILD_NOSERVER
else if (IsEqualIID(riid,IID_IDirectPlay8Server) &&
pdnObject->dwFlags & DN_OBJECT_FLAG_SERVER )
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8Server");
lpVtbl = &DN_ServerVtbl;
}
#endif // DPNBUILD_NOSERVER
else if (IsEqualIID(riid,IID_IDirectPlay8Peer) &&
pdnObject->dwFlags & DN_OBJECT_FLAG_PEER )
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8Peer");
lpVtbl = &DN_PeerVtbl;
}
#ifndef DPNBUILD_NOMULTICAST
else if (IsEqualIID(riid,IID_IDirectPlay8Multicast) &&
pdnObject->dwFlags & DN_OBJECT_FLAG_MULTICAST )
{
DPFX(DPFPREP, 7,"riid = IID_IDirectPlay8Multicast");
lpVtbl = &DNMcast_Vtbl;
}
#endif // DPNBUILD_NOMULTICAST
else
{
DPFERR("riid not found !");
hResultCode = E_NOINTERFACE;
goto Exit;
}
if ((pIntNew = static_cast<INTERFACE_LIST*>(DNMalloc(sizeof(INTERFACE_LIST)))) == NULL)
{
DPFERR("Could not allocate interface");
hResultCode = E_OUTOFMEMORY;
goto Exit;
}
pIntNew->lpVtbl = lpVtbl;
pIntNew->lRefCount = 0;
pIntNew->pIntNext = NULL;
DBG_CASSERT( sizeof( pIntNew->iid ) == sizeof( riid ) );
memcpy( &(pIntNew->iid), &riid, sizeof( pIntNew->iid ) );
pIntNew->pObject = pObject;
*ppv = pIntNew;
DPFX(DPFPREP, 7,"*ppv = [0x%p]",*ppv);
hResultCode = S_OK;
Exit:
DPFX(DPFPREP, 6,"Returning: hResultCode = [%lx]",hResultCode);
return(hResultCode);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_FindInterface"
INTERFACE_LIST *DN_FindInterface(void *pInterface,
REFIID riid)
{
INTERFACE_LIST *pIntList;
DPFX(DPFPREP, 6,"Parameters: pInterface [%p], riid [%p]",pInterface,&riid);
DNASSERT(pInterface != NULL);
pIntList = (static_cast<INTERFACE_LIST*>(pInterface))->pObject->pIntList; // Find first interface
while (pIntList != NULL)
{
if (IsEqualIID(riid,pIntList->iid))
break;
pIntList = pIntList->pIntNext;
}
DPFX(DPFPREP, 6,"Returning: pIntList [0x%p]",pIntList);
return(pIntList);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_QueryInterface"
STDMETHODIMP DN_QueryInterface(void *pInterface,
DP8REFIID riid,
void **ppv)
{
INTERFACE_LIST *pIntList;
INTERFACE_LIST *pIntNew;
HRESULT hResultCode;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p], riid [0x%p], ppv [0x%p]",pInterface,&riid,ppv);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
hResultCode = E_INVALIDARG;
goto Exit;
}
if (ppv == NULL)
{
DPFERR("Invalid target interface pointer specified");
hResultCode = E_POINTER;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
if ((pIntList = DN_FindInterface(pInterface,riid)) == NULL)
{ // Interface must be created
pIntList = (static_cast<INTERFACE_LIST*>(pInterface))->pObject->pIntList;
if ((hResultCode = DN_CreateInterface(pIntList->pObject,riid,&pIntNew)) != S_OK)
{
goto Exit;
}
pIntNew->pIntNext = pIntList;
pIntList->pObject->pIntList = pIntNew;
pIntList = pIntNew;
}
if (pIntList->lRefCount == 0) // New interface exposed
{
DNInterlockedIncrement( &pIntList->pObject->lRefCount );
}
DNInterlockedIncrement( &pIntList->lRefCount );
*ppv = static_cast<void*>(pIntList);
DPFX(DPFPREP, 5,"*ppv = [0x%p]", *ppv);
hResultCode = S_OK;
Exit:
DPFX(DPFPREP, 2,"Returning: [0x%lx]",hResultCode);
return(hResultCode);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_AddRef"
STDMETHODIMP_(ULONG) DN_AddRef(void *pInterface)
{
INTERFACE_LIST *pIntList;
LONG lRefCount;
DPFX(DPFPREP, 2,"Parameters: pInterface [0x%p]",pInterface);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
lRefCount = 0;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
pIntList = static_cast<INTERFACE_LIST*>(pInterface);
lRefCount = DNInterlockedIncrement( &pIntList->lRefCount );
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
#ifndef DPNBUILD_NOPARAMVAL
Exit:
#endif // ! DPNBUILD_NOPARAMVAL
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
return(lRefCount);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DN_Release"
STDMETHODIMP_(ULONG) DN_Release(void *pInterface)
{
INTERFACE_LIST *pIntList;
INTERFACE_LIST *pIntCurrent;
LONG lRefCount;
LONG lObjRefCount;
DPFX(DPFPREP, 2,"Parameters: pInterface [%p]",pInterface);
#ifndef DPNBUILD_NOPARAMVAL
if (pInterface == NULL)
{
DPFERR("Invalid COM interface specified");
lRefCount = 0;
goto Exit;
}
#endif // ! DPNBUILD_NOPARAMVAL
pIntList = static_cast<INTERFACE_LIST*>(pInterface);
lRefCount = DNInterlockedDecrement( &pIntList->lRefCount );
DPFX(DPFPREP, 5,"New lRefCount [%ld]",lRefCount);
if (lRefCount == 0)
{
//
// Decrease object's interface count
//
lObjRefCount = DNInterlockedDecrement( &pIntList->pObject->lRefCount );
//
// Free object and interfaces
//
if (lObjRefCount == 0)
{
//
// Ensure we're properly closed
//
DN_Close(pInterface, 0);
// Free object here
DPFX(DPFPREP, 5,"Free object");
DNCF_FreeObject(pIntList->pObject->pvData);
pIntList = pIntList->pObject->pIntList; // Get head of interface list
DNFree(pIntList->pObject);
// Free Interfaces
DPFX(DPFPREP, 5,"Free interfaces");
while(pIntList != NULL)
{
pIntCurrent = pIntList;
pIntList = pIntList->pIntNext;
DNFree(pIntCurrent);
}
DNInterlockedDecrement(&g_lCoreObjectCount);
}
}
#ifndef DPNBUILD_NOPARAMVAL
Exit:
#endif // ! DPNBUILD_NOPARAMVAL
DPFX(DPFPREP, 2,"Returning: lRefCount [%ld]",lRefCount);
return(lRefCount);
}
#endif // ! DPNBUILD_LIBINTERFACE