///////////////////////////////////////////////////////////////////////////// // // Copyright (c) 1997-2002 Microsoft Corporation // // Module Name: // ExtObj.cpp // // Description: // Implementation of the CExtObject class, which implements the // extension interfaces required by a Microsoft Windows NT Cluster // Administrator Extension DLL. // // Maintained By: // David Potter (DavidP) Mmmm DD, 1997 // // Revision History: // // Notes: // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "DebugEx.h" #include "ExtObj.h" #include "ResProp.h" ///////////////////////////////////////////////////////////////////////////// // Global Variables ///////////////////////////////////////////////////////////////////////////// static CRuntimeClass * g_rgprtcResPSPages[] = { RUNTIME_CLASS(CDebugParamsPage), NULL }; static CRuntimeClass ** g_rgpprtcResPSPages[] = { g_rgprtcResPSPages, }; static CRuntimeClass * g_rgprtcResTypePSPages[] = { RUNTIME_CLASS(CDebugParamsPage), NULL }; static CRuntimeClass ** g_rgpprtcResTypePSPages[] = { g_rgprtcResTypePSPages, }; ///////////////////////////////////////////////////////////////////////////// // CExtObject ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::CExtObject // // Routine Description: // Default constructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CExtObject::CExtObject(void) { m_piData = NULL; m_bWizard = FALSE; m_istrResTypeName = 0; m_lcid = NULL; m_hfont = NULL; m_hicon = NULL; m_hcluster = NULL; m_cobj = 0; m_podObjData = NULL; } //*** CExtObject::CExtObject() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::~CExtObject // // Routine Description: // Destructor. // // Arguments: // None. // // Return Value: // None. // //-- ///////////////////////////////////////////////////////////////////////////// CExtObject::~CExtObject(void) { // Release the data interface. if (PiData() != NULL) { PiData()->Release(); m_piData = NULL; } // if: we have a data interface pointer // Delete the pages. { POSITION pos; pos = Lpg().GetHeadPosition(); while (pos != NULL) delete Lpg().GetNext(pos); } // Delete the pages delete m_podObjData; } //*** CExtObject::~CExtObject() ///////////////////////////////////////////////////////////////////////////// // ISupportErrorInfo Implementation ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo) // // Routine Description: // Indicates whether an interface suportes the IErrorInfo interface. // This interface is provided by ATL. // // Arguments: // riid Interface ID. // // Return Value: // S_OK Interface supports IErrorInfo. // S_FALSE Interface does not support IErrorInfo. // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo(REFIID riid) { static const IID * rgiid[] = { &IID_IWEExtendPropertySheet, }; int iiid; for (iiid = 0 ; iiid < sizeof(rgiid) / sizeof(rgiid[0]) ; iiid++) { if (InlineIsEqualGUID(*rgiid[iiid], riid)) return S_OK; } return S_FALSE; } //*** CExtObject::InterfaceSupportsErrorInfo() ///////////////////////////////////////////////////////////////////////////// // IWEExtendPropertySheet Implementation ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet) // // Routine Description: // Create property sheet pages and add them to the sheet. // // Arguments: // piData IUnkown pointer from which to obtain interfaces // for obtaining data describing the object for // which the sheet is being displayed. // piCallback Pointer to an IWCPropertySheetCallback interface // for adding pages to the sheet. // // Return Value: // NOERROR Pages added successfully. // E_INVALIDARG Invalid arguments to the function. // E_OUTOFMEMORY Error allocating memory. // E_FAIL Error creating a page. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IDataObject::GetData() (through HrSaveData()). // //-- ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CExtObject::CreatePropertySheetPages( IN IUnknown * piData, IN IWCPropertySheetCallback * piCallback ) { HRESULT hr = NOERROR; HPROPSHEETPAGE hpage = NULL; CException exc(FALSE /*bAutoDelete*/); CRuntimeClass ** pprtc = NULL; int irtc; CBasePropertyPage * ppage; AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Validate the parameters. if ((piData == NULL) || (piCallback == NULL)) return E_INVALIDARG; try { // Get info about displaying UI. hr = HrGetUIInfo(piData); if (hr != NOERROR) throw &exc; // Save the data. hr = HrSaveData(piData); if (hr != NOERROR) throw &exc; // Delete any previous pages. { POSITION pos; pos = Lpg().GetHeadPosition(); while (pos != NULL) delete Lpg().GetNext(pos); Lpg().RemoveAll(); } // Delete any previous pages // Create property pages. ASSERT(PodObjData() != NULL); switch (PodObjData()->m_cot) { case CLUADMEX_OT_RESOURCE: pprtc = g_rgpprtcResPSPages[0]; break; case CLUADMEX_OT_RESOURCETYPE: pprtc = g_rgpprtcResTypePSPages[0]; break; default: hr = E_NOTIMPL; throw &exc; break; } // switch: object type // Create each page. for (irtc = 0 ; pprtc[irtc] != NULL ; irtc++) { // Create the page. ppage = (CBasePropertyPage *) pprtc[irtc]->CreateObject(); ASSERT(ppage->IsKindOf(pprtc[irtc])); // Add it to the list. Lpg().AddTail(ppage); // Initialize the property page. if (!ppage->BInit(this)) throw &exc; // Create the page. hpage = ::CreatePropertySheetPage(&ppage->m_psp); if (hpage == NULL) throw &exc; // Save the hpage in the page itself. ppage->SetHpage(hpage); // Add it to the property sheet. hr = piCallback->AddPropertySheetPage((LONG *) hpage); if (hr != NOERROR) throw &exc; } // for: each page in the list } // try catch (CMemoryException * pme) { TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n")); pme->Delete(); hr = E_OUTOFMEMORY; } // catch: anything catch (CException * pe) { TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n")); pe->Delete(); if (hr == NOERROR) hr = E_FAIL; } // catch: anything if (hr != NOERROR) { if (hpage != NULL) ::DestroyPropertySheetPage(hpage); piData->Release(); m_piData = NULL; } // if: error occurred piCallback->Release(); return hr; } //*** CExtObject::CreatePropertySheetPages() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::HrGetUIInfo // // Routine Description: // Get info about displaying UI. // // Arguments: // piData IUnkown pointer from which to obtain interfaces // for obtaining data describing the object. // // Return Value: // NOERROR Data saved successfully. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(), // or HrGetResourceName(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CExtObject::HrGetUIInfo(IUnknown * piData) { HRESULT hr = NOERROR; ASSERT(piData != NULL); // Save info about all types of objects. { IGetClusterUIInfo * pi; hr = piData->QueryInterface(IID_IGetClusterUIInfo, (LPVOID *) &pi); if (hr != NOERROR) return hr; m_lcid = pi->GetLocale(); m_hfont = pi->GetFont(); m_hicon = pi->GetIcon(); pi->Release(); } // Save info about all types of objects return hr; } //*** CExtObject::HrGetUIInfo() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::HrSaveData // // Routine Description: // Save data from the object so that it can be used for the life // of the object. // // Arguments: // piData IUnkown pointer from which to obtain interfaces // for obtaining data describing the object. // // Return Value: // NOERROR Data saved successfully. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(), // or HrGetResourceName(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CExtObject::HrSaveData(IUnknown * piData) { HRESULT hr = NOERROR; ASSERT(piData != NULL); if (piData != m_piData) { if (m_piData != NULL) m_piData->Release(); m_piData = piData; } // if: different data interface pointer // Save info about all types of objects. { IGetClusterDataInfo * pi; hr = piData->QueryInterface(IID_IGetClusterDataInfo, (LPVOID *) &pi); if (hr != NOERROR) return hr; m_hcluster = pi->GetClusterHandle(); m_cobj = pi->GetObjectCount(); if (Cobj() != 1) // Only have support for one selected object. hr = E_NOTIMPL; pi->Release(); if (hr != NOERROR) return hr; } // Save info about all types of objects // Save info about this object. hr = HrGetObjectInfo(); if (hr != NOERROR) return hr; return hr; } //*** CExtObject::HrSaveData() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::HrGetObjectInfo // // Routine Description: // Get information about the object. // // Arguments: // None. // // Return Value: // NOERROR Data saved successfully. // E_OUTOFMEMORY Error allocating memory. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IUnknown::QueryInterface(), HrGetObjectName(), // or HrGetResourceTypeName(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CExtObject::HrGetObjectInfo(void) { HRESULT hr = NOERROR; IGetClusterObjectInfo * piGcoi; CLUADMEX_OBJECT_TYPE cot; CException exc(FALSE /*bAutoDelete*/); ASSERT(PiData() != NULL); // Get object info. { // Get an IGetClusterObjectInfo interface pointer. hr = PiData()->QueryInterface(IID_IGetClusterObjectInfo, (LPVOID *) &piGcoi); if (hr != NOERROR) return hr; // Read the object data. try { // Delete the previous object data. delete m_podObjData; m_podObjData = NULL; // Get the type of the object. cot = piGcoi->GetObjectType(0); switch (cot) { case CLUADMEX_OT_RESOURCE: { IGetClusterResourceInfo * pi; m_podObjData = new CResData; // Get an IGetClusterResourceInfo interface pointer. hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &pi); if (hr != NOERROR) throw &exc; PrdResDataRW()->m_hresource = pi->GetResourceHandle(0); hr = HrGetResourceTypeName(pi); pi->Release(); if (hr != NOERROR) throw &exc; } // if: object is a node break; case CLUADMEX_OT_RESOURCETYPE: m_podObjData = new CObjData; break; default: hr = E_NOTIMPL; throw &exc; } // switch: object type PodObjDataRW()->m_cot = cot; hr = HrGetObjectName(piGcoi); } // try catch (CException * pe) { pe->Delete(); } // catch: CException piGcoi->Release(); if (hr != NOERROR) return hr; } // Get object info return hr; } //*** CExtObject::HrGetObjectInfo() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::HrGetObjectName // // Routine Description: // Get the name of the object. // // Arguments: // piData IGetClusterObjectInfo interface pointer for getting // the object name. // // Return Value: // NOERROR Data saved successfully. // E_OUTOFMEMORY Error allocating memory. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IGetClusterObjectInfo::GetObjectInfo(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CExtObject::HrGetObjectName( IN OUT IGetClusterObjectInfo * pi ) { HRESULT hr = NOERROR; WCHAR * pwszName = NULL; LONG cchName; BSTR bstr = NULL; ASSERT(pi != NULL); hr = pi->GetObjectName(0, NULL, &cchName); if (hr != NOERROR) return hr; bstr = SysAllocStringLen( NULL, cchName ); if ( bstr != NULL ) { try { hr = pi->GetObjectName(0, bstr, &cchName); if (hr == NOERROR) { pwszName = new WCHAR[cchName]; hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) ); if ( FAILED( hr ) ) { goto Cleanup; } } PodObjDataRW()->m_strName = pwszName; } // try catch (CMemoryException * pme) { pme->Delete(); hr = E_OUTOFMEMORY; } // catch: CMemoryException } // if: ( bstr != NULL ) else { hr = E_OUTOFMEMORY; } Cleanup: delete [] pwszName; SysFreeString( bstr ); return hr; } //*** CExtObject::HrGetObjectName() ///////////////////////////////////////////////////////////////////////////// //++ // // CExtObject::HrGetResourceTypeName // // Routine Description: // Get the name of the resource's type. // // Arguments: // piData IGetClusterResourceInfo interface pointer for getting // the resource type name. // // Return Value: // NOERROR Data saved successfully. // E_OUTOFMEMORY Error allocating memory. // E_NOTIMPL Not implemented for this type of data. // Any error codes from IGetClusterResourceInfo::GetResourceTypeName(). // //-- ///////////////////////////////////////////////////////////////////////////// HRESULT CExtObject::HrGetResourceTypeName( IN OUT IGetClusterResourceInfo * pi ) { HRESULT hr = NOERROR; WCHAR * pwszName = NULL; LONG cchName; BSTR bstr = NULL; ASSERT(pi != NULL); hr = pi->GetResourceTypeName(0, NULL, &cchName); if (hr != NOERROR) return hr; bstr = SysAllocStringLen( NULL, cchName ); if ( bstr != NULL ) { try { hr = pi->GetResourceTypeName(0, bstr, &cchName); if (hr == NOERROR) { pwszName = new WCHAR[cchName]; hr = StringCchCopyNW( pwszName, cchName, bstr, SysStringLen( bstr ) ); if ( FAILED( hr ) ); { goto Cleanup; } } PrdResDataRW()->m_strResTypeName = pwszName; } // try catch (CMemoryException * pme) { pme->Delete(); hr = E_OUTOFMEMORY; } // catch: CMemoryException } // if: ( bstr != NULL ) else { hr = E_OUTOFMEMORY; } Cleanup: delete [] pwszName; SysFreeString( bstr ); return hr; } //*** CExtObject::HrGetResourceTypeName()