/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: CPropSht.cpp Abstract: Implementation of Property-Sheet-Like container object for property sheet pages. Author: Art Bragg 10/8/97 Revision History: --*/ ///////////////////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////////////////// #include "stdafx.h" // To make sure callbacks are in correct order: // PropPageCallback -> MMC Callback -> MFC Callback // This is because MMC only stores one pointer, and they want it // to be MFC's // note that pfnCallback has already been set to PropPageCallback HRESULT CSakPropertyPage::SetMMCCallBack( ) { HRESULT hr = S_OK; m_psp.pfnCallback = m_pMfcCallback; hr = MMCPropPageCallback( &( m_psp ) ); m_pMfcCallback = m_psp.pfnCallback; m_psp.pfnCallback = PropPageCallback; return( hr ); } // To make sure callbacks are in correct order: // PropPageCallback -> MMC Callback -> MFC Callback // This is because MMC only stores one pointer, and they want it // to be MFC's // note that pfnCallback has already been set to PropPageCallback HRESULT CSakWizardPage::SetMMCCallBack( ) { HRESULT hr = S_OK; m_psp.pfnCallback = m_pMfcCallback; hr = MMCPropPageCallback( &( m_psp ) ); m_pMfcCallback = m_psp.pfnCallback; m_psp.pfnCallback = PropPageCallback; return( hr ); } HRESULT CSakPropertySheet::InitSheet( RS_NOTIFY_HANDLE Handle, IUnknown* pUnkPropSheetCallback, CSakNode* pSakNode, ISakSnapAsk* pSakSnapAsk, IEnumGUID* pEnumObjectId, IEnumUnknown* pEnumUnkNode ) { WsbTraceIn( L"CSakPropertySheet::InitSheet", L"" ); HRESULT hr = S_OK; try { // // Set data members // WsbAffirmHr( RsQueryInterface( pUnkPropSheetCallback, IPropertySheetCallback, m_pPropSheetCallback ) ); m_pSakNode = pSakNode; m_Handle = Handle; m_bMultiSelect = pEnumObjectId ? TRUE : FALSE ; if( pSakNode ) { WsbAffirmHr( SetNode( pSakNode ) ); } // // Marshall ISakSnapAsk // WsbAffirmPointer( pSakSnapAsk ); WsbAffirmHr ( CoMarshalInterThreadInterfaceInStream( IID_ISakSnapAsk, pSakSnapAsk, &m_pSakSnapAskStream ) ); // // Store the GUIDs // if( pEnumObjectId ) { GUID objectId; while( pEnumObjectId->Next( 1, &objectId, NULL ) == S_OK) { m_ObjectIdList.Add( objectId ); } } // // Store the nodes // if( pEnumUnkNode ) { CComPtr pUnkNode; CComPtr pNode; pEnumUnkNode->Reset( ); while( pEnumUnkNode->Next( 1, &pUnkNode, NULL ) == S_OK ) { WsbAffirmHr( pUnkNode.QueryInterface( &pNode ) ); m_UnkNodeList.Add( pNode ); pUnkNode.Release( ); pNode.Release( ); } } } WsbCatch( hr ); WsbTraceOut( L"CSakPropertySheet::InitSheet", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakPropertySheet::SetNode( CSakNode* pSakNode ) { WsbTraceIn( L"CSakPropertySheet::SetNode", L"" ); HRESULT hr = S_OK; try { // // Marshall pHsmObj as an unknown // CComPtr pHsmObj; pSakNode->GetHsmObj( &pHsmObj ); if( pHsmObj ) { WsbAffirmHr ( CoMarshalInterThreadInterfaceInStream( IID_IUnknown, pHsmObj, &m_pHsmObjStream ) ); } } WsbCatch( hr ); WsbTraceOut( L"CSakPropertySheet::SetNode", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } CSakPropertySheet::~CSakPropertySheet() { WsbTraceIn( L"CSakPropertySheet::~CSakPropertySheet", L"" ); MMCFreeNotifyHandle( m_Handle ); WsbTraceOut( L"CSakPropertySheet::~CSakPropertySheet", L"" ); } HRESULT CSakPropertySheet::GetNextObjectId( INT *pBookMark, GUID *pObjectId ) { HRESULT hr = S_OK; try { WsbAffirm( *pBookMark >= 0, E_FAIL ); if( *pBookMark <= m_ObjectIdList.GetUpperBound( ) ) { *pObjectId = m_ObjectIdList[ *pBookMark ]; (*pBookMark)++; } else { // // We're done // WsbThrow ( S_FALSE ); } } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::GetNextNode( INT *pBookMark, ISakNode **ppNode ) { HRESULT hr = S_OK; try { WsbAffirm( *pBookMark >= 0, E_FAIL ); if( *pBookMark < m_UnkNodeList.length( ) ) { WsbAffirmHr( m_UnkNodeList.CopyTo( *pBookMark, ppNode ) ); (*pBookMark)++; } else { // // We're done // hr = S_FALSE; } } WsbCatch( hr ); return( hr ); } void CSakPropertySheet::AddPageRef() { m_nPageCount++; } void CSakPropertySheet::ReleasePageRef() { m_nPageCount--; // // Check to see if this is last reference // if( m_nPageCount <= 0 ) { delete( this ); } } HRESULT CSakPropertySheet::GetHsmObj( IUnknown **ppHsmObj ) { HRESULT hr = S_OK; try { if( !m_pHsmObj ) { // // Unmarhsall the pointer // WsbAffirmHr( CoGetInterfaceAndReleaseStream( m_pHsmObjStream, IID_IUnknown, (void **) &m_pHsmObj ) ); } m_pHsmObj.CopyTo( ppHsmObj ); } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::GetSakSnapAsk( ISakSnapAsk **ppAsk ) { HRESULT hr = S_OK; try { if ( !m_pSakSnapAsk ) { // // Unmarhsall the pointer // WsbAffirmHr( CoGetInterfaceAndReleaseStream( m_pSakSnapAskStream, IID_ISakSnapAsk, (void **) &m_pSakSnapAsk ) ); } m_pSakSnapAsk.CopyTo( ppAsk ); } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::GetHsmServer (IHsmServer **ppHsmServer) { HRESULT hr = S_OK; try { CComPtr pAsk; WsbAffirmHr( GetSakSnapAsk( &pAsk ) ); WsbAffirmHrOk( pAsk->GetHsmServer( ppHsmServer ) ); } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::GetFsaServer (IFsaServer **ppFsaServer) { HRESULT hr = S_OK; try { CComPtr pAsk; WsbAffirmHr( GetSakSnapAsk( &pAsk ) ); WsbAffirmHrOk( pAsk->GetFsaServer( ppFsaServer ) ); } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::GetRmsServer (IRmsServer **ppRmsServer) { HRESULT hr = S_OK; try { CComPtr pAsk; WsbAffirmHr( GetSakSnapAsk( &pAsk ) ); WsbAffirmHrOk( pAsk->GetRmsServer( ppRmsServer ) ); } WsbCatch( hr ); return( hr ); } HRESULT CSakPropertySheet::IsMultiSelect ( ) { return m_bMultiSelect ? S_OK : S_FALSE; } HRESULT CSakPropertySheet::OnPropertyChange( RS_NOTIFY_HANDLE hConsoleHandle, ISakNode* pNode ) { // // Called by a property sheet to notify MMC // HRESULT hr = S_OK; RS_PRIVATE_DATA privData; // // Notify the console that properties have changed for the node(s) // try { if( !m_bMultiSelect ) { // // Single Select // if( ! pNode ) { pNode = m_pSakNode; } WsbAffirmHr( pNode->GetPrivateData( &privData ) ); WsbAffirmHr( MMCPropertyChangeNotify( hConsoleHandle, (LPARAM)privData ) ); } else { // // Multi Select // INT bookMark = 0; CComPtr pNode; while( GetNextNode( &bookMark, &pNode ) == S_OK) { WsbAffirmHr( pNode->GetPrivateData( &privData ) ); WsbAffirmHr( MMCPropertyChangeNotify( hConsoleHandle, (LPARAM)privData ) ); pNode.Release( ); } } } WsbCatch( hr ); return( hr ); } // This function is to be called from the page thread HRESULT CSakPropertySheet::GetFsaFilter( IFsaFilter **ppFsaFilter ) { WsbTraceIn( L"CSakPropertySheet::GetFsaFilter", L"" ); HRESULT hr = S_OK; try { CComPtr pFsa; WsbAffirmHr( GetFsaServer( &pFsa ) ); // // Get the FsaFilter object // WsbAffirmHr( pFsa->GetFilter( ppFsaFilter ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakPropertySheet::GetFsaFilter", L"hr = <%ls>, *ppFsaFilter = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppFsaFilter ) ); return( hr ); } HRESULT CSakPropertySheet::AddPage( IN CSakPropertyPage* pPage ) { WsbTraceIn( L"CSakPropertySheet::AddPage", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // // Get the property sheet callback interface from the input param. // pPage->m_hConsoleHandle = m_Handle; pPage->m_pParent = this; WsbAffirmHr( pPage->SetMMCCallBack( ) ); HPROPSHEETPAGE hPage; hPage = CreatePropertySheetPage( &( pPage->m_psp ) ); WsbAffirmPointer( hPage ); AddPageRef( ); WsbAffirmHr( m_pPropSheetCallback->AddPage( hPage ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakPropertySheet::AddPage", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } CSakPropertyPage::CSakPropertyPage( UINT nIDTemplate, UINT nIDCaption ) : CRsPropertyPage( nIDTemplate, nIDCaption ), m_pParent( 0 ) { } void CSakPropertyPage::OnPageRelease( ) { if( m_pParent ) { m_pParent->ReleasePageRef( ); } delete this; } //////////////////////////////////////////////////////////////////////////////////////// // // class CSakVolPropSheet // // Supports property sheets for Managed volume and Managed Volume List // // HRESULT CSakVolPropSheet::GetFsaResource (IFsaResource **ppFsaResource) { WsbTraceIn( L"CSakVolPropSheet::GetFsaResource", L"" ); HRESULT hr = S_OK; try { // // Get the hsm object which is a CHsmManagedResource // CComPtr pUnk; WsbAffirmHr( GetHsmObj( &pUnk ) ); CComPtr pManRes; WsbAffirmHr( pUnk.QueryInterface( &pManRes ) ); // // Then Get Coresponding FSA resource // CComPtr pUnkFsaRes; WsbAffirmHr( pManRes->GetFsaResource( &pUnkFsaRes ) ); WsbAffirmHr( pUnkFsaRes.QueryInterface( ppFsaResource ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakVolPropSheet::GetFsaResource", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakVolPropSheet::AddPage( IN CSakVolPropPage* pPage ) { WsbTraceIn( L"CSakVolPropSheet::AddPage", L"" ); HRESULT hr = CSakPropertySheet::AddPage( pPage ); if( SUCCEEDED( hr ) ) { pPage->m_pVolParent = this; } WsbTraceOut( L"CSakVolPropSheet::AddPage", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } CSakVolPropPage::CSakVolPropPage( UINT nIDTemplate, UINT nIDCaption ) : CSakPropertyPage( nIDTemplate, nIDCaption ), m_pVolParent( 0 ) { } //////////////////////////////////////////////////////////////////////////////////////// // // class CSakWizardSheet // // Supports wizards created through MMC // // CSakWizardSheet::CSakWizardSheet( ) : m_HrFinish( RS_E_CANCELLED ), m_pFirstPage( 0 ) { } STDMETHODIMP CSakWizardSheet::GetWatermarks( OUT HBITMAP* pWatermark, OUT HBITMAP* pHeader, OUT HPALETTE* pPalette, OUT BOOL* pStretch ) { WsbTraceIn( L"CSakWizardSheet::GetWatermarks", L"" ); AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hr = S_OK; try { // // Have we loaded them yet? // if( ! m_Header.GetSafeHandle( ) ) { m_Header.LoadBitmap( m_HeaderId ); m_Watermark.LoadBitmap( m_WatermarkId ); } *pHeader = (HBITMAP)m_Header.GetSafeHandle( ); *pWatermark = (HBITMAP)m_Watermark.GetSafeHandle( ); *pStretch = TRUE; *pPalette = 0; } WsbCatch( hr ); WsbTraceOut( L"CSakWizardSheet::GetWatermarks", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakWizardSheet::GetTitle( OUT OLECHAR** pTitle ) { WsbTraceIn( L"CSakWizardSheet::GetTitle", L"" ); HRESULT hr = S_OK; try { // // Have we loaded yet? // if( m_Title.IsEmpty( ) ) { m_Title.LoadString( m_TitleId ); } // // Easiest way to CoTaskMemAlloc string // CWsbStringPtr title = m_Title; WsbAffirmHr( title.GiveTo( pTitle ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakWizardSheet::GetTitle", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } void CSakWizardSheet::AddPageRef() { ((ISakWizard*)this)->AddRef( ); } void CSakWizardSheet::ReleasePageRef() { ((ISakWizard*)this)->Release( ); } HRESULT CSakWizardSheet::AddPage( IN CSakWizardPage* pPage ) { WsbTraceIn( L"CSakWizardSheet::AddPage", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // // Need to track first page so that we can find true HWND of sheet // in later calls // if( ! m_pFirstPage ) { m_pFirstPage = pPage; } // // Take the caption from our sheet class and put it in the page // pPage->SetCaption( CString( m_Title ) ); // // Get the property sheet callback interface from the input param. // pPage->m_pSheet = this; WsbAffirmHr( pPage->SetMMCCallBack( ) ); HPROPSHEETPAGE hPage; hPage = pPage->CreatePropertyPage( ); WsbAffirmPointer( hPage ); AddPageRef( ); WsbAffirmHr( m_pPropSheetCallback->AddPage( hPage ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakWizardSheet::AddPage", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } void CSakWizardSheet::SetWizardButtons( DWORD Flags ) { WsbTraceIn( L"CSakWizardSheet::SetWizardButtons", L"" ); HRESULT hr = S_OK; try { WsbAffirmPointer( m_pFirstPage ); WsbAffirmHandle( m_pFirstPage->GetSafeHwnd( ) ); CPropertySheet* pSheet; pSheet = (CPropertySheet*)m_pFirstPage->GetParent( ); WsbAffirmPointer( pSheet ); pSheet->SetWizardButtons( Flags ); } WsbCatch( hr ); WsbTraceOut( L"CSakWizardSheet::SetWizardButtons", L"hr = <%ls>", WsbHrAsString( hr ) ); } BOOL CSakWizardSheet::PressButton( int Button ) { WsbTraceIn( L"CSakWizardSheet::PressButton", L"" ); HRESULT hr = S_OK; BOOL retVal = FALSE; try { WsbAffirmPointer( m_pFirstPage ); WsbAffirmHandle( m_pFirstPage->GetSafeHwnd( ) ); CPropertySheet* pSheet; pSheet = (CPropertySheet*)m_pFirstPage->GetParent( ); WsbAffirmPointer( pSheet ); retVal = pSheet->PressButton( Button ); } WsbCatch( hr ); WsbTraceOut( L"CSakWizardSheet::PressButton", L"hr = <%ls>", WsbHrAsString( hr ) ); return( retVal ); } CSakWizardPage::CSakWizardPage( UINT nIDTemplate, BOOL bExterior, UINT nIdTitle, UINT nIdSubtitle ) : CRsWizardPage( nIDTemplate, bExterior, nIdTitle, nIdSubtitle ), m_pSheet( 0 ) { } BOOL CSakWizardPage::OnWizardFinish( ) { WsbTraceIn( L"CSakWizardPage::OnWizardFinish", L"" ); // // Delegate the finish work to the sheet // m_pSheet->OnFinish( ); BOOL retval = CRsWizardPage::OnWizardFinish( ); WsbTraceOut( L"CSakWizardPage::OnWizardFinish", L"" ); return( retval ); } void CSakWizardPage::OnCancel( ) { WsbTraceIn( L"CSakWizardPage::OnCancel", L"" ); // // Since the Sheet does not receive an "OnCancel", we call it from the // page that will always exist - the intro // m_pSheet->OnCancel( ); CRsWizardPage::OnCancel( ); WsbTraceOut( L"CSakWizardPage::OnCancel", L"" ); } void CSakWizardPage::OnPageRelease( ) { if( m_pSheet ) { m_pSheet->ReleasePageRef( ); } }