DATAOBJ.CPP

// This is a part of the Microsoft Management Console. 
// Copyright 1995 - 1997 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Management Console and related
// electronic documentation provided with the interfaces.


#include "stdafx.h"
#include "Service.h"
#include "CSnapin.h"
#include "DataObj.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

///////////////////////////////////////////////////////////////////////////////
// Sample code to show how to Create DataObjects
// Minimal error checking for clarity

///////////////////////////////////////////////////////////////////////////////
// Snap-in NodeType in both GUID format and string format
// Note - Typically there is a node type for each different object, sample
// only uses one node type.

unsigned int CDataObject::m_cfNodeType = 0;
unsigned int CDataObject::m_cfNodeTypeString = 0;
unsigned int CDataObject::m_cfDisplayName = 0;
unsigned int CDataObject::m_cfCoClass = 0;

unsigned int CDataObject::m_cfInternal = 0;
unsigned int CDataObject::m_cfMultiSel = 0;




// Extension information
// The only additional clipboard format supported is to get the workstation name.
unsigned int CDataObject::m_cfWorkstation = 0;

/////////////////////////////////////////////////////////////////////////////
// CDataObject implementations

CDataObject::CDataObject()
{
USES_CONVERSION;

m_cfNodeType = RegisterClipboardFormat(W2T(CCF_NODETYPE));
m_cfNodeTypeString = RegisterClipboardFormat(W2T(CCF_SZNODETYPE));
m_cfDisplayName = RegisterClipboardFormat(W2T(CCF_DISPLAY_NAME));
m_cfCoClass = RegisterClipboardFormat(W2T(CCF_SNAPIN_CLASSID));
m_cfMultiSel = RegisterClipboardFormat(W2T(CCF_OBJECT_TYPES_IN_MULTI_SELECT));

#ifdef UNICODE
m_cfInternal = RegisterClipboardFormat(W2T((LPTSTR)SNAPIN_INTERNAL));
m_cfWorkstation = RegisterClipboardFormat(W2T((LPTSTR)SNAPIN_WORKSTATION));
#else
m_cfInternal = RegisterClipboardFormat(W2T(SNAPIN_INTERNAL));
m_cfWorkstation = RegisterClipboardFormat(W2T(SNAPIN_WORKSTATION));
#endif //UNICODE


#ifdef _DEBUG
m_ComponentData = NULL;
dbg_refCount = 0;
#endif

m_pbMultiSelData = 0;
m_cbMultiSelData = 0;
m_bMultiSelDobj = FALSE;
}


STDMETHODIMP CDataObject::GetData(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());

HRESULT hr = DV_E_CLIPFORMAT;

if (lpFormatetc->cfFormat == m_cfMultiSel)
{
ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);
if (m_internal.m_cookie != MMC_MULTI_SELECT_COOKIE)
return E_FAIL;

//return CreateMultiSelData(lpMedium);

ASSERT(m_pbMultiSelData != 0);
ASSERT(m_cbMultiSelData != 0);

lpMedium->tymed = TYMED_HGLOBAL;
lpMedium->hGlobal = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,
(m_cbMultiSelData + sizeof(DWORD)));
if (lpMedium->hGlobal == NULL)
return STG_E_MEDIUMFULL;

BYTE* pb = reinterpret_cast<BYTE*>(::GlobalLock(lpMedium->hGlobal));
*((DWORD*)pb) = m_cbMultiSelData / sizeof(GUID);
pb += sizeof(DWORD);
CopyMemory(pb, m_pbMultiSelData, m_cbMultiSelData);

::GlobalUnlock(lpMedium->hGlobal);

hr = S_OK;
}

return hr;
}

STDMETHODIMP CDataObject::GetDataHere(LPFORMATETC lpFormatetc, LPSTGMEDIUM lpMedium)
{
HRESULT hr = DV_E_CLIPFORMAT;

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// Based on the CLIPFORMAT write data to the stream
const CLIPFORMAT cf = lpFormatetc->cfFormat;

if (cf == m_cfNodeType)
{
hr = CreateNodeTypeData(lpMedium);
}
else if (cf == m_cfCoClass)
{
hr = CreateCoClassID(lpMedium);
}
else if(cf == m_cfNodeTypeString)
{
hr = CreateNodeTypeStringData(lpMedium);
}
else if (cf == m_cfDisplayName)
{
hr = CreateDisplayName(lpMedium);
}
else if (cf == m_cfInternal)
{
hr = CreateInternal(lpMedium);
}
else if (cf == m_cfWorkstation)
{
hr = CreateWorkstationName(lpMedium);
}

return hr;
}

STDMETHODIMP CDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppEnumFormatEtc)
{
return E_NOTIMPL;
}

/////////////////////////////////////////////////////////////////////////////
// CDataObject creation members

HRESULT CDataObject::Create(const void* pBuffer, int len, LPSTGMEDIUM lpMedium)
{
HRESULT hr = DV_E_TYMED;

// Do some simple validation
if (pBuffer == NULL || lpMedium == NULL)
return E_POINTER;

// Make sure the type medium is HGLOBAL
if (lpMedium->tymed == TYMED_HGLOBAL)
{
// Create the stream on the hGlobal passed in
LPSTREAM lpStream;
hr = CreateStreamOnHGlobal(lpMedium->hGlobal, FALSE, &lpStream);

if (SUCCEEDED(hr))
{
// Write to the stream the number of bytes
unsigned long written;
hr = lpStream->Write(pBuffer, len, &written);

// Because we told CreateStreamOnHGlobal with 'FALSE',
// only the stream is released here.
// Note - the caller (i.e. snap-in, object) will free the HGLOBAL
// at the correct time. This is according to the IDataObject specification.
lpStream->Release();
}
}

return hr;
}


HRESULT CDataObject::CreateMultiSelData(LPSTGMEDIUM lpMedium)
{
ASSERT(m_internal.m_cookie == MMC_MULTI_SELECT_COOKIE);

ASSERT(m_pbMultiSelData != 0);
ASSERT(m_cbMultiSelData != 0);

return Create(reinterpret_cast<const void*>(m_pbMultiSelData),
m_cbMultiSelData, lpMedium);
}

HRESULT CDataObject::CreateNodeTypeData(LPSTGMEDIUM lpMedium)
{
// Create the node type object in GUID format
const GUID* pcObjectType = NULL;

if (m_internal.m_cookie == NULL)
{
pcObjectType = &cNodeTypeStatic;
}
else if (m_internal.m_type == CCT_SCOPE)
{
CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
ASSERT(pFolder != NULL);
if (pFolder == NULL)
return E_UNEXPECTED;

switch (pFolder->GetType())
{
case COMPANY:
pcObjectType = &cNodeTypeCompany;
break;

case USER:
pcObjectType = &cNodeTypeUser;
break;

case EXT_COMPANY:
pcObjectType = &cNodeTypeExtCompany;
break;

case EXT_USER:
pcObjectType = &cNodeTypeExtUser;
break;

case VIRTUAL:
case EXT_VIRTUAL:
pcObjectType = &cNodeTypeExtUser;
break;

default:
pcObjectType = &cNodeTypeDynamic;
break;
}
}
else if (m_internal.m_type == CCT_RESULT)
{
// RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);

pcObjectType = &cObjectTypeResultItem;
}

return Create(reinterpret_cast<const void*>(pcObjectType), sizeof(GUID),
lpMedium);
}

HRESULT CDataObject::CreateNodeTypeStringData(LPSTGMEDIUM lpMedium)
{
// Create the node type object in GUID string format
const WCHAR* cszObjectType = NULL;

if (m_internal.m_cookie == NULL)
{
cszObjectType = cszNodeTypeStatic;
}
else if (m_internal.m_type == CCT_SCOPE)
{
CFolder* pFolder = reinterpret_cast<CFolder*>(m_internal.m_cookie);
ASSERT(pFolder != NULL);
if (pFolder == NULL)
return E_UNEXPECTED;

switch (pFolder->GetType())
{
case COMPANY:
cszObjectType = cszNodeTypeCompany;
break;

case USER:
cszObjectType = cszNodeTypeUser;
break;

case EXT_COMPANY:
cszObjectType = cszNodeTypeExtCompany;
break;

case EXT_USER:
cszObjectType = cszNodeTypeExtUser;
break;

default:
cszObjectType = cszNodeTypeDynamic;
break;
}
}
else if (m_internal.m_type == CCT_RESULT)
{
// RESULT_DATA* pData = reinterpret_cast<RESULT_DATA*>(m_internal.m_cookie);

cszObjectType = cszObjectTypeResultItem;
}
return Create(cszObjectType, ((wcslen(cszObjectType)+1) * sizeof(WCHAR)), lpMedium);
}

HRESULT CDataObject::CreateDisplayName(LPSTGMEDIUM lpMedium)
{
// This is the display named used in the scope pane and snap-in manager

// Load the name from resource
// Note - if this is not provided, the console will used the snap-in name

CString szDispName;
szDispName.LoadString(IDS_NODENAME);

USES_CONVERSION;

#ifdef UNICODE
return Create(szDispName, ((szDispName.GetLength()+1) * sizeof(WCHAR)), lpMedium);
#else
return Create(T2W(szDispName), ((szDispName.GetLength()+1) * sizeof(WCHAR)), lpMedium);
#endif
}

HRESULT CDataObject::CreateInternal(LPSTGMEDIUM lpMedium)
{
return Create(&m_internal, sizeof(INTERNAL), lpMedium);
}

HRESULT CDataObject::CreateWorkstationName(LPSTGMEDIUM lpMedium)
{
TCHAR pzName[MAX_COMPUTERNAME_LENGTH+1] = {0};
DWORD len = MAX_COMPUTERNAME_LENGTH+1;

if (GetComputerName(pzName, &len) == FALSE)
return E_FAIL;

// Add 1 for the NULL and calculate the bytes for the stream
//#ifdef UNICODE
USES_CONVERSION;
return Create(T2W(pzName), ((len+1)* sizeof(WCHAR)), lpMedium);
//#else
// return Create(pzName, ((len+1)* sizeof(WCHAR)), lpMedium);
//#endif

}

HRESULT CDataObject::CreateCoClassID(LPSTGMEDIUM lpMedium)
{
// Create the CoClass information
return Create(reinterpret_cast<const void*>(&m_internal.m_clsid), sizeof(CLSID), lpMedium);
}