1218 lines
29 KiB
C++
1218 lines
29 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// ObjectManager.cpp
|
|
//
|
|
// Description:
|
|
// Object Manager implementation.
|
|
//
|
|
// Documentation:
|
|
// Yes.
|
|
//
|
|
// Maintained By:
|
|
// Galen Barbee (GalenB) 22-NOV-1999
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pch.h"
|
|
#include "ObjectManager.h"
|
|
#include "ConnectionInfo.h"
|
|
#include "StandardInfo.h"
|
|
#include "EnumCookies.h"
|
|
|
|
DEFINE_THISCLASS("CObjectManager")
|
|
|
|
#define COOKIE_BUFFER_GROW_SIZE 100
|
|
|
|
// ************************************************************************
|
|
//
|
|
// Constructor / Destructor
|
|
//
|
|
// ************************************************************************
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LPUNKNOWN
|
|
// CObjectManager::S_HrCreateInstance(
|
|
// IUnknown ** ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CObjectManager::S_HrCreateInstance(
|
|
IUnknown ** ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( ppunkOut != NULL );
|
|
|
|
HRESULT hr;
|
|
IServiceProvider * psp;
|
|
|
|
// Don't wrap - this can fail with E_POINTER.
|
|
hr = CServiceManager::S_HrGetManagerPointer( &psp );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = THR( psp->TypeSafeQS( CLSID_ObjectManager,
|
|
IUnknown,
|
|
ppunkOut
|
|
) );
|
|
psp->Release( );
|
|
|
|
} // if: service manager
|
|
else if ( hr == E_POINTER )
|
|
{
|
|
//
|
|
// This happens when the Service Manager is first started.
|
|
//
|
|
CObjectManager * pom = new CObjectManager( );
|
|
if ( pom != NULL )
|
|
{
|
|
hr = THR( pom->Init( ) );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = THR( pom->TypeSafeQI( IUnknown, ppunkOut ) );
|
|
} // if: success
|
|
|
|
pom->Release( );
|
|
|
|
} // if: got object
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
} // if: service manager doesn't exists
|
|
else
|
|
{
|
|
THR( hr );
|
|
} // else:
|
|
|
|
HRETURN( hr );
|
|
|
|
} // S_HrCreateInstance( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CObjectManager::CObjectManager( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CObjectManager::CObjectManager( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
InterlockedIncrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
} // CObjectManager( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::Init( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::Init( void )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// IUnknown stuff
|
|
Assert( m_cRef == 0 );
|
|
AddRef( ); // Add one count
|
|
|
|
// IObjectManager
|
|
Assert( m_cAllocSize == 0 );
|
|
Assert( m_cCurrentUsed == 0 );
|
|
Assert( m_pCookies == NULL );
|
|
|
|
HRETURN( hr );
|
|
|
|
} // Init( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CObjectManager::~CObjectManager( )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CObjectManager::~CObjectManager( )
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
if ( m_pCookies != NULL )
|
|
{
|
|
while ( m_cCurrentUsed != 0 )
|
|
{
|
|
m_cCurrentUsed --;
|
|
|
|
if ( m_pCookies[ m_cCurrentUsed ] != NULL )
|
|
{
|
|
m_pCookies[ m_cCurrentUsed ]->Release( );
|
|
}
|
|
}
|
|
|
|
TraceFree( m_pCookies );
|
|
}
|
|
|
|
InterlockedDecrement( &g_cObjects );
|
|
|
|
TraceFuncExit();
|
|
} // ~CObjectManager( )
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::QueryInterface(
|
|
// REFIID riid,
|
|
// LPVOID *ppv
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppv
|
|
)
|
|
{
|
|
TraceQIFunc( riid, ppv );
|
|
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if ( IsEqualIID( riid, IID_IUnknown ) )
|
|
{
|
|
*ppv = static_cast< LPUNKNOWN >( this );
|
|
hr = S_OK;
|
|
} // if: IUnknown
|
|
else if ( IsEqualIID( riid, IID_IObjectManager ) )
|
|
{
|
|
*ppv = TraceInterface( __THISCLASS__, IObjectManager, this, 0 );
|
|
hr = S_OK;
|
|
} // else if: IObjectManager
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
((IUnknown*) *ppv)->AddRef( );
|
|
} // if: success
|
|
|
|
QIRETURN_IGNORESTDMARSHALLING( hr, riid );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_(ULONG)
|
|
// CObjectManager::AddRef( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG)
|
|
CObjectManager::AddRef( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedIncrement( &m_cRef );
|
|
|
|
RETURN( m_cRef );
|
|
|
|
} // AddRef( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP_(ULONG)
|
|
// CObjectManager::Release( void )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP_(ULONG)
|
|
CObjectManager::Release( void )
|
|
{
|
|
TraceFunc( "[IUnknown]" );
|
|
|
|
InterlockedDecrement( &m_cRef );
|
|
|
|
if ( m_cRef )
|
|
RETURN( m_cRef );
|
|
|
|
TraceDo( delete this );
|
|
|
|
RETURN(0);
|
|
|
|
} // Release( )
|
|
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IObjectManager
|
|
//
|
|
// ************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::FindObject(
|
|
// REFCLSID rclsidTypeIn,
|
|
// OBJECTCOOKIE cookieParentIn,
|
|
// LPCWSTR pcszNameIn,
|
|
// REFCLSID rclsidFormatIn,
|
|
// OBJECTCOOKIE * cookieOut,
|
|
// LPUNKNOWN * punkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::FindObject(
|
|
REFCLSID rclsidTypeIn,
|
|
OBJECTCOOKIE cookieParentIn,
|
|
LPCWSTR pcszNameIn,
|
|
REFCLSID rclsidFormatIn,
|
|
OBJECTCOOKIE * pcookieOut,
|
|
LPUNKNOWN * ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "[IObjectManager]" );
|
|
|
|
ExtObjectEntry * pentry;
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
OBJECTCOOKIE cookie = 0;
|
|
|
|
CStandardInfo * pcsi = NULL; // don't free
|
|
|
|
BOOL fTempCookie = FALSE;
|
|
|
|
CEnumCookies * pcec = NULL;
|
|
IUnknown * punk = NULL;
|
|
IExtendObjectManager * peom = NULL;
|
|
|
|
//
|
|
// Check to see if we already have an object.
|
|
//
|
|
|
|
if ( pcszNameIn != NULL )
|
|
{
|
|
hr = STHR( HrSearchForExistingCookie( rclsidTypeIn, cookieParentIn, pcszNameIn, &cookie ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
if ( hr == S_FALSE )
|
|
{
|
|
hr = THR( HrCreateNewCookie( rclsidTypeIn, cookieParentIn, pcszNameIn, &cookie ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
pcsi = m_pCookies[ cookie ];
|
|
Assert( pcsi != NULL );
|
|
}
|
|
else if ( hr == S_OK )
|
|
{
|
|
//
|
|
// Found an existing cookie.
|
|
//
|
|
|
|
if ( pcookieOut != NULL )
|
|
{
|
|
*pcookieOut = cookie;
|
|
}
|
|
|
|
if ( ppunkOut != NULL )
|
|
{
|
|
pcsi = m_pCookies[ cookie ];
|
|
|
|
//
|
|
// Is the object still in an failed state or still pending?
|
|
//
|
|
|
|
if ( FAILED( pcsi->m_hrStatus ) )
|
|
{
|
|
hr = pcsi->m_hrStatus;
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Retrieve the requested format.
|
|
//
|
|
|
|
hr = THR( GetObject( rclsidFormatIn, cookie, ppunkOut ) );
|
|
// we always jump to cleanup. No need to check hr here.
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Unexpected error_success - now what?
|
|
//
|
|
Assert( !hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
} // if: named object
|
|
else
|
|
{
|
|
Assert( pcsi == NULL );
|
|
}
|
|
|
|
//
|
|
// Create a new object.
|
|
//
|
|
|
|
if ( IsEqualIID( rclsidFormatIn, IID_NULL )
|
|
|| ppunkOut == NULL
|
|
)
|
|
{
|
|
//
|
|
// No-op.
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) )
|
|
{
|
|
hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
else if ( IsEqualIID( rclsidFormatIn, DFGUID_ConnectionInfoFormat ) )
|
|
{
|
|
if ( pcsi->m_pci != NULL )
|
|
{
|
|
*ppunkOut = TraceInterface( L"CConnectionInfo!ObjectManager", IConnectionInfo, pcsi->m_pci, 0 );
|
|
(*ppunkOut)->AddRef( );
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = THR( CConnectionInfo::S_HrCreateInstance( &punk,
|
|
pcsi->m_cookieParent
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IConnectionInfo,
|
|
&pcsi->m_pci
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->QueryInterface( IID_IConnectionInfo,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else if ( IsEqualIID( rclsidFormatIn, DFGUID_EnumCookies ) )
|
|
{
|
|
ULONG cIter;
|
|
|
|
//
|
|
// Create a new cookie enumerator.
|
|
//
|
|
|
|
pcec = new CEnumCookies;
|
|
if ( pcec == NULL )
|
|
goto OutOfMemory;
|
|
|
|
//
|
|
// Initialize the enumerator. This also cause an AddRef( ).
|
|
//
|
|
|
|
hr = THR( pcec->Init( ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
//
|
|
// See who matches our citeria.
|
|
//
|
|
|
|
pcec->m_cIter = 0;
|
|
|
|
for( cIter = 1; cIter < m_cCurrentUsed; cIter ++ )
|
|
{
|
|
pcsi = m_pCookies[ cIter ];
|
|
|
|
if ( pcsi != NULL )
|
|
{
|
|
if ( rclsidTypeIn == IID_NULL
|
|
|| pcsi->m_clsidType == rclsidTypeIn
|
|
)
|
|
{
|
|
if ( cookieParentIn == NULL
|
|
|| pcsi->m_cookieParent == cookieParentIn
|
|
)
|
|
{
|
|
if ( ( pcszNameIn == NULL )
|
|
|| ( ( pcsi->m_bstrName != NULL )
|
|
&& ( StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 )
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// Match!
|
|
//
|
|
pcec->m_cIter ++;
|
|
|
|
} // if: names match
|
|
|
|
} // if: parents match
|
|
|
|
} // if: match parent and type
|
|
|
|
} // if: valid element
|
|
|
|
} // for: cIter
|
|
|
|
if ( pcec->m_cIter == 0 )
|
|
goto ErrorNotFound;
|
|
|
|
//
|
|
// Alloc an array to hold the cookies.
|
|
//
|
|
|
|
pcec->m_pList = (OBJECTCOOKIE*) TraceAlloc( HEAP_ZERO_MEMORY, pcec->m_cIter * sizeof(OBJECTCOOKIE) );
|
|
if ( pcec->m_pList == NULL )
|
|
goto OutOfMemory;
|
|
|
|
pcec->m_cAlloced = pcec->m_cIter;
|
|
pcec->m_cIter = 0;
|
|
|
|
for( cIter = 1; cIter < m_cCurrentUsed; cIter ++ )
|
|
{
|
|
pcsi = m_pCookies[ cIter ];
|
|
|
|
if ( pcsi != NULL )
|
|
{
|
|
if ( rclsidTypeIn == IID_NULL
|
|
|| pcsi->m_clsidType == rclsidTypeIn
|
|
)
|
|
{
|
|
if ( cookieParentIn == NULL
|
|
|| pcsi->m_cookieParent == cookieParentIn
|
|
)
|
|
{
|
|
if ( ( pcszNameIn == NULL )
|
|
|| ( ( pcsi->m_bstrName != NULL )
|
|
&& ( StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 )
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// Match!
|
|
//
|
|
|
|
pcec->m_pList[ pcec->m_cIter ] = cIter;
|
|
|
|
pcec->m_cIter ++;
|
|
|
|
} // if: names match
|
|
|
|
} // if: parents match
|
|
|
|
} // if: match parent and type
|
|
|
|
} // if: valid element
|
|
|
|
} // for: cIter
|
|
|
|
Assert( pcec->m_cIter != 0 );
|
|
pcec->m_cCookies = pcec->m_cIter;
|
|
pcec->m_cIter = 0;
|
|
|
|
//
|
|
// Grab the inteface on the way out.
|
|
//
|
|
|
|
hr = THR( pcec->QueryInterface( IID_IEnumCookies,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check for extension formats.
|
|
//
|
|
|
|
//
|
|
// See if the format already exists for this cookie.
|
|
//
|
|
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release( );
|
|
punk = NULL;
|
|
}
|
|
|
|
if ( pcsi != NULL )
|
|
{
|
|
for( pentry = pcsi->m_pExtObjList; pentry != NULL; pentry = pentry->pNext )
|
|
{
|
|
if ( pentry->iid == rclsidFormatIn )
|
|
{
|
|
hr = THR( pentry->punk->QueryInterface( rclsidFormatIn,
|
|
reinterpret_cast< void ** >( &punk )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
break; // exit loop
|
|
}
|
|
|
|
} // for: pentry
|
|
|
|
} // if: have cookie
|
|
else
|
|
{
|
|
//
|
|
// Create a temporary cookie.
|
|
//
|
|
|
|
Assert( pcszNameIn == NULL );
|
|
|
|
hr = THR( HrCreateNewCookie( IID_NULL, cookieParentIn, NULL, &cookie ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
fTempCookie = TRUE;
|
|
|
|
Assert( pcsi == NULL );
|
|
|
|
} // else: need a temporary cookie
|
|
|
|
if ( punk == NULL )
|
|
{
|
|
//
|
|
// Possibly a new or externally object, try creating it and querying.
|
|
//
|
|
|
|
hr = THR( HrCoCreateInternalInstance( rclsidFormatIn,
|
|
NULL,
|
|
CLSCTX_ALL,
|
|
TypeSafeParams( IExtendObjectManager, &peom )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
Assert( punk == NULL );
|
|
// Can't wrap with THR because it can return E_PENDING.
|
|
hr = peom->FindObject( cookie,
|
|
rclsidTypeIn,
|
|
pcszNameIn,
|
|
&punk
|
|
);
|
|
if ( hr == E_PENDING )
|
|
{
|
|
// ignore
|
|
}
|
|
else if ( FAILED( hr ) )
|
|
{
|
|
THR( hr );
|
|
goto Cleanup;
|
|
}
|
|
|
|
if ( fTempCookie )
|
|
{
|
|
(m_pCookies[ cookie ])->Release( );
|
|
m_pCookies[ cookie ] = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Keep track of the format (if extension wants)
|
|
//
|
|
|
|
if ( ( ( SUCCEEDED( hr )
|
|
&& hr != S_FALSE
|
|
)
|
|
|| hr == E_PENDING
|
|
)
|
|
&& punk != NULL
|
|
&& pcsi != NULL
|
|
)
|
|
{
|
|
pentry = (ExtObjectEntry *) TraceAlloc( 0, sizeof(ExtObjectEntry) );
|
|
if ( pentry == NULL )
|
|
goto OutOfMemory;
|
|
|
|
pentry->iid = rclsidFormatIn;
|
|
pentry->pNext = pcsi->m_pExtObjList;
|
|
pentry->punk = punk;
|
|
pentry->punk->AddRef( );
|
|
|
|
pcsi->m_pExtObjList = pentry; // update header of list (LIFO)
|
|
pcsi->m_hrStatus = hr; // update status
|
|
}
|
|
|
|
} // else: persistent cookie
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Give up ownership
|
|
*ppunkOut = punk;
|
|
punk = NULL;
|
|
}
|
|
|
|
} // if: creating new object
|
|
|
|
} // else: possible extension format
|
|
|
|
//
|
|
// Save stuff for the caller.
|
|
//
|
|
|
|
if ( pcookieOut != NULL )
|
|
{
|
|
*pcookieOut = cookie;
|
|
}
|
|
|
|
Cleanup:
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release( );
|
|
}
|
|
if ( peom != NULL )
|
|
{
|
|
peom->Release( );
|
|
}
|
|
if ( pcec != NULL )
|
|
{
|
|
pcec->Release( );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
OutOfMemory:
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
|
|
ErrorNotFound:
|
|
// The error text is better than the coding value.
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
|
|
goto Cleanup;
|
|
|
|
} // FindObject( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::GetObject(
|
|
// REFCLSID rclsidFormatIn,
|
|
// OBJECTCOOKIE cookieIn,
|
|
// LPUNKNOWN * ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::GetObject(
|
|
REFCLSID rclsidFormatIn,
|
|
OBJECTCOOKIE cookieIn,
|
|
LPUNKNOWN * ppunkOut
|
|
)
|
|
{
|
|
TraceFunc( "[IObjectManager]" );
|
|
|
|
CStandardInfo * pcsi;
|
|
ExtObjectEntry * pentry;
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
IUnknown * punk = NULL;
|
|
IExtendObjectManager * peom = NULL;
|
|
|
|
//
|
|
// Check parameters
|
|
//
|
|
if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
|
|
goto InvalidArg;
|
|
|
|
pcsi = m_pCookies[ cookieIn ];
|
|
if ( pcsi == NULL )
|
|
goto ErrorNotFound;
|
|
|
|
//
|
|
// Create the request format object.
|
|
//
|
|
|
|
if ( IsEqualIID( rclsidFormatIn, IID_NULL )
|
|
|| ppunkOut == NULL
|
|
)
|
|
{
|
|
//
|
|
// No-op.
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) )
|
|
{
|
|
hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
else if ( IsEqualIID( rclsidFormatIn, DFGUID_ConnectionInfoFormat ) )
|
|
{
|
|
if ( pcsi->m_pci != NULL )
|
|
{
|
|
*ppunkOut = pcsi->m_pci;
|
|
(*ppunkOut)->AddRef( );
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = THR( CConnectionInfo::S_HrCreateInstance( &punk,
|
|
pcsi->m_cookieParent
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->TypeSafeQI( IConnectionInfo,
|
|
&pcsi->m_pci
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
hr = THR( punk->QueryInterface( IID_IConnectionInfo,
|
|
reinterpret_cast< void ** >( ppunkOut )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// See if the format already exists for this cookie.
|
|
//
|
|
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release( );
|
|
punk = NULL;
|
|
}
|
|
|
|
for( pentry = pcsi->m_pExtObjList; pentry != NULL; pentry = pentry->pNext )
|
|
{
|
|
if ( pentry->iid == rclsidFormatIn )
|
|
{
|
|
hr = THR( pentry->punk->QueryInterface( rclsidFormatIn,
|
|
reinterpret_cast< void ** >( &punk )
|
|
) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
break; // exit loop
|
|
}
|
|
|
|
} // for: pentry
|
|
|
|
if ( punk == NULL )
|
|
goto ErrorNotFound;
|
|
|
|
// Give up ownership
|
|
*ppunkOut = punk;
|
|
punk = NULL;
|
|
|
|
} // else: external?
|
|
|
|
Cleanup:
|
|
if ( punk != NULL )
|
|
{
|
|
punk->Release( );
|
|
}
|
|
if ( peom != NULL )
|
|
{
|
|
peom->Release( );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
InvalidArg:
|
|
hr = THR( E_INVALIDARG );
|
|
goto Cleanup;
|
|
|
|
ErrorNotFound:
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
|
|
goto Cleanup;
|
|
#if 0
|
|
OutOfMemory:
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
#endif
|
|
|
|
} // GetObject( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::RemoveObject(
|
|
// OBJECTCOOKIE cookieIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::RemoveObject(
|
|
OBJECTCOOKIE cookieIn
|
|
)
|
|
{
|
|
TraceFunc( "[IObjectManager]" );
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
CStandardInfo * pcsi;
|
|
|
|
BOOL fLocked = FALSE;
|
|
|
|
//
|
|
// Check parameters
|
|
//
|
|
if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
|
|
goto InvalidArg;
|
|
|
|
pcsi = m_pCookies[ cookieIn ];
|
|
if ( pcsi == NULL )
|
|
goto ErrorNotFound;
|
|
|
|
hr = THR( HrDeleteInstanceAndChildren( cookieIn ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
|
|
InvalidArg:
|
|
hr = THR( E_INVALIDARG );
|
|
goto Cleanup;
|
|
|
|
ErrorNotFound:
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
|
|
goto Cleanup;
|
|
|
|
} // RemoveObject( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// STDMETHODIMP
|
|
// CObjectManager::SetObjectStatus(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// HRESULT hrIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP
|
|
CObjectManager::SetObjectStatus(
|
|
OBJECTCOOKIE cookieIn,
|
|
HRESULT hrIn
|
|
)
|
|
{
|
|
TraceFunc( "[IObjectManager]" );
|
|
|
|
HRESULT hr = S_OK;
|
|
CStandardInfo * pcsi;
|
|
|
|
//
|
|
// Check parameters
|
|
//
|
|
|
|
if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed )
|
|
goto InvalidArg;
|
|
|
|
pcsi = m_pCookies[ cookieIn ];
|
|
if ( pcsi == NULL )
|
|
goto ErrorNotFound;
|
|
|
|
//
|
|
// Update the status.
|
|
//
|
|
|
|
pcsi->m_hrStatus = hrIn;
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
|
|
InvalidArg:
|
|
hr = THR( E_INVALIDARG );
|
|
goto Cleanup;
|
|
|
|
ErrorNotFound:
|
|
hr = THR( HRESULT_FROM_WIN32( ERROR_NOT_FOUND ) );
|
|
goto Cleanup;
|
|
|
|
} // SetObjectStatus( )
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// Privates
|
|
//
|
|
//****************************************************************************
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CObjectManager::HrDeleteCookie(
|
|
// OBJECTCOOKIE cookieIn
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CObjectManager::HrDeleteCookie(
|
|
OBJECTCOOKIE cookieIn
|
|
)
|
|
{
|
|
TraceFunc1( "cookieIn = %#X", cookieIn );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
CStandardInfo * pcsi;
|
|
|
|
Assert( cookieIn != 0 && cookieIn < m_cCurrentUsed );
|
|
|
|
pcsi = m_pCookies[ cookieIn ];
|
|
Assert( pcsi != NULL );
|
|
pcsi->Release( );
|
|
m_pCookies[ cookieIn ] = NULL;
|
|
|
|
HRETURN( hr );
|
|
|
|
} // HrDeleteCookie( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CObjectManager::HrSearchForExistingCookie(
|
|
// OBJECTCOOKIE cookieIn,
|
|
// LPUNKNOWN ppunkOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CObjectManager::HrSearchForExistingCookie(
|
|
REFCLSID rclsidTypeIn,
|
|
OBJECTCOOKIE cookieParentIn,
|
|
LPCWSTR pcszNameIn,
|
|
OBJECTCOOKIE * pcookieOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
Assert( pcszNameIn != NULL );
|
|
Assert( pcookieOut != NULL );
|
|
|
|
HRESULT hr = S_FALSE;
|
|
ULONG idx;
|
|
|
|
CStandardInfo * pcsi;
|
|
|
|
//
|
|
// Search the list.
|
|
//
|
|
for( idx = 1; idx < m_cCurrentUsed; idx ++ )
|
|
{
|
|
pcsi = m_pCookies[ idx ];
|
|
|
|
if ( pcsi != NULL )
|
|
{
|
|
if ( pcsi->m_cookieParent == cookieParentIn // matching parents
|
|
&& IsEqualIID( pcsi->m_clsidType, rclsidTypeIn ) // matching types
|
|
&& StrCmpI( pcsi->m_bstrName, pcszNameIn ) == 0 // matching names
|
|
)
|
|
{
|
|
//
|
|
// Found a match.
|
|
//
|
|
|
|
*pcookieOut = idx;
|
|
hr = S_OK;
|
|
|
|
break; // exit loop
|
|
|
|
} // if: match
|
|
|
|
} // if: cookie exists
|
|
|
|
} // while: pcsi
|
|
|
|
HRETURN( hr );
|
|
|
|
} // HrSearchForExistingCookie( )
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CObjectManager::HrDeleteInstanceAndChildren(
|
|
// OBJECTCOOKIE pcsiIn
|
|
// )
|
|
//
|
|
// Notes:
|
|
// This should be called while the ListLock is held!
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CObjectManager::HrDeleteInstanceAndChildren(
|
|
OBJECTCOOKIE cookieIn
|
|
)
|
|
{
|
|
TraceFunc1( "cookieIn = %#X", cookieIn );
|
|
|
|
ULONG idx;
|
|
CStandardInfo * pcsi;
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = THR( HrDeleteCookie( cookieIn ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
for ( idx = 1; idx < m_cCurrentUsed; idx ++ )
|
|
{
|
|
pcsi = m_pCookies[ idx ];
|
|
|
|
if ( pcsi != NULL
|
|
&& pcsi->m_cookieParent == cookieIn )
|
|
{
|
|
hr = THR( HrDeleteInstanceAndChildren( idx ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
} // if:
|
|
|
|
} // while:
|
|
|
|
Cleanup:
|
|
HRETURN( hr );
|
|
|
|
} // HrDeleteInstanceAndChildren( )
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// HRESULT
|
|
// CObjectManager::HrCreateNewCookie(
|
|
// REFCLSID rclsidTypeIn
|
|
// OBJECTCOOKIE cookieParentIn,
|
|
// BSTR pcszNameIn,
|
|
// OBJECTCOOKIE * pcookieOut
|
|
// )
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CObjectManager::HrCreateNewCookie(
|
|
REFCLSID rclsidTypeIn,
|
|
OBJECTCOOKIE cookieParentIn,
|
|
LPCWSTR pcszNameIn,
|
|
OBJECTCOOKIE * pcookieOut
|
|
)
|
|
{
|
|
TraceFunc( "" );
|
|
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
CStandardInfo * pcsi = NULL;
|
|
|
|
Assert( pcookieOut != NULL );
|
|
|
|
*pcookieOut = 0;
|
|
|
|
//
|
|
// Create some space for it.
|
|
//
|
|
|
|
if ( m_cCurrentUsed == m_cAllocSize )
|
|
{
|
|
CStandardInfo ** pnew = (CStandardInfo **) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(CStandardInfo *) * ( m_cAllocSize + COOKIE_BUFFER_GROW_SIZE ) );
|
|
if ( pnew == NULL )
|
|
goto OutOfMemory;
|
|
|
|
if ( m_pCookies != NULL )
|
|
{
|
|
CopyMemory( pnew, m_pCookies, sizeof(CStandardInfo *) * m_cCurrentUsed );
|
|
TraceFree( m_pCookies );
|
|
}
|
|
|
|
m_pCookies = pnew;
|
|
|
|
m_cAllocSize += COOKIE_BUFFER_GROW_SIZE;
|
|
|
|
if ( m_cCurrentUsed == 0 )
|
|
{
|
|
//
|
|
// Always skip zero.
|
|
//
|
|
m_cCurrentUsed = 1;
|
|
}
|
|
}
|
|
|
|
pcsi = new CStandardInfo( );
|
|
if ( pcsi == NULL )
|
|
goto OutOfMemory;
|
|
|
|
hr = THR( pcsi->Init( ) );
|
|
if ( FAILED( hr ) )
|
|
goto Cleanup;
|
|
|
|
m_pCookies[ m_cCurrentUsed ] = pcsi;
|
|
|
|
//
|
|
// Initialize the rest of the structure.
|
|
//
|
|
|
|
pcsi->m_cookieParent = cookieParentIn;
|
|
pcsi->m_hrStatus = E_PENDING;
|
|
|
|
CopyMemory( &pcsi->m_clsidType, &rclsidTypeIn, sizeof( pcsi->m_clsidType ) );
|
|
|
|
if ( pcszNameIn != NULL )
|
|
{
|
|
pcsi->m_bstrName = TraceSysAllocString( pcszNameIn );
|
|
if ( pcsi->m_bstrName == NULL )
|
|
{
|
|
m_cCurrentUsed --;
|
|
goto OutOfMemory;
|
|
} // if: out of memory
|
|
}
|
|
|
|
Assert( pcsi->m_pci == NULL );
|
|
Assert( pcsi->m_pExtObjList == NULL );
|
|
|
|
//
|
|
// Keep it around and return SUCCESS!
|
|
//
|
|
|
|
pcsi = NULL;
|
|
*pcookieOut = m_cCurrentUsed;
|
|
m_cCurrentUsed ++;
|
|
hr = S_OK;
|
|
|
|
Cleanup:
|
|
if ( pcsi != NULL )
|
|
{
|
|
pcsi->Release( );
|
|
}
|
|
|
|
HRETURN( hr );
|
|
|
|
OutOfMemory:
|
|
hr = E_OUTOFMEMORY;
|
|
goto Cleanup;
|
|
|
|
} // HrCreateNewCookie( )
|