/*++ Copyright (C) 1997-1999 Microsoft Corporation Module Name: DATAOBJ.CPP Abstract: Implementation of IDataObject for data communication --*/ #include "StdAfx.h" #include "smlogcfg.h" #include "smnode.h" #include "dataobj.h" // MMC uses these to get necessary information from our snapin about // our nodes. // Register the clipboard formats unsigned int CDataObject::s_cfMmcMachineName = RegisterClipboardFormat(CF_MMC_SNAPIN_MACHINE_NAME); unsigned int CDataObject::s_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME); unsigned int CDataObject::s_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE); unsigned int CDataObject::s_cfSnapinClsid = RegisterClipboardFormat(CCF_SNAPIN_CLASSID); unsigned int CDataObject::s_cfInternal = RegisterClipboardFormat(CF_INTERNAL); #ifdef _DEBUG // For tracking data objects static UINT nCount = 0; WCHAR wszMsg[64]; #endif ///////////////////////////////////////////////////////////////////////////// // CDataObject - This class is used to pass data back and forth with MMC. It // uses a standard interface, IDataObject to acomplish this. // Refer to OLE documentation for a description of clipboard // formats and the IdataObject interface. //--------------------------------------------------------------------------- // Added some code to check on data objects CDataObject::CDataObject() : m_cRefs(0), m_ulCookie(0), m_Context(CCT_UNINITIALIZED), m_CookieType(COOKIE_IS_ROOTNODE) { #ifdef _DEBUG swprintf( wszMsg, L"DATAOBJECT Create %u\n", nCount ); LOCALTRACE( wszMsg ); nCount++; #endif } // end Constructor() //--------------------------------------------------------------------------- // Added some code to check on data objects // CDataObject::~CDataObject() { if ( ( COOKIE_IS_COUNTERMAINNODE == m_CookieType ) || ( COOKIE_IS_TRACEMAINNODE == m_CookieType ) || ( COOKIE_IS_ALERTMAINNODE == m_CookieType ) ) { ASSERT( m_ulCookie ); } #ifdef _DEBUG swprintf( wszMsg, L"DATAOBJECT Delete %u\n", nCount ); LOCALTRACE( wszMsg ); nCount--; #endif } // end Destructor() ///////////////////////////////////////////////////////////////////////////// // IDataObject implementation // //--------------------------------------------------------------------------- // Fill the hGlobal in pmedium with the requested data // STDMETHODIMP CDataObject::GetDataHere ( FORMATETC *pFormatEtc, // [in] Pointer to the FORMATETC structure STGMEDIUM *pMedium // [out] Pointer to the STGMEDIUM structure ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = DV_E_FORMATETC; // Unknown format const CLIPFORMAT cf = pFormatEtc->cfFormat; IStream *pStream = NULL; pMedium->pUnkForRelease = NULL; // by OLE spec do // Write data to the stream based { // of the clipformat hr = CreateStreamOnHGlobal( pMedium->hGlobal, FALSE, &pStream ); if ( FAILED(hr) ) return hr; // Minimal error checking if( cf == s_cfDisplayName ) { hr = WriteDisplayName( pStream ); } else if( cf == s_cfInternal) { hr = WriteInternal (pStream); } else if( cf == s_cfMmcMachineName) { hr = WriteMachineName( pStream ); } else if( cf == s_cfNodeType ) { hr = WriteNodeType( pStream ); } else if( cf == s_cfSnapinClsid ) { hr = WriteClsid( pStream ); } } while( 0 ); pStream->Release(); return hr; } // end GetDataHere() ///////////////////////////////////////////////////////////////////////////// // Support methods // //--------------------------------------------------------------------------- // Write the appropriate GUID to the stream // HRESULT CDataObject::WriteNodeType ( IStream* pStream // [in] Stream we are writing to ) { const GUID *pGuid = NULL; switch( m_CookieType ) { case COOKIE_IS_ROOTNODE: pGuid = &GUID_RootNode; break; case COOKIE_IS_COUNTERMAINNODE: pGuid = &GUID_CounterMainNode; break; case COOKIE_IS_TRACEMAINNODE: pGuid = &GUID_TraceMainNode; break; case COOKIE_IS_ALERTMAINNODE: pGuid = &GUID_AlertMainNode; break; default: ASSERT( FALSE ); return E_UNEXPECTED; } return pStream->Write( (PVOID)pGuid, sizeof(GUID), NULL ); } // end WriteNodeType() //--------------------------------------------------------------------------- // Writes the display name to the stream. This is the name associated // with the root node // HRESULT CDataObject::WriteDisplayName ( IStream* pStream // [in] Stream we are writing to ) { CString strName; ULONG ulSizeofName; ResourceStateManager rsm; if( NULL == m_ulCookie ) { // Add Local vs machine name when implement machine name override/change. // NOTE: For root node, cookie is either NULL or points to a root node object. strName.LoadString( IDS_MMC_DEFAULT_NAME ); } else { PSMNODE pTmp = reinterpret_cast(m_ulCookie); //??? strName = *pTmp->GetDisplayName(); strName = pTmp->GetDisplayName(); } ulSizeofName = strName.GetLength(); ulSizeofName++; // Count null character ulSizeofName *= sizeof(WCHAR); return pStream->Write((LPCWSTR)strName, ulSizeofName, NULL); } // end WriteDisplayName() //--------------------------------------------------------------------------- // Writes the machine name to the stream. // HRESULT CDataObject::WriteMachineName ( IStream* pStream // [in] Stream we are writing to ) { CString strName; ULONG ulSizeOfName; if( NULL == m_ulCookie ) { // Cookie is null if not an extension. In that case, only support // local machine. strName = L""; // local } else { PSMNODE pTmp = reinterpret_cast(m_ulCookie); strName = pTmp->GetMachineName(); } ulSizeOfName = strName.GetLength(); ulSizeOfName++; // Count null character ulSizeOfName *= sizeof(WCHAR); return pStream->Write((LPCWSTR)strName, ulSizeOfName, NULL); } // end WriteMachineName() //--------------------------------------------------------------------------- // Writes a pointer to this data object to the stream // HRESULT CDataObject::WriteInternal ( IStream* pStream // [in] Stream we are writing to ) { CDataObject *pThis = this; return pStream->Write( &pThis, sizeof(CDataObject*), NULL ); } // end WriteInternal //--------------------------------------------------------------------------- // Writes the Class ID to the stream // HRESULT CDataObject::WriteClsid ( IStream* pStream // [in] Stream we are writing to ) { return pStream->Write( &CLSID_ComponentData, sizeof(CLSID_ComponentData), NULL ); } // end WriteClsid() //--------------------------------------------------------------------------- // The cookie is what ever we decide it is going to be. // This is being called from QueryDataObject. Refer to that code. // VOID CDataObject::SetData ( MMC_COOKIE ulCookie, // [in] Unique indentifier DATA_OBJECT_TYPES Context, // [in] Context of the caller COOKIETYPE Type // [in] Type of cookie ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT( NULL == m_ulCookie ); m_ulCookie = ulCookie; m_Context = Context; m_CookieType = Type; } // end SetData() ///////////////////////////////////////////////////////////////////////////// // IUnknown implementation // //--------------------------------------------------------------------------- // Standard implementation // STDMETHODIMP CDataObject::QueryInterface ( REFIID riid, LPVOID *ppvObj ) { HRESULT hr = S_OK; do { if( NULL == ppvObj ) { hr = E_INVALIDARG; break; } if (IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IUnknown *)(IDataObject *)this; } else if (IsEqualIID(riid, IID_IDataObject)) { *ppvObj = (IUnknown *)(IDataObject *)this; } else { hr = E_NOINTERFACE; *ppvObj = NULL; break; } // If we got this far we are handing out a new interface pointer on // this object, so addref it. AddRef(); } while (0); return hr; } // end QueryInterface() //--------------------------------------------------------------------------- // Standard implementation // STDMETHODIMP_(ULONG) CDataObject::AddRef() { return InterlockedIncrement((LONG*) &m_cRefs); } //--------------------------------------------------------------------------- // Standard implementation // STDMETHODIMP_(ULONG) CDataObject::Release() { ULONG cRefsTemp; cRefsTemp = InterlockedDecrement((LONG *)&m_cRefs); if( 0 == cRefsTemp ) { delete this; } return cRefsTemp; } // end Release()