/*========================================================================== * * 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(&pdnObject->pIDPThreadPoolWork)); hResultCode = S_OK; #else // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS hResultCode = DPTPCF_CreateObject(reinterpret_cast(&pdnObject->pIDPThreadPoolWork)); #endif // ! DPNBUILD_ONLYONETHREAD or DPNBUILD_MULTIPLETHREADPOOLS #else // ! DPNBUILD_LIBINTERFACE hResultCode = COM_CoCreateInstance(CLSID_DirectPlay8ThreadPool, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay8ThreadPoolWork, reinterpret_cast(&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(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(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(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(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(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(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(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(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(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(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