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