378 lines
7.7 KiB
C++
378 lines
7.7 KiB
C++
//
|
|
// Copyright 1997 - Microsoft
|
|
//
|
|
|
|
//
|
|
// DATAOBJ.CPP - A data object
|
|
//
|
|
|
|
#include "pch.h"
|
|
#include "dataobj.h"
|
|
|
|
DEFINE_MODULE("IMADMUI")
|
|
DEFINE_THISCLASS("CDsPropDataObj")
|
|
#define THISCLASS CDsPropDataObj
|
|
#define LPTHISCLASS CDsPropDataObj*
|
|
|
|
|
|
//
|
|
// CreateInstance( )
|
|
//
|
|
LPVOID
|
|
CDsPropDataObj_CreateInstance(
|
|
HWND hwndParent,
|
|
IDataObject * pido,
|
|
GUID * pClassGUID,
|
|
BOOL fReadOnly,
|
|
LPWSTR pszObjPath,
|
|
LPWSTR bstrClass )
|
|
{
|
|
TraceFunc( "CDsPropDataObj_CreateInstance( ... )\n" );
|
|
|
|
LPTHISCLASS lpcc = new THISCLASS( hwndParent, pido, pClassGUID, fReadOnly);
|
|
if (!lpcc)
|
|
RETURN(lpcc);
|
|
|
|
HRESULT hr = THR( lpcc->Init( pszObjPath, bstrClass ) );
|
|
if ( hr )
|
|
{
|
|
delete lpcc;
|
|
RETURN(NULL);
|
|
}
|
|
|
|
RETURN((LPVOID) lpcc);
|
|
}
|
|
|
|
|
|
//
|
|
// Constructor
|
|
//
|
|
THISCLASS::THISCLASS(
|
|
HWND hwndParent,
|
|
IDataObject * pido,
|
|
GUID * pClassGUID,
|
|
BOOL fReadOnly) :
|
|
m_fReadOnly(fReadOnly),
|
|
m_pwszObjName(NULL),
|
|
m_pwszObjClass(NULL),
|
|
m_hwnd(hwndParent),
|
|
m_pPage(pido),
|
|
m_ClassGUID(*pClassGUID),
|
|
_cRef(0)
|
|
{
|
|
TraceClsFunc( "CDsPropDataObj( )\n" );
|
|
|
|
if (m_pPage) {
|
|
m_pPage->AddRef();
|
|
}
|
|
|
|
TraceFuncExit( );
|
|
}
|
|
|
|
//
|
|
// Destructor
|
|
//
|
|
THISCLASS::~THISCLASS(void)
|
|
{
|
|
TraceClsFunc( "~CDsPropDataObj( )\n" );
|
|
if (m_pPage) {
|
|
m_pPage->Release();
|
|
}
|
|
|
|
if (m_pwszObjName) {
|
|
TraceFree(m_pwszObjName);
|
|
}
|
|
|
|
if (m_pwszObjClass) {
|
|
TraceFree(m_pwszObjClass);
|
|
}
|
|
|
|
TraceFuncExit( );
|
|
}
|
|
|
|
//
|
|
// Init( )
|
|
//
|
|
HRESULT
|
|
THISCLASS::Init(
|
|
LPWSTR pwszObjName,
|
|
LPWSTR pwszClass )
|
|
{
|
|
TraceClsFunc( "Init( ... )\n" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
// IUnknown stuff
|
|
BEGIN_QITABLE_IMP( CDsPropDataObj, IDataObject );
|
|
QITABLE_IMP( IDataObject );
|
|
END_QITABLE_IMP( CDsPropDataObj );
|
|
Assert( _cRef == 0);
|
|
AddRef( );
|
|
|
|
if (!pwszObjName || *pwszObjName == L'\0')
|
|
{
|
|
HRETURN(E_INVALIDARG);
|
|
}
|
|
if (!pwszClass || *pwszClass == L'\0')
|
|
{
|
|
HRETURN(E_INVALIDARG);
|
|
}
|
|
|
|
m_pwszObjName = (LPWSTR) TraceStrDup( pwszObjName );
|
|
if ( !m_pwszObjName ) {
|
|
hr = THR(E_OUTOFMEMORY);
|
|
goto Error;
|
|
}
|
|
|
|
m_pwszObjClass = (LPWSTR) TraceStrDup( pwszClass );
|
|
if ( !m_pwszObjClass ) {
|
|
hr = THR(E_OUTOFMEMORY);
|
|
goto Error;
|
|
}
|
|
|
|
Cleanup:
|
|
HRETURN(S_OK);
|
|
|
|
Error:
|
|
if ( m_pwszObjName ) {
|
|
TraceFree( m_pwszObjName );
|
|
m_pwszObjName = NULL;
|
|
}
|
|
|
|
if ( m_pwszObjClass ) {
|
|
TraceFree( m_pwszObjClass );
|
|
m_pwszObjClass = NULL;
|
|
}
|
|
|
|
switch (hr) {
|
|
case S_OK:
|
|
break;
|
|
default:
|
|
MessageBoxFromHResult( m_hwnd, IDC_ERROR_CREATINGACCOUNT_TITLE, hr );
|
|
break;
|
|
}
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IUnknown
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// QueryInterface()
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppv )
|
|
{
|
|
TraceClsFunc( "" );
|
|
|
|
HRESULT hr = ::QueryInterface( this, _QITable, riid, ppv );
|
|
|
|
QIRETURN( hr, riid );
|
|
}
|
|
|
|
//
|
|
// AddRef()
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
THISCLASS::AddRef( void )
|
|
{
|
|
TraceClsFunc( "[IUnknown] AddRef( )\n" );
|
|
|
|
InterlockIncrement( _cRef );
|
|
|
|
RETURN(_cRef);
|
|
}
|
|
|
|
//
|
|
// Release()
|
|
//
|
|
STDMETHODIMP_(ULONG)
|
|
THISCLASS::Release( void )
|
|
{
|
|
TraceClsFunc( "[IUnknown] Release( )\n" );
|
|
|
|
InterlockDecrement( _cRef );
|
|
|
|
if ( _cRef )
|
|
RETURN(_cRef);
|
|
|
|
TraceDo( delete this );
|
|
|
|
RETURN(0);
|
|
}
|
|
|
|
// ************************************************************************
|
|
//
|
|
// IDataObject
|
|
//
|
|
// ************************************************************************
|
|
|
|
//
|
|
// GetData( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetData(
|
|
FORMATETC * pFormatEtc,
|
|
STGMEDIUM * pMedium)
|
|
{
|
|
TraceClsFunc( "[IDataObject] GetData( ... )\n" );
|
|
if (IsBadWritePtr(pMedium, sizeof(STGMEDIUM))) {
|
|
HRETURN(E_INVALIDARG);
|
|
}
|
|
if (!(pFormatEtc->tymed & TYMED_HGLOBAL)) {
|
|
HRETURN(DV_E_TYMED);
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (pFormatEtc->cfFormat == g_cfDsObjectNames)
|
|
{
|
|
// return the object name and class.
|
|
//
|
|
INT cbPath = sizeof(WCHAR) * (wcslen(m_pwszObjName) + 1);
|
|
INT cbClass = sizeof(WCHAR) * (wcslen(m_pwszObjClass) + 1);
|
|
INT cbStruct = sizeof(DSOBJECTNAMES);
|
|
|
|
LPDSOBJECTNAMES pDSObj;
|
|
|
|
pDSObj = (LPDSOBJECTNAMES)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
|
|
cbStruct + cbPath + cbClass);
|
|
if (pDSObj == NULL) {
|
|
hr = THR(STG_E_MEDIUMFULL);
|
|
goto Error;
|
|
}
|
|
|
|
pDSObj->clsidNamespace = CLSID_MicrosoftDS;
|
|
pDSObj->cItems = 1;
|
|
pDSObj->aObjects[0].offsetName = cbStruct;
|
|
pDSObj->aObjects[0].offsetClass = cbStruct + cbPath;
|
|
if (m_fReadOnly)
|
|
{
|
|
pDSObj->aObjects[0].dwFlags = DSOBJECT_READONLYPAGES;
|
|
}
|
|
|
|
wcscpy((PWSTR)((BYTE *)pDSObj + cbStruct), m_pwszObjName);
|
|
wcscpy((PWSTR)((BYTE *)pDSObj + cbStruct + cbPath), m_pwszObjClass);
|
|
|
|
pMedium->hGlobal = (HGLOBAL)pDSObj;
|
|
}
|
|
else if (pFormatEtc->cfFormat == g_cfDsPropCfg)
|
|
{
|
|
// return the property sheet notification info. In this case, it is
|
|
// the invokding sheet's hwnd.
|
|
//
|
|
PPROPSHEETCFG pSheetCfg;
|
|
|
|
pSheetCfg = (PPROPSHEETCFG)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
|
|
sizeof(PROPSHEETCFG));
|
|
if (pSheetCfg == NULL) {
|
|
hr = THR(STG_E_MEDIUMFULL);
|
|
goto Error;
|
|
}
|
|
|
|
ZeroMemory(pSheetCfg, sizeof(PROPSHEETCFG));
|
|
|
|
pSheetCfg->hwndParentSheet = m_hwnd;
|
|
|
|
pMedium->hGlobal = (HGLOBAL)pSheetCfg;
|
|
}
|
|
else
|
|
{
|
|
// Pass call on to "parent" object's data obj.
|
|
if (m_pPage ) {
|
|
hr = m_pPage->GetData( pFormatEtc, pMedium );
|
|
#ifdef DEBUG
|
|
if (hr != DV_E_FORMATETC )
|
|
THR(hr);
|
|
#endif
|
|
goto Error; // not really, but we don't want to clean up
|
|
} else {
|
|
hr = THR(E_FAIL);
|
|
goto Error;
|
|
}
|
|
}
|
|
|
|
pMedium->tymed = TYMED_HGLOBAL;
|
|
pMedium->pUnkForRelease = NULL;
|
|
|
|
Error:
|
|
HRETURN(hr);
|
|
}
|
|
|
|
//
|
|
// GetDataHere( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::GetDataHere(
|
|
LPFORMATETC pFormatEtc,
|
|
LPSTGMEDIUM pMedium)
|
|
{
|
|
TraceClsFunc( "[IDataObject] GetDataHere( ... )\n" );
|
|
HRESULT hr;
|
|
|
|
if (IsBadWritePtr(pMedium, sizeof(STGMEDIUM))) {
|
|
HRETURN(E_INVALIDARG);
|
|
}
|
|
|
|
if (pFormatEtc->cfFormat == g_cfMMCGetNodeType)
|
|
{
|
|
if (!(pFormatEtc->tymed & TYMED_HGLOBAL)) {
|
|
hr = THR(DV_E_TYMED);
|
|
goto Error;
|
|
}
|
|
LPSTREAM lpStream;
|
|
ULONG written;
|
|
|
|
// Create the stream on the hGlobal passed in.
|
|
//
|
|
hr = CreateStreamOnHGlobal(pMedium->hGlobal, FALSE, &lpStream);
|
|
if (hr)
|
|
goto Error;
|
|
|
|
hr = lpStream->Write(&m_ClassGUID, sizeof(m_ClassGUID), &written);
|
|
|
|
// Because we told CreateStreamOnHGlobal with 'FALSE', only the
|
|
// stream is released here.
|
|
lpStream->Release();
|
|
} else if (m_pPage ) {
|
|
// Pass call on to "parent" object's data obj.
|
|
hr = THR( m_pPage->GetDataHere( pFormatEtc, pMedium ) );
|
|
} else {
|
|
hr = THR(E_FAIL);
|
|
}
|
|
|
|
Cleanup:
|
|
HRETURN(hr);
|
|
|
|
Error:
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// EnumFormatEtc( )
|
|
//
|
|
STDMETHODIMP
|
|
THISCLASS::EnumFormatEtc(
|
|
DWORD dwDirection,
|
|
LPENUMFORMATETC * ppEnumFormatEtc)
|
|
{
|
|
TraceClsFunc( "[IDataObject] EnumFormatEtc( ... )\n" );
|
|
//
|
|
// Pass call on to "parent" object's data obj.
|
|
//
|
|
if (m_pPage )
|
|
{
|
|
HRETURN(m_pPage->EnumFormatEtc(dwDirection, ppEnumFormatEtc));
|
|
}
|
|
else
|
|
{
|
|
HRETURN(E_FAIL);
|
|
}
|
|
}
|