/*========================================================================== * * Copyright (C) 2000-2002 Microsoft Corporation. All Rights Reserved. * * File: ServProv.cpp * Content: Service Provider Objects *@@BEGIN_MSINTERNAL * History: * Date By Reason * ==== == ====== * 03/17/00 mjn Created * 04/04/00 rmt Added set of SP caps from cache (if cache exists). * 04/10/00 mjn Farm out RemoveSP to worker thread * 05/02/00 mjn Fixed RefCount issue * 06/09/00 rmt Updates to split CLSID and allow whistler compat * 07/06/00 mjn Fixes to support SP handle to Protocol * 08/03/00 rmt Bug #41244 - Wrong return codes -- part 2 * 08/05/00 RichGr IA64: Use %p format specifier in DPFs for 32/64-bit pointers and handles. * 08/06/00 mjn Added CWorkerJob * 08/20/00 mjn Changed Initialize() to not add SP to DirectNet object bilink * 10/08/01 vanceo Add multicast filter *@@END_MSINTERNAL * ***************************************************************************/ #include "dncorei.h" //********************************************************************** // Constant definitions //********************************************************************** //********************************************************************** // Macro definitions //********************************************************************** //********************************************************************** // Structure definitions //********************************************************************** //********************************************************************** // Variable definitions //********************************************************************** //********************************************************************** // Function prototypes //********************************************************************** //********************************************************************** // Function definitions //********************************************************************** #undef DPF_MODNAME #define DPF_MODNAME "CServiceProvider::Initialize" HRESULT CServiceProvider::Initialize(DIRECTNETOBJECT *const pdnObject #if ((defined(DPNBUILD_ONLYONESP)) && (defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_PREALLOCATEDMEMORYMODEL))) ,const XDP8CREATE_PARAMS * const pDP8CreateParams #else // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_PREALLOCATEDMEMORYMODEL #ifndef DPNBUILD_ONLYONESP ,const GUID *const pguid #endif // ! DPNBUILD_ONLYONESP #ifndef DPNBUILD_LIBINTERFACE ,const GUID *const pguidApplication #endif // ! DPNBUILD_LIBINTERFACE #endif // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_PREALLOCATEDMEMORYMODEL ) { HRESULT hResultCode; IDP8ServiceProvider *pISP; BOOL fAddedToProtocol; #ifndef DPNBUILD_LIBINTERFACE SPISAPPLICATIONSUPPORTEDDATA spAppSupData; #endif // ! DPNBUILD_LIBINTERFACE DNASSERT(pdnObject != NULL); #ifndef DPNBUILD_ONLYONESP DNASSERT(pguid != NULL); #endif // ! DPNBUILD_ONLYONESP m_pdnObject = NULL; #if ((defined(DPNBUILD_ONLYONESP)) && (defined(DPNBUILD_LIBINTERFACE))) m_lRefCount = 0; #else // ! DPNBUILD_ONLYONESP or ! DPNBUILD_LIBINTERFACE m_lRefCount = 1; #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP m_pISP = NULL; m_hProtocolSPHandle = NULL; #ifndef DPNBUILD_ONLYONESP m_bilinkServiceProviders.Initialize(); #endif // ! DPNBUILD_ONLYONESP pISP = NULL; fAddedToProtocol = FALSE; m_pdnObject = pdnObject; // // Instantiate SP // #ifndef DPNBUILD_ONLYONESP if (IsEqualCLSID(*pguid, CLSID_DP8SP_TCPIP)) #endif // ! DPNBUILD_ONLYONESP { hResultCode = CreateIPInterface( #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &pISP ); } #ifndef DPNBUILD_ONLYONESP #ifndef DPNBUILD_NOIPX else if (IsEqualCLSID(*pguid, CLSID_DP8SP_IPX)) { hResultCode = CreateIPXInterface( #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &pISP ); } #endif // ! DPNBUILD_NOIPX #ifndef DPNBUILD_NOSERIALSP else if (IsEqualCLSID(*pguid, CLSID_DP8SP_MODEM)) { hResultCode = CreateModemInterface( #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &pISP ); } else if (IsEqualCLSID(*pguid, CLSID_DP8SP_SERIAL)) { hResultCode = CreateSerialInterface( #ifdef DPNBUILD_PREALLOCATEDMEMORYMODEL pDP8CreateParams, #endif // DPNBUILD_PREALLOCATEDMEMORYMODEL &pISP ); } #endif // ! DPNBUILD_NOSERIALSP else { hResultCode = COM_CoCreateInstance(*pguid, NULL, CLSCTX_INPROC_SERVER, IID_IDP8ServiceProvider, reinterpret_cast(&pISP), FALSE); } #endif // ! DPNBUILD_ONLYONESP if (hResultCode != S_OK) { DPFX(DPFPREP,0,"Could not instantiate SP (err = 0x%lx)!",hResultCode); hResultCode = DPNERR_DOESNOTEXIST; DisplayDNError(0,hResultCode); goto Exit; } // // Add SP to Protocol Layer // #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONESP))) DNProtocolAddRef(pdnObject); #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP //Flags parameter for DNPAddServiceProvider is passed through as the //flags parameter in the SPINITIALIZEDATA structure to the SP //We pass the session type via it DWORD dwFlags; if (pdnObject->dwFlags & DN_OBJECT_FLAG_PEER) dwFlags=SP_SESSION_TYPE_PEER; else if (pdnObject->dwFlags & DN_OBJECT_FLAG_CLIENT) dwFlags=SP_SESSION_TYPE_CLIENT; else { DNASSERT(pdnObject->dwFlags & DN_OBJECT_FLAG_SERVER); dwFlags=SP_SESSION_TYPE_SERVER; } hResultCode = DNPAddServiceProvider(m_pdnObject->pdnProtocolData, pISP, &m_hProtocolSPHandle, dwFlags); if (hResultCode!= DPN_OK) { DPFX(DPFPREP,1,"Could not add service provider to protocol"); DisplayDNError(1,hResultCode); #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONESP))) DNProtocolRelease(pdnObject); #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP goto Failure; } fAddedToProtocol = TRUE; #ifndef DPNBUILD_NOMULTICAST // // If this is a multicast object, make sure the SP in question supports multicasting. // if (pdnObject->dwFlags & DN_OBJECT_FLAG_MULTICAST) { SPGETCAPSDATA spGetCapsData; // // Get the SP caps // memset( &spGetCapsData, 0x00, sizeof( SPGETCAPSDATA ) ); spGetCapsData.dwSize = sizeof( SPGETCAPSDATA ); spGetCapsData.hEndpoint = INVALID_HANDLE_VALUE; if ((hResultCode = IDP8ServiceProvider_GetCaps( pISP, &spGetCapsData )) != DPN_OK) { DPFERR("Could not get SP caps"); DisplayDNError(0,hResultCode); goto Failure; } // // Check for the multicast support flag. // if (! (spGetCapsData.dwFlags & DPNSPCAPS_SUPPORTSMULTICAST)) { DPFX(DPFPREP,1,"Service provider does not support multicasting."); hResultCode = DPNERR_UNSUPPORTED; goto Failure; } } #endif // ! DPNBUILD_NOMULTICAST #ifndef DPNBUILD_LIBINTERFACE // // If an application GUID was given, make sure the SP can be used by that app. // if (pguidApplication != NULL) // app GUID given { spAppSupData.pApplicationGuid = pguidApplication; spAppSupData.dwFlags = 0; if ((hResultCode = IDP8ServiceProvider_IsApplicationSupported(pISP,&spAppSupData)) != DPN_OK) // SP doesn't support app { DPFX(DPFPREP,1,"Service provider does not support app (err = 0x%lx).", hResultCode); hResultCode = DPNERR_UNSUPPORTED; goto Failure; } } #endif // ! DPNBUILD_LIBINTERFACE IDP8ServiceProvider_AddRef(pISP); m_pISP = pISP; IDP8ServiceProvider_Release(pISP); pISP = NULL; #ifndef DPNBUILD_ONLYONESP m_guid = *pguid; /* REMOVE // Add to bilink AddRef(); m_bilink.InsertBefore(&m_pdnObject->m_bilinkServiceProviders); */ #endif // ! DPNBUILD_ONLYONESP hResultCode = DPN_OK; Exit: return(hResultCode); Failure: if (fAddedToProtocol) { // // Ignore failure. // DNPRemoveServiceProvider(pdnObject->pdnProtocolData,m_hProtocolSPHandle); #if ((! defined(DPNBUILD_LIBINTERFACE)) || (! defined(DPNBUILD_ONLYONESP))) DNProtocolRelease(pdnObject); #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP } if (pISP) { IDP8ServiceProvider_Release(pISP); pISP = NULL; } goto Exit; }; #if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONESP))) #undef DPF_MODNAME #define DPF_MODNAME "CServiceProvider::Deinitialize" void CServiceProvider::Deinitialize( void ) #else // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP #undef DPF_MODNAME #define DPF_MODNAME "CServiceProvider::Release" void CServiceProvider::Release( void ) #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP { HRESULT hResultCode; #if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONESP))) DNASSERT(m_lRefCount == 0); #else // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP LONG lRefCount; lRefCount = DNInterlockedDecrement(&m_lRefCount); DPFX(DPFPREP, 9,"[0x%p] new RefCount [%ld]",this,lRefCount); DNASSERT(lRefCount >= 0); if (lRefCount == 0) #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP { #if ((defined(DPNBUILD_LIBINTERFACE)) && (defined(DPNBUILD_ONLYONESP))) hResultCode = DNPRemoveServiceProvider(m_pdnObject->pdnProtocolData,m_hProtocolSPHandle); if (hResultCode != DPN_OK) #else // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP CWorkerJob *pWorkerJob; pWorkerJob = NULL; if ((hResultCode = WorkerJobNew(m_pdnObject,&pWorkerJob)) == DPN_OK) { pWorkerJob->SetJobType( WORKER_JOB_REMOVE_SERVICE_PROVIDER ); DNASSERT( m_hProtocolSPHandle != NULL ); pWorkerJob->SetRemoveServiceProviderHandle( m_hProtocolSPHandle ); DNQueueWorkerJob(m_pdnObject,pWorkerJob); pWorkerJob = NULL; } else #endif // ! DPNBUILD_LIBINTERFACE or ! DPNBUILD_ONLYONESP { DPFERR("Could not remove SP"); DisplayDNError(0,hResultCode); DNASSERT(FALSE); } if (m_pISP) { IDP8ServiceProvider_Release(m_pISP); m_pISP = NULL; } m_pdnObject = NULL; DNFree(this); } } #undef DPF_MODNAME #define DPF_MODNAME "CServiceProvider::GetInterfaceRef" HRESULT CServiceProvider::GetInterfaceRef( IDP8ServiceProvider **ppIDP8SP ) { DNASSERT( ppIDP8SP != NULL ); if (m_pISP == NULL) { return( DPNERR_GENERIC ); } IDP8ServiceProvider_AddRef( m_pISP ); *ppIDP8SP = m_pISP; return( DPN_OK ); }