// DataObj.cpp : Implementation of data object classes #include "stdafx.h" #include "stdutils.h" // GetObjectType() utility routines #include "macros.h" USE_HANDLE_MACROS("MYCOMPUT(dataobj.cpp)") #include "dataobj.h" #include "compdata.h" #include "resource.h" // IDS_SCOPE_MYCOMPUTER #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "stddtobj.cpp" #ifdef __DAN_MORIN_HARDCODED_CONTEXT_MENU_EXTENSION__ // Additional clipboard formats for the Service context menu extension CLIPFORMAT g_cfServiceName = (CLIPFORMAT)::RegisterClipboardFormat(L"FILEMGMT_SNAPIN_SERVICE_NAME"); CLIPFORMAT g_cfServiceDisplayName = (CLIPFORMAT)::RegisterClipboardFormat(L"FILEMGMT_SNAPIN_SERVICE_DISPLAYNAME"); #endif // __DAN_MORIN_HARDCODED_CONTEXT_MENU_EXTENSION__ // Additional clipboard formats for the Send Console Message snapin //CLIPFORMAT CMyComputerDataObject::m_cfSendConsoleMessageText = (CLIPFORMAT)::RegisterClipboardFormat(_T("mmc.sendcmsg.MessageText")); CLIPFORMAT CMyComputerDataObject::m_cfSendConsoleMessageRecipients = (CLIPFORMAT)::RegisterClipboardFormat(_T("mmc.sendcmsg.MessageRecipients")); ///////////////////////////////////////////////////////////////////// // CMyComputerDataObject::IDataObject::GetDataHere() HRESULT CMyComputerDataObject::GetDataHere( FORMATETC __RPC_FAR *pFormatEtcIn, STGMEDIUM __RPC_FAR *pMedium) { MFC_TRY; // ISSUE-2002/02/27-JonN test for NULL pointers const CLIPFORMAT cf=pFormatEtcIn->cfFormat; if (cf == m_CFNodeType) { const GUID* pguid = GetObjectTypeGUID( m_pcookie->m_objecttype ); stream_ptr s(pMedium); return s.Write(pguid, sizeof(GUID)); } else if (cf == m_CFSnapInCLSID) { const GUID* pguid = &CLSID_MyComputer; stream_ptr s(pMedium); return s.Write(pguid, sizeof(GUID)); } else if (cf == m_CFNodeTypeString) { const BSTR strGUID = GetObjectTypeString( m_pcookie->m_objecttype ); stream_ptr s(pMedium); return s.Write(strGUID); } else if (cf == m_CFDisplayName) { return PutDisplayName(pMedium); } else if (cf == m_CFDataObjectType) { stream_ptr s(pMedium); return s.Write(&m_dataobjecttype, sizeof(m_dataobjecttype)); } else if (cf == m_CFMachineName) { stream_ptr s(pMedium); LPCWSTR pszMachineName = m_pcookie->QueryNonNULLMachineName(); if (IsBadStringPtr(pszMachineName,(UINT_PTR)-1)) // JonN 2/6/02 Security Push { ASSERT(FALSE); return E_FAIL; } if ( !wcsncmp (pszMachineName, L"\\\\", 2) ) pszMachineName += 2; // skip whackwhack return s.Write(pszMachineName); } else if (cf == m_CFRawCookie) { stream_ptr s(pMedium); // CODEWORK This cast ensures that the data format is // always a CCookie*, even for derived subclasses CCookie* pcookie = (CCookie*)m_pcookie; return s.Write(reinterpret_cast(&pcookie), sizeof(m_pcookie)); } else if (cf == m_CFSnapinPreloads) { stream_ptr s(pMedium); // If this is TRUE, then the next time this snapin is loaded, it will // be preloaded to give us the opportunity to change the root node // name before the user sees it. return s.Write (reinterpret_cast(&m_fAllowOverrideMachineName), sizeof (BOOL)); } return DV_E_FORMATETC; MFC_CATCH; } // CMyComputerDataObject::GetDataHere() ///////////////////////////////////////////////////////////////////// // CMyComputerDataObject::IDataObject::GetData() // // Write data into the storage medium. // The data will be retrieved by the Send Console Message snapin. // // HISTORY // 12-Aug-97 t-danm Creation. // HRESULT CMyComputerDataObject::GetData( FORMATETC __RPC_FAR * pFormatEtcIn, STGMEDIUM __RPC_FAR * pMedium) { // ISSUE-2002-02-27-JonN Should use MFC_TRY/MFC_CATCH // JonN 2/20/02 Security Push if (NULL == pFormatEtcIn || NULL == pMedium) { ASSERT(FALSE); return E_POINTER; } HRESULT hr = S_OK; const CLIPFORMAT cf = pFormatEtcIn->cfFormat; if (cf == m_cfSendConsoleMessageRecipients) { // // Write the list of recipients to the storage medium. // - The list of recipients is a group of UNICODE strings // terminated by TWO null characters.c // - Allocated memory must include BOTH null characters. // ASSERT (m_pcookie); if ( m_pcookie ) { CString computerName = m_pcookie->QueryNonNULLMachineName (); if ( computerName.IsEmpty () ) { DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1 ; VERIFY (::GetComputerName ( computerName.GetBufferSetLength (dwSize), &dwSize)); computerName.ReleaseBuffer (); } size_t cch = computerName.GetLength () + 2; HGLOBAL hGlobal = ::GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, cch * sizeof (WCHAR)); if ( hGlobal ) { // JonN 2/6/02 Security Push: memcpy -> StringCchCopy // this should leave two NULLS StringCchCopyW ((LPWSTR)hGlobal, cch, (LPCWSTR)computerName); pMedium->hGlobal = hGlobal; return S_OK; } else return E_OUTOFMEMORY; } else return E_UNEXPECTED; } else if (cf == m_CFNodeID2) { const LPCTSTR strGUID = GetObjectTypeString( m_pcookie->m_objecttype ); // JonN 12/11/01 502856 int cbString = (lstrlen(strGUID) + 1) * sizeof(TCHAR); pMedium->tymed = TYMED_HGLOBAL; pMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(SNodeID2) + cbString); if (!(pMedium->hGlobal)) { hr = E_OUTOFMEMORY; } else { SNodeID2 *pNodeID = (SNodeID2 *)GlobalLock(pMedium->hGlobal); if (!pNodeID) { hr = HRESULT_FROM_WIN32(GetLastError()); GlobalFree(pMedium->hGlobal); pMedium->hGlobal = NULL; } else { pNodeID->dwFlags = 0; pNodeID->cBytes = cbString; // JonN 2/6/02 Security Push: function usage approved CopyMemory(pNodeID->id, strGUID, cbString ); GlobalUnlock(pMedium->hGlobal); } } } else { hr = DV_E_FORMATETC; } return hr; } // CMyComputerDataObject::GetData() //#endif // __DAN_MORIN_HARDCODED_CONTEXT_MENU_EXTENSION__ HRESULT CMyComputerDataObject::Initialize( CMyComputerCookie* pcookie, DATA_OBJECT_TYPES type, BOOL fAllowOverrideMachineName) { // ISSUE-2002-/02/27-JonN check "type" parameter if (NULL == pcookie || NULL != m_pcookie) { ASSERT(FALSE); return E_UNEXPECTED; } m_dataobjecttype = type; m_pcookie = pcookie; m_fAllowOverrideMachineName = fAllowOverrideMachineName; ((CRefcountedObject*)m_pcookie)->AddRef(); return S_OK; } CMyComputerDataObject::~CMyComputerDataObject() { if (NULL != m_pcookie) { ((CRefcountedObject*)m_pcookie)->Release(); } else { ASSERT(FALSE); } } HRESULT CMyComputerDataObject::PutDisplayName(STGMEDIUM* pMedium) // Writes the "friendly name" to the provided storage medium // Returns the result of the write operation { // JonN 2/20/02 Security Push if (NULL == pMedium) { ASSERT(FALSE); return E_POINTER; } CString strDisplayName = m_pcookie->QueryTargetServer(); CString formattedName = FormatDisplayName (strDisplayName); stream_ptr s(pMedium); return s.Write(formattedName); } // Register the clipboard formats CLIPFORMAT CMyComputerDataObject::m_CFDisplayName = (CLIPFORMAT)RegisterClipboardFormat(CCF_DISPLAY_NAME); CLIPFORMAT CMyComputerDataObject::m_CFNodeID2 = (CLIPFORMAT)RegisterClipboardFormat(CCF_NODEID2); CLIPFORMAT CMyComputerDataObject::m_CFMachineName = (CLIPFORMAT)RegisterClipboardFormat(L"MMC_SNAPIN_MACHINE_NAME"); CLIPFORMAT CDataObject::m_CFRawCookie = (CLIPFORMAT)RegisterClipboardFormat(L"MYCOMPUT_SNAPIN_RAW_COOKIE"); STDMETHODIMP CMyComputerComponentData::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject) { MFC_TRY; // ISSUE-2002/02/27-JonN This would be more efficient if an instance of // CMyComputerDataObject were permanently attached to CMyComputerCookie, // or better yet, if they were the same object. QueryDataObject gets // called a lot... CMyComputerCookie* pUseThisCookie = (CMyComputerCookie*)ActiveBaseCookie(reinterpret_cast(cookie)); // JonN 2/20/02 Security Push if (NULL == pUseThisCookie) { ASSERT(FALSE); return E_POINTER; } CComObject* pDataObject = NULL; HRESULT hRes = CComObject::CreateInstance(&pDataObject); if ( FAILED(hRes) ) return hRes; HRESULT hr = pDataObject->Initialize( pUseThisCookie, type, m_fAllowOverrideMachineName); if ( SUCCEEDED(hr) ) { hr = pDataObject->QueryInterface(IID_IDataObject, reinterpret_cast(ppDataObject)); } if ( FAILED(hr) ) { delete pDataObject; return hr; } return hr; MFC_CATCH; }