694 lines
13 KiB
C++
694 lines
13 KiB
C++
/*++
|
|
|
|
Copyright (c) 1994-1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
dataobj.cpp
|
|
|
|
Abstract:
|
|
|
|
Snapin data object
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "inetmgr.h"
|
|
#include "cinetmgr.h"
|
|
#include "dataobj.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
//
|
|
// 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 = RegisterClipboardFormat(CCF_NODETYPE);
|
|
unsigned int CDataObject::m_cfNodeTypeString = RegisterClipboardFormat(CCF_SZNODETYPE);
|
|
unsigned int CDataObject::m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
|
|
unsigned int CDataObject::m_cfCoClass = RegisterClipboardFormat(CCF_SNAPIN_CLASSID);
|
|
|
|
/*
|
|
//
|
|
// Multi-select
|
|
//
|
|
unsigned int CDataObject::m_cfpMultiSelDataObj = RegisterClipboardFormat(CCF_MMC_MULTISELECT_DATAOBJECT);
|
|
unsigned int CDataObject::m_cfMultiObjTypes = RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT);
|
|
unsigned int CDataObject::m_cfMultiSelDataObjs = RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS);
|
|
*/
|
|
|
|
//
|
|
// Internal
|
|
//
|
|
unsigned int CDataObject::m_cfInternal = RegisterClipboardFormat(ISM_SNAPIN_INTERNAL);
|
|
|
|
//
|
|
// Published Information
|
|
//
|
|
unsigned int CDataObject::m_cfISMMachineName = RegisterClipboardFormat(ISM_SNAPIN_MACHINE_NAME);
|
|
unsigned int CDataObject::m_cfMyComputMachineName = RegisterClipboardFormat(MYCOMPUT_MACHINE_NAME);
|
|
unsigned int CDataObject::m_cfISMService = RegisterClipboardFormat(ISM_SNAPIN_SERVICE);
|
|
unsigned int CDataObject::m_cfISMInstance = RegisterClipboardFormat(ISM_SNAPIN_INSTANCE);
|
|
unsigned int CDataObject::m_cfISMParentPath = RegisterClipboardFormat(ISM_SNAPIN_PARENT_PATH);
|
|
unsigned int CDataObject::m_cfISMNode = RegisterClipboardFormat(ISM_SNAPIN_NODE);
|
|
unsigned int CDataObject::m_cfISMMetaPath = RegisterClipboardFormat(ISM_SNAPIN_META_PATH);
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CDataObject::GetDataHere(
|
|
IN LPFORMATETC lpFormatetc,
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write requested information type to the given medium
|
|
|
|
Arguments:
|
|
|
|
LPFORMATETC lpFormatetc : Format etc
|
|
LPSTGMEDIUM lpMedium : Medium to write to.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = DV_E_CLIPFORMAT;
|
|
|
|
//
|
|
// 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_cfNodeTypeString)
|
|
{
|
|
hr = CreateNodeTypeStringData(lpMedium);
|
|
}
|
|
else if (cf == m_cfCoClass)
|
|
{
|
|
hr = CreateCoClassID(lpMedium);
|
|
}
|
|
else if (cf == m_cfDisplayName)
|
|
{
|
|
hr = CreateDisplayName(lpMedium);
|
|
}
|
|
else if (cf == m_cfInternal)
|
|
{
|
|
hr = CreateInternal(lpMedium);
|
|
}
|
|
else if (cf == m_cfISMMachineName)
|
|
{
|
|
hr = CreateMachineName(lpMedium);
|
|
}
|
|
|
|
/*
|
|
multi-select pulled
|
|
|
|
else if (cf == m_cfpMultiSelDataObj)
|
|
{
|
|
TRACEEOLID("CCF_MMC_MULTISELECT_DATAOBJECT");
|
|
}
|
|
else if (cf == m_cfMultiObjTypes)
|
|
{
|
|
TRACEEOLID("CCF_OBJECT_TYPES_IN_MULTI_SELECT");
|
|
}
|
|
else if (cf == m_cfMultiSelDataObjs)
|
|
{
|
|
TRACEEOLID("CCF_MULTI_SELECT_SNAPINS");
|
|
}
|
|
*/
|
|
|
|
else if (cf == m_cfISMService)
|
|
{
|
|
hr = CreateMetaField(lpMedium, META_SERVICE);
|
|
}
|
|
else if (cf == m_cfISMInstance)
|
|
{
|
|
hr = CreateMetaField(lpMedium, META_INSTANCE);
|
|
}
|
|
else if (cf == m_cfISMParentPath)
|
|
{
|
|
hr = CreateMetaField(lpMedium, META_PARENT);
|
|
}
|
|
else if (cf == m_cfISMNode)
|
|
{
|
|
hr = CreateMetaField(lpMedium, META_NODE);
|
|
}
|
|
else if (cf == m_cfISMMetaPath)
|
|
{
|
|
hr = CreateMetaField(lpMedium, META_WHOLE);
|
|
}
|
|
else
|
|
{
|
|
TRACEEOLID("Unrecognized format");
|
|
hr = DV_E_CLIPFORMAT;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CDataObject::GetData(
|
|
IN LPFORMATETC lpFormatetcIn,
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get data from the data object
|
|
|
|
Arguments:
|
|
|
|
LPFORMATETC lpFormatetcIn : Formatetc Input
|
|
LPSTGMEDIUM lpMedium : Pointer to medium
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Not implemented
|
|
//
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CDataObject::EnumFormatEtc(
|
|
IN DWORD dwDirection,
|
|
IN LPENUMFORMATETC * ppEnumFormatEtc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enumerate format etc information
|
|
|
|
Arguments:
|
|
|
|
DWORD dwDirection : Direction
|
|
LPENUMFORMATETC * ppEnumFormatEtc : Format etc array
|
|
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Not implemented
|
|
//
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// CDataObject creation members
|
|
//
|
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::Create(
|
|
IN const void * pBuffer,
|
|
IN int len,
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create information on the given medium
|
|
|
|
Arguments:
|
|
|
|
const void * pBuffer : Data buffer
|
|
int len : Size of data
|
|
LPSTGMEDIUM lpMedium : Medium to write to.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
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 called 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::CreateNodeTypeData(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create node type data on medium
|
|
|
|
Arguments:
|
|
|
|
LPSTGMEDIUM lpMedium : Medium to write to.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Create the node type object in GUID format
|
|
//
|
|
const GUID * pcObjectType = NULL;
|
|
|
|
if (m_internal.m_cookie == NULL)
|
|
{
|
|
//
|
|
// Blank CIISNode, must be the static root
|
|
//
|
|
pcObjectType = &cInternetRootNode;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Ask the object what kind of object it is.
|
|
//
|
|
CIISObject * pObject = (CIISObject *)m_internal.m_cookie;
|
|
pcObjectType = pObject->GetGUIDPtr();
|
|
}
|
|
|
|
return Create((const void *)pcObjectType, sizeof(GUID), lpMedium);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateNodeTypeStringData(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create node type in string format
|
|
|
|
Arguments:
|
|
|
|
LPSTGMEDIUM lpMedium : Medium to write to.
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Create the node type object in GUID string format
|
|
//
|
|
const wchar_t * cszObjectType = NULL;
|
|
CString str;
|
|
|
|
if (m_internal.m_cookie == NULL)
|
|
{
|
|
//
|
|
// This must be the static root node
|
|
//
|
|
cszObjectType = GUIDToCString(cInternetRootNode, str);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Ask the CIISObject what type it is
|
|
//
|
|
CIISObject * pObject = (CIISObject *)m_internal.m_cookie;
|
|
cszObjectType = GUIDToCString(pObject->QueryGUID(), str);
|
|
}
|
|
|
|
return Create(
|
|
cszObjectType,
|
|
((wcslen(cszObjectType) + 1) * sizeof(wchar_t)),
|
|
lpMedium
|
|
);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateDisplayName(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
CDataObject implementations
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// This is the display name 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
|
|
//
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CString szDispName;
|
|
szDispName.LoadString(IDS_NODENAME);
|
|
|
|
return Create(
|
|
szDispName,
|
|
((szDispName.GetLength() + 1) * sizeof(wchar_t)),
|
|
lpMedium
|
|
);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateInternal(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
CDataObject implementations
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
return Create(&m_internal, sizeof(INTERNAL), lpMedium);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateMachineName(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create the machine name
|
|
|
|
Arguments:
|
|
|
|
LPSTGMEDIUM lpMedium : Address of STGMEDIUM object
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
wchar_t pzName[MAX_PATH + 1] = {0};
|
|
DWORD len; // = MAX_PATH + 1;
|
|
|
|
CIISObject * pObject = (CIISObject *)m_internal.m_cookie;
|
|
if (pObject == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
lstrcpyn(pzName, pObject->GetMachineName(), MAX_PATH);
|
|
len = lstrlen(pzName);
|
|
|
|
//
|
|
// Add 1 for the NULL and calculate the bytes for the stream
|
|
//
|
|
return Create(pzName, ((len + 1) * sizeof(wchar_t)), lpMedium);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateMetaField(
|
|
IN LPSTGMEDIUM lpMedium,
|
|
IN META_FIELD fld
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create a field from the metabase path, indicated by fld, or the entire
|
|
path.
|
|
|
|
Arguments:
|
|
|
|
LPSTGMEDIUM lpMedium : Address of STGMEDIUM object
|
|
META_FIELD fld : Type of metabase information
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CIISObject * pObject = (CIISObject *)m_internal.m_cookie;
|
|
|
|
if (pObject == NULL)
|
|
{
|
|
//
|
|
// Static root node has no metabase path
|
|
//
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Generate complete metabase path for this node
|
|
//
|
|
CString strField;
|
|
CString strMetaPath;
|
|
pObject->BuildFullPath(strMetaPath, TRUE);
|
|
|
|
if (fld == META_WHOLE)
|
|
{
|
|
//
|
|
// Whole metabase path requested
|
|
//
|
|
strField = strMetaPath;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// A portion of the metabase is requested. Return the requested
|
|
// portion
|
|
//
|
|
LPCTSTR lpMetaPath = (LPCTSTR)strMetaPath;
|
|
LPCTSTR lpEndPath = lpMetaPath + strMetaPath.GetLength() + 1;
|
|
LPCTSTR lpSvc = NULL;
|
|
LPCTSTR lpInstance = NULL;
|
|
LPCTSTR lpParent = NULL;
|
|
LPCTSTR lpNode = NULL;
|
|
|
|
//
|
|
// Break up the metabase path in portions
|
|
//
|
|
if (lpSvc = _tcschr(lpMetaPath, _T('/')))
|
|
{
|
|
++lpSvc;
|
|
|
|
if (lpInstance = _tcschr(lpSvc, _T('/')))
|
|
{
|
|
++lpInstance;
|
|
|
|
if (lpParent = _tcschr(lpInstance, _T('/')))
|
|
{
|
|
++lpParent;
|
|
lpNode = _tcsrchr(lpParent, _T('/'));
|
|
|
|
if (lpNode)
|
|
{
|
|
++lpNode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int n1, n2;
|
|
switch(fld)
|
|
{
|
|
case META_SERVICE:
|
|
//
|
|
// Requested the service string
|
|
//
|
|
if (lpSvc)
|
|
{
|
|
n1 = DIFF(lpSvc - lpMetaPath);
|
|
n2 = lpInstance ? DIFF(lpInstance - lpSvc) : DIFF(lpEndPath - lpSvc);
|
|
strField = strMetaPath.Mid(n1, n2 - 1);
|
|
}
|
|
break;
|
|
|
|
case META_INSTANCE:
|
|
//
|
|
// Requested the instance number
|
|
//
|
|
if (lpInstance)
|
|
{
|
|
n1 = DIFF(lpInstance - lpMetaPath);
|
|
n2 = lpParent ? DIFF(lpParent - lpInstance) : DIFF(lpEndPath - lpInstance);
|
|
strField = strMetaPath.Mid(n1, n2 - 1);
|
|
}
|
|
|
|
break;
|
|
|
|
case META_PARENT:
|
|
//
|
|
// Requestd the parent path
|
|
//
|
|
if (lpParent)
|
|
{
|
|
n1 = DIFF(lpParent - lpMetaPath);
|
|
n2 = lpNode ? DIFF(lpNode - lpParent) : DIFF(lpEndPath - lpParent);
|
|
strField = strMetaPath.Mid(n1, n2 - 1);
|
|
}
|
|
break;
|
|
|
|
case META_NODE:
|
|
//
|
|
// Requested the node name
|
|
//
|
|
if (lpNode)
|
|
{
|
|
n1 = DIFF(lpNode - lpMetaPath);
|
|
n2 = DIFF(lpEndPath - lpNode);
|
|
strField = strMetaPath.Mid(n1, n2 - 1);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// Bogus
|
|
//
|
|
ASSERT(FALSE);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
TRACEEOLID("Requested metabase path data: " << strField);
|
|
int len = strField.GetLength() + 1;
|
|
|
|
return Create((LPCTSTR)strField, (len) * sizeof(TCHAR), lpMedium);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CDataObject::CreateCoClassID(
|
|
IN LPSTGMEDIUM lpMedium
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create the CoClassID
|
|
|
|
Arguments:
|
|
|
|
LPSTGMEDIUM lpMedium : Medium
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Create the CoClass information
|
|
//
|
|
return Create((const void *)&m_internal.m_clsid, sizeof(CLSID), lpMedium);
|
|
}
|