////////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1999-2002 Microsoft Corporation // // Module Name: // ObjectManager.cpp // // Description: // Object Manager implementation. // // 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( "" ); HRESULT hr = S_OK; IServiceProvider * psp = NULL; CObjectManager * pom = NULL; Assert( ppunkOut != NULL ); if ( ppunkOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // Don't wrap - this can fail with E_POINTER. hr = CServiceManager::S_HrGetManagerPointer( &psp ); if ( hr == E_POINTER ) { // // This happens when the Service Manager is first started. // pom = new CObjectManager(); if ( pom == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } hr = THR( pom->HrInit() ); if ( FAILED( hr ) ) { goto Cleanup; } hr = THR( pom->TypeSafeQI( IUnknown, ppunkOut ) ); if ( FAILED( hr ) ) { goto Cleanup; } } // if: service manager doesn't exists else if ( FAILED( hr ) ) { THR( hr ); goto Cleanup; } else { hr = THR( psp->TypeSafeQS( CLSID_ObjectManager, IUnknown, ppunkOut ) ); psp->Release(); } // else: service manager exists Cleanup: if ( pom != NULL ) { pom->Release(); } HRETURN( hr ); } //*** CObjectManager::S_HrCreateInstance ////////////////////////////////////////////////////////////////////////////// // // CObjectManager::CObjectManager // ////////////////////////////////////////////////////////////////////////////// CObjectManager::CObjectManager( void ) : m_cRef( 1 ) { TraceFunc( "" ); InterlockedIncrement( &g_cObjects ); TraceFuncExit(); } //*** CObjectManager::CObjectManager ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CObjectManager::HrInit // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjectManager::HrInit( void ) { TraceFunc( "" ); HRESULT hr = S_OK; // IUnknown stuff Assert( m_cRef == 1 ); // IObjectManager Assert( m_cAllocSize == 0 ); Assert( m_cCurrentUsed == 0 ); Assert( m_pCookies == NULL ); hr = THR( m_csInstanceGuard.HrInitialized() ); HRETURN( hr ); } //*** CObjectManager::HrInit ////////////////////////////////////////////////////////////////////////////// // // CObjectManager::~CObjectManager // ////////////////////////////////////////////////////////////////////////////// CObjectManager::~CObjectManager( void ) { 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::~CObjectManager // ************************************************************************ // // IUnknown // // ************************************************************************ ////////////////////////////////////////////////////////////////////////////// //++ // // CObjectManager::QueryInterface // // Description: // Query this object for the passed in interface. // // Arguments: // riidIn // Id of interface requested. // // ppvOut // Pointer to the requested interface. // // Return Value: // S_OK // If the interface is available on this object. // // E_NOINTERFACE // If the interface is not available. // // E_POINTER // ppvOut was NULL. // // Remarks: // None. // //-- ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjectManager::QueryInterface( REFIID riidIn , LPVOID * ppvOut ) { TraceQIFunc( riidIn, ppvOut ); HRESULT hr = S_OK; // // Validate arguments. // Assert( ppvOut != NULL ); if ( ppvOut == NULL ) { hr = THR( E_POINTER ); goto Cleanup; } // // Handle known interfaces. // if ( IsEqualIID( riidIn, IID_IUnknown ) ) { *ppvOut = static_cast< LPUNKNOWN >( this ); } // if: IUnknown else if ( IsEqualIID( riidIn, IID_IObjectManager ) ) { *ppvOut = TraceInterface( __THISCLASS__, IObjectManager, this, 0 ); } // else if: IObjectManager else { *ppvOut = NULL; hr = E_NOINTERFACE; } // // Add a reference to the interface if successful. // if ( SUCCEEDED( hr ) ) { ((IUnknown *) *ppvOut)->AddRef(); } // if: success Cleanup: QIRETURN_IGNORESTDMARSHALLING( hr, riidIn ); } //*** CObjectManager::QueryInterface ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP_(ULONG) // CObjectManager::AddRef // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CObjectManager::AddRef( void ) { TraceFunc( "[IUnknown]" ); InterlockedIncrement( &m_cRef ); CRETURN( m_cRef ); } //*** CObjectManager::AddRef ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP_(ULONG) // CObjectManager::Release // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CObjectManager::Release( void ) { TraceFunc( "[IUnknown]" ); LONG cRef; cRef = InterlockedDecrement( &m_cRef ); if ( cRef == 0 ) { TraceDo( delete this ); } CRETURN( cRef ); } //*** CObjectManager::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 = HRESULT_FROM_WIN32( ERROR_OBJECT_NOT_FOUND ); 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. // m_csInstanceGuard.Enter(); 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 == S_OK ); 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; } // if: IID_NULL else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) ) { hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo, reinterpret_cast< void ** >( ppunkOut ) ) ); if ( FAILED( hr ) ) goto Cleanup; } // else if: standard info 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: } // else if: connection info else if ( IsEqualIID( rclsidFormatIn, DFGUID_EnumCookies ) ) { ULONG cIter; // // Create a new cookie enumerator. // pcec = new CEnumCookies; if ( pcec == NULL ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // // Initialize the enumerator. This also causes an AddRef(). // hr = THR( pcec->HrInit() ); 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 ) { // The error text is better than the coding value. hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) ); goto Cleanup; } // // 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 ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } 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 if: enum cookies 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 ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } 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(); } m_csInstanceGuard.Leave(); HRETURN( hr ); } //*** CObjectManager::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 = HRESULT_FROM_WIN32( ERROR_OBJECT_NOT_FOUND ); IUnknown * punk = NULL; IExtendObjectManager * peom = NULL; // // Check parameters // m_csInstanceGuard.Enter(); if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed ) { hr = THR( E_INVALIDARG ); goto Cleanup; } pcsi = m_pCookies[ cookieIn ]; if ( pcsi == NULL ) { hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) ); goto Cleanup; } // // Create the request format object. // if ( IsEqualIID( rclsidFormatIn, IID_NULL ) || ppunkOut == NULL ) { // // No-op. // hr = S_OK; } // if: IID_NULL else if ( IsEqualIID( rclsidFormatIn, DFGUID_StandardInfo ) ) { hr = THR( pcsi->QueryInterface( DFGUID_StandardInfo, reinterpret_cast< void ** >( ppunkOut ) ) ); if ( FAILED( hr ) ) { goto Cleanup; } } // else if: Standard Info 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 if: Connection Info 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 ) { hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) ); goto Cleanup; } // Give up ownership *ppunkOut = punk; punk = NULL; } // else: external? Cleanup: if ( punk != NULL ) { punk->Release(); } if ( peom != NULL ) { peom->Release(); } m_csInstanceGuard.Leave(); HRETURN( hr ); } //*** CObjectManager::GetObject ////////////////////////////////////////////////////////////////////////////// // // STDMETHODIMP // CObjectManager::RemoveObject( // OBJECTCOOKIE cookieIn // ) // ////////////////////////////////////////////////////////////////////////////// STDMETHODIMP CObjectManager::RemoveObject( OBJECTCOOKIE cookieIn ) { TraceFunc( "[IObjectManager]" ); HRESULT hr = S_FALSE; CStandardInfo * pcsi; // // Check parameters // m_csInstanceGuard.Enter(); if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed ) { hr = THR( E_INVALIDARG ); goto Cleanup; } pcsi = m_pCookies[ cookieIn ]; if ( pcsi == NULL ) { hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) ); goto Cleanup; } hr = THR( HrDeleteInstanceAndChildren( cookieIn ) ); if ( FAILED( hr ) ) { goto Cleanup; } Cleanup: m_csInstanceGuard.Leave(); HRETURN( hr ); } //*** CObjectManager::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 // m_csInstanceGuard.Enter(); if ( cookieIn == 0 || cookieIn >= m_cCurrentUsed ) { hr = THR( E_INVALIDARG ); goto Cleanup; } pcsi = m_pCookies[ cookieIn ]; if ( pcsi == NULL ) { hr = HRESULT_FROM_WIN32( TW32( ERROR_NOT_FOUND ) ); goto Cleanup; } // // Update the status. // pcsi->m_hrStatus = hrIn; Cleanup: m_csInstanceGuard.Leave(); HRETURN( hr ); } //*** CObjectManager::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 ); } //*** CObjectManager::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 ); } //*** CObjectManager::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 ); } //*** CObjectManager::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 = S_OK; 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 ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } 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 ) { hr = THR( E_OUTOFMEMORY ); goto Cleanup; } hr = THR( pcsi->HrInit() ); 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 --; hr = THR( E_OUTOFMEMORY ); goto Cleanup; } // 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 ); } //*** CObjectManager::HrCreateNewCookie