/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: CSakData.cpp Abstract: This component implements the IComponentData interface for the snapin. Primarily it is responsible for handling the scope view panes. Author: Rohde Wakefield [rohde] 04-Mar-1997 Revision History: --*/ #include "stdafx.h" #include "HsmConn.h" #include "CSakSnap.h" #include "CSakData.h" #include "ChooHsm.h" #include "WzQstart.h" UINT CSakData::m_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME); UINT CSakData::m_cfNodeType = RegisterClipboardFormat(CCF_NODETYPE); UINT CSakData::m_cfNodeTypeString = RegisterClipboardFormat(CCF_SZNODETYPE); UINT CSakData::m_cfClassId = RegisterClipboardFormat(CCF_SNAPIN_CLASSID); UINT CSakData::m_cfObjectTypes = RegisterClipboardFormat(CCF_OBJECT_TYPES_IN_MULTI_SELECT); UINT CSakData::m_cfMultiSelect = RegisterClipboardFormat(CCF_MULTI_SELECT_SNAPINS); UINT CSakData::m_nImageArray[RS_SCOPE_IMAGE_ARRAY_MAX]; INT CSakData::m_nImageCount = 0; /////////////////////////////////////////////////////////////////////// // CSakData // // CSakData plays several roles in the snapin: // // 1) Provides the single entry into the HSM Admin Snapin by // implementing IComponentData // // 2) Provides the "Interface" for scopeview activities within MMC // // 3) Owns the node tree / objects // // 4) Provides a layer between MMC and the node objects // // 5) Act as its own data object for MMC's node manager, // // 6) Manages our portion of the MMC image lists. // /////////////////////////////////////////////////////////////////////// const CString CSakData::CParamParse::m_DsFlag = TEXT( "ds:" ); void CSakData::CParamParse::ParseParam( LPCTSTR lpszParam, BOOL bFlag, BOOL /* bLast */ ) { CString cmdLine = lpszParam; WsbTraceIn( L"CSakData::CParamParse::ParseParam", L"cmdLine = \"%ls\"\n", (LPCTSTR)cmdLine ); if( bFlag ) { // This is the "correct" code, but currently we don't get the DsFlag parameter // passed on the command line via Directory Services if( cmdLine.Left( m_DsFlag.GetLength( ) ) == m_DsFlag ) { CString dsToken; CWsbStringPtr computerName; dsToken = cmdLine.Mid( m_DsFlag.GetLength( ) ); if( SUCCEEDED( HsmGetComputerNameFromADsPath( dsToken, &computerName ) ) ) { m_HsmName = computerName; m_ManageLocal = FALSE; m_PersistManageLocal = FALSE; m_SetHsmName = TRUE; m_SetManageLocal = TRUE; m_SetPersistManageLocal = TRUE; } } } else { // This code is our stopgap measure until Directory Services starts // working the way it should if( cmdLine.Left( 5 ) == TEXT("LDAP:") ) { CWsbStringPtr computerName; if( SUCCEEDED( HsmGetComputerNameFromADsPath( cmdLine, &computerName ) ) ) { WsbTrace(L"CSakData::CParamParse::ParseParam: computerName = \"%ls\"\n", (OLECHAR*)computerName); m_HsmName = computerName; m_ManageLocal = FALSE; m_PersistManageLocal = FALSE; m_SetHsmName = TRUE; m_SetManageLocal = TRUE; m_SetPersistManageLocal = TRUE; } } } WsbTraceOut( L"CSakData::CParamParse::ParseParam", L"" ); } HRESULT CSakData::FinalConstruct( void ) /*++ Routine Description: Called during initial CSakData construction to initialize members. Arguments: none. Return Value: S_OK - Initialized correctly. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::FinalConstruct", L"" ); HRESULT hr = S_OK; AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); try { // // Init values // m_ManageLocal = FALSE; m_PersistManageLocal = TRUE; m_IsDirty = TRUE; m_State = FALSE; m_FirstTime = TRUE; m_Disabled = FALSE; m_RootNodeInitialized = FALSE; m_HrRmsConnect = S_FALSE; // // Create the hidden window so we can post messages back to self // m_pWnd = new CSakDataWnd; WsbAffirmPointer( m_pWnd ); WsbAffirmStatus( m_pWnd->Create( this ) ); // // Finally do low level ATL construct // WsbAffirmHr( CComObjectRoot::FinalConstruct( ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::FinalConstruct", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } void CSakData::FinalRelease( void ) /*++ Routine Description: Called on final release in order to clean up all members. Arguments: none. Return Value: none. --*/ { WsbTraceIn( L"CSakData::FinalRelease", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { if( m_pWnd ) { m_pWnd->DestroyWindow( ); m_pWnd = 0; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::FinalRelease", L"" ); } /////////////////////////////////////////////////////////////////////// // IComponentData // /////////////////////////////////////////////////////////////////////// STDMETHODIMP CSakData::Initialize( IN IUnknown * pUnk ) /*++ Routine Description: Called when the user first adds a snapin. Arguments: pUnk - Base IUnknown of console Return Value: S_OK - Correctly initialized. E_xxxxxxxxxxx - Unable to initialize. --*/ { WsbTraceIn( L"CSakData::Initialize", L"pUnk = <0x%p>", pUnk ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // // validity check on parameters // WsbAffirmPointer( pUnk ); // // QI and Save interfaces // WsbAffirmHr( RsQueryInterface( pUnk, IConsole, m_pConsole ) ); WsbAffirmHr( RsQueryInterface( pUnk, IConsoleNameSpace, m_pNameSpace ) ); // // Get the scope image list only and store it in the snapin. // It is AddRef'ed by the console // WsbAffirmHr( m_pConsole->QueryScopeImageList( &m_pImageScope ) ); // Create the root node (make sure not already set) WsbAffirmPointer( !m_pRootNode ); WsbAffirmHr( m_pRootNode.CoCreateInstance( CLSID_CUiHsmCom ) ); // // If the Hsm name has not been set (by choose Hsm), // do not initialize the node here. Allow // IPersistStream::Load to initialize it, or to be grabbed // from the extension's parent // if( m_ManageLocal || ( m_HsmName != "" ) ) { // // Make sure no changes from command line // InitFromCommandLine( ); // // Set the Hsm name in sakData and HsmCom objectds // WsbAffirmHr( InitializeRootNode( ) ); } WsbAffirmHr( OnAddImages() ); } WsbCatch( hr); WsbTraceOut( L"CSakData::Initialize", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::Notify( IN IDataObject* pDataObject, IN MMC_NOTIFY_TYPE event, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: Handle user clicks on nodes in the treeview, along with other MMC notices. Arguments: pDataObject - Data Object for which event occured event - The event type arg, param - Info for event (depend on type) Return Value: S_OK - Notification handled without error. E_xxxxxxxxxxx - Unable to register server. --*/ { WsbTraceIn( L"CSakData::Notify", L"pDataObject = <0x%p>, event = <%ls>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, RsNotifyEventAsString( event ), arg, arg, param, param ); HRESULT hr = S_OK; try { switch( event ) { // // This node was selected or deselected in the scope pane (the user clicked // on the expansion/contraction button) // case MMCN_EXPAND: WsbAffirmHr( OnFolder(pDataObject, arg, param) ); break; // // This node was expanded or contracted in the scope pane (the user // clicked on the actual node // case MMCN_SHOW: WsbAffirmHr( OnShow( pDataObject, arg, param ) ); break; // Not implemented case MMCN_SELECT: WsbAffirmHr( OnSelect( pDataObject, arg, param ) ); break; // Not implemented case MMCN_MINIMIZED: WsbAffirmHr( OnMinimize( pDataObject, arg, param ) ); break; case MMCN_ADD_IMAGES: WsbAffirmHr( OnAddImages() ); break; case MMCN_PROPERTY_CHANGE: { CComPtr pNode; WsbAffirmHr( GetBaseHsmFromCookie( (MMC_COOKIE) param, &pNode ) ); WsbAffirmHr( UpdateAllViews( pNode ) ); } break; case MMCN_CONTEXTHELP: WsbAffirmHr( OnContextHelp( pDataObject, arg, param ) ); break; case MMCN_REMOVE_CHILDREN: WsbAffirmHr( OnRemoveChildren( pDataObject ) ); break; // Note - Future expansion of notify types possible default: break; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::Notify", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::Destroy( void ) /*++ Routine Description: Called to force the release of any owned objects and to clear all views. Arguments: none. Return Value: S_OK - Correctly tore down. E_xxxxxxxxxxx - Failure occurred (not meaningful). --*/ { WsbTraceIn( L"CSakData::Destroy", L"" ); HRESULT hr = S_OK; try { // Release the interfaces that we QI'ed if( m_pConsole != NULL ) { // // Tell the console to release the header control interface // m_pNameSpace.Release(); m_pImageScope.Release(); // // Release the IConsole interface last // m_pConsole.Release(); } // Recursive delete list of UI nodes, including the root node. if( m_pRootNode ) { m_pRootNode->DeleteAllChildren( ); m_pRootNode->TerminateNode( ); m_pRootNode.Release( ); } m_pHsmServer.Release( ); m_pFsaServer.Release( ); m_pRmsServer.Release( ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::Destroy", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::QueryDataObject( IN MMC_COOKIE cookie, IN DATA_OBJECT_TYPES type, OUT IDataObject** ppDataObject ) /*++ Routine Description: Called by the console when it needs data for a particular node. Since each node is a data object, its IDataObject interface is simply returned. The console will later pass in this dataobject to SakSnap help it establish the context under which it is being called. Arguments: cookie - Node which is being queried. type - The context under which a dataobject is being requested. ppDataObject - returned data object. Return Value: S_OK - Data Object found and returned. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::QueryDataObject", L"cookie = <0x%p>, type = <%d>, ppDataObject = <0x%p>", cookie, type, ppDataObject ); HRESULT hr = S_OK; try { // // We return ourself if needing a root for the node manager // if( ( ( 0 == cookie ) || ( EXTENSION_RS_FOLDER_PARAM == cookie ) ) && ( CCT_SNAPIN_MANAGER == type ) ) { WsbAffirmHr( _InternalQueryInterface( IID_IDataObject, (void**)ppDataObject ) ); } else { WsbAffirmHr( GetDataObjectFromCookie ( cookie, ppDataObject ) ); WsbAffirmHr( SetContextType( *ppDataObject, type ) ); } } WsbCatch ( hr ) WsbTraceOut( L"CSakData::QueryDataObject", L"hr = <%ls>, *ppDataObject = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppDataObject ) ); return ( hr ); } STDMETHODIMP CSakData::CompareObjects( IN IDataObject* pDataObjectA, IN IDataObject* pDataObjectB ) /*++ Routine Description: Compare data objects for MMC Arguments: pDataObjectA, - Data object refering to node. pDataObjectB Return Value: S_OK - Objects represent the same node. S_FALSE - Objects do not represent the same node. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::CompareObjects", L"pDataObjectA = <0x%p>, pDataObjectB = <0x%p>", pDataObjectA, pDataObjectB ); HRESULT hr = S_OK; try { WsbAssertPointer ( pDataObjectA ); WsbAssertPointer ( pDataObjectB ); // // Since only one dataobject exists for any given node, // the QI's for IUnknown should match. (object identity) // CComPtr pUnkA, pUnkB; WsbAssertHr( RsQueryInterface( pDataObjectA, IUnknown, pUnkA ) ); WsbAssertHr( RsQueryInterface( pDataObjectB, IUnknown, pUnkB ) ); if ( (IUnknown*)pUnkA != (IUnknown*)pUnkB ) { hr = S_FALSE; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::CompareObjects", L"hr = <%ls>", WsbHrAsString( hr ) ); return ( hr ); } STDMETHODIMP CSakData::CreateComponent( OUT IComponent** ppComponent ) /*++ Routine Description: Creates a new Component object for MMC - our CSakSnap object. Arguments: ppComponent - Return value of the Component. Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::CreateComponent", L"ppComponent = <0x%p>", ppComponent ); HRESULT hr = S_OK; try { WsbAffirmPointer( ppComponent ); // // Create the Snapin Component as C++ object so we can init. // CSakSnap * pSnapin = new CComObject; WsbAffirmPointer( pSnapin ); // // Following code is based on ATL's CreateInstance // pSnapin->SetVoid( NULL ); pSnapin->InternalFinalConstructAddRef(); HRESULT hRes = pSnapin->FinalConstruct(); pSnapin->InternalFinalConstructRelease(); if( FAILED( hRes ) ) { delete pSnapin; pSnapin = NULL; WsbThrow( hRes ); } // // And QI for right interface // WsbAffirmHr ( pSnapin->_InternalQueryInterface( IID_IComponent, (void**)ppComponent ) ); // // Initialize internal pointer to CSakData // pSnapin->m_pSakData = this; } WsbCatch( hr ); WsbTraceOut( L"CSakData::CreateComponent", L"hr = <%ls>, *ppComponent = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppComponent ) ); return( hr ); } STDMETHODIMP CSakData::GetDisplayInfo( IN OUT SCOPEDATAITEM* pScopeItem ) /*++ Routine Description: When MMC is told to call back concerning scope items, we receive a call here to fill in missing information. Currently we do not use this capability. Arguments: pScopeItem - SCOPEDATAITEM structure representing state of the node in the scope treeview. Return Value: S_OK - Struct filled in. E_xxxxxxxxxxx - Failure occurred. --*/ { static CWsbStringPtr tmpString; WsbTraceIn( L"CSakData::GetDisplayInfo", L"cookie = <0x%p>, pScopeItem->mask = <0x%p>", pScopeItem->lParam, pScopeItem->mask ); HRESULT hr = S_OK; try { CComPtr pNode; CComPtr pNodeProp; WsbAffirmHr( GetBaseHsmFromCookie( pScopeItem->lParam, &pNode ) ); WsbAffirmHr( pNode.QueryInterface( &pNodeProp ) ); if( pScopeItem->mask & SDI_IMAGE ) { WsbAffirmHr( pNode->GetScopeOpenIcon( m_State, &pScopeItem->nImage ) ); } if( SDI_STR & pScopeItem->mask ) { // // Go to the node and get the display name. // Following the example of the snapin framework, we // copy the name into a static string pointer and // return a pointer to this. // CWsbBstrPtr bstr; WsbAffirmHr( pNodeProp->get_DisplayName( &bstr ) ); tmpString = bstr; pScopeItem->displayname = tmpString; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetDisplayInfo", L"hr = <%ls>, pScopeItem->displayname = <%ls>", WsbHrAsString( hr ), (SDI_STR & pScopeItem->mask) ? pScopeItem->displayname : L"N/A" ); return( hr ); } /////////////////////////////////////////////////////////////////////// // IExtendPropertySheet // /////////////////////////////////////////////////////////////////////// STDMETHODIMP CSakData::CreatePropertyPages( IN IPropertySheetCallback* pPropSheetCallback, IN RS_NOTIFY_HANDLE handle, IN IDataObject* pDataObject ) /*++ Routine Description: Console calls this when it is building a property sheet to show for a node. It is also called for the data object given to represent the snapin to the snapin manager, and should show the initial selection page at that point. Arguments: pPropSheetCallback - MMC interface to use to add page. handle - Handle to MMC to use to add the page. pDataObject - Data object refering to node. Return Value: S_OK - Pages added. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::CreatePropertyPages", L"pPropSheetCallback = <0x%p>, handle = <0x%p>, pDataObject = <0x%p>", pPropSheetCallback, handle, pDataObject ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // // Confirm parameters. // WsbAffirmPointer( pPropSheetCallback ); // WsbAffirmPointer( handle ); // Can be zero WsbAffirmPointer( pDataObject ); // // If DataObject is CSakData, we need to present user // with page for machine. Do this by checking for // support of IComponentData interface. // CComPtr pData; CComPtr pWizard; if( SUCCEEDED( RsQueryInterface( pDataObject, IComponentData, pData ) ) ) { // // Create the Hsm Choose property page. // HPROPSHEETPAGE hPage = 0; // Windows property page handle CChooseHsmDlg * pChooseDlg = new CChooseHsmDlg( ); WsbAffirmPointer( pChooseDlg ); pChooseDlg->m_hConsoleHandle = handle; pChooseDlg->m_pHsmName = &m_HsmName; pChooseDlg->m_pManageLocal = &m_ManageLocal; WsbAffirmHr( MMCPropPageCallback( &(pChooseDlg->m_psp) ) ); hPage = CreatePropertySheetPage( &pChooseDlg->m_psp ); WsbAffirmPointer( hPage ); pPropSheetCallback->AddPage( hPage ); } else if( SUCCEEDED( RsQueryInterface( pDataObject, ISakWizard, pWizard ) ) ) { WsbAffirmHr( pWizard->AddWizardPages( handle, pPropSheetCallback, this ) ); } else { // // Get node out of the dataobject. // CComPtr pNode; CComPtr pEnumObjectId; CComPtr pEnumUnkNode; // // Get the base hsm pointer depending on the data object type // WsbAffirmHr( GetBaseHsmFromDataObject( pDataObject, &pNode, &pEnumObjectId, &pEnumUnkNode ) ); // // Tell the node to add its property pages. pEnumObjectId will be NULL if // we are processing single-select. // WsbAffirmHr( pNode->AddPropertyPages( handle, pPropSheetCallback, pEnumObjectId, pEnumUnkNode ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::CreatePropertyPages", L"hr = <%ls>", WsbHrAsString( hr ) ); return ( hr ); } STDMETHODIMP CSakData::QueryPagesFor( IN IDataObject* pDataObject ) /*++ Routine Description: This method is called by MMC when it wants to find out if this node supports property pages. The answer is yes if: 1) The MMC context is either for the scope pane or result pane, AND 2) The node actually DOES have property pages. OR 1) The Data Object is acquired by the snapin manager. OR 1) It is a wizard data object Return S_OK if it DOES have pages, and S_FALSE if it does NOT have pages. Arguments: pDataObject - Data object refering to node. Return Value: S_OK - Pages exist. S_FALSE - No property pages. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::QueryPagesFor", L"pDataObject = <0x%p>", pDataObject ); HRESULT hr = S_FALSE; try { // // Confirm parameter. // WsbAffirmPointer( pDataObject ); // // If DataObject is CSakData, we need to present user // with page for machine. Do this by checking for // support of IComponentData interface, which is only // supported by CSakData. // CComPtr pData; CComPtr pWizard; if( SUCCEEDED( RsQueryInterface( pDataObject, IComponentData, pData ) ) || SUCCEEDED( RsQueryInterface( pDataObject, ISakWizard, pWizard ) ) ) { hr = S_OK; } else { // // Get node out of the dataobject. // CComPtr pBaseHsm; WsbAffirmHr( GetBaseHsmFromDataObject( pDataObject, &pBaseHsm ) ); // // Ask the node if it has property pages. // Ensure we did not get an error. // hr = pBaseHsm->SupportsProperties( FALSE ); WsbAffirmHr( hr ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::QueryPagesFor", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } /////////////////////////////////////////////////////////////////////// // IDataObject methods /////////////////////////////////////////////////////////////////////// STDMETHODIMP CSakData::GetDataHere( IN LPFORMATETC lpFormatetc, IN LPSTGMEDIUM lpMedium ) /*++ Routine Description: Retrieve information FROM the dataobject and put INTO lpMedium. Arguments: lpFormatetc - Format to retreive. lpMedium - Storage to put information into. Return Value: S_OK - Storage filled in. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::GetDataHere", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetc->cfFormat ) ); HRESULT hr = DV_E_CLIPFORMAT; // // Based on the CLIPFORMAT write data to "lpMedium" in the correct format. // const CLIPFORMAT cf = lpFormatetc->cfFormat; // // clip format is the Display Name // if( cf == m_cfDisplayName ) { hr = RetrieveDisplayName( lpMedium ); } // // clip format is the Node Type // else if( cf == m_cfNodeType ) { hr = RetrieveNodeTypeData( lpMedium ); } // // clip format is the Node Type // else if( cf == m_cfNodeTypeString ) { hr = RetrieveNodeTypeStringData( lpMedium ); } // // clip format is the ClassId // else if( cf == m_cfClassId ) { hr = RetrieveClsid( lpMedium ); } WsbTraceOut( L"CSakData::GetDataHere", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::SetData( IN LPFORMATETC lpFormatetc, IN LPSTGMEDIUM /*lpMedium*/, IN BOOL /*fRelease*/ ) /*++ Routine Description: Put data INTO a dataobject FROM the information in the lpMedium. We do not allow any data to be set. Arguments: lpFormatetc - Format to set. lpMedium - Storage to get information from. fRelease - Indicates who owns storage after call. Return Value: S_OK - Storage retreived. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::SetData", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetc->cfFormat ) ); HRESULT hr = DV_E_CLIPFORMAT; WsbTraceOut( L"CSakData::SetData", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } /////////////////////////////////////////////////////////////////////// // Note - CSakData does not implement these /////////////////////////////////////////////////////////////////////// STDMETHODIMP CSakData::GetData(LPFORMATETC lpFormatetcIn, LPSTGMEDIUM /*lpMedium*/) { WsbTraceIn( L"CSakData::GetData", L"lpFormatetc->cfFormat = <%ls>", RsClipFormatAsString( lpFormatetcIn->cfFormat ) ); HRESULT hr = E_NOTIMPL; WsbTraceOut( L"CSakData::GetData", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::EnumFormatEtc(DWORD /*dwDirection*/, LPENUMFORMATETC* /*ppEnumFormatEtc*/) { WsbTraceIn( L"CSakData::EnumFormatEtc", L"" ); HRESULT hr = E_NOTIMPL; WsbTraceOut( L"CSakData::EnumFormatEtc", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RetrieveDisplayName( OUT LPSTGMEDIUM lpMedium ) /*++ Routine Description: Retrieve from a dataobject with the display named used in the scope pane Arguments: lpMedium - Storage to set information into. Return Value: S_OK - Storage set. E_xxxxxxxxxxx - Failure occurred. --*/ { AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // // Load the name the data object // CString fullTitle; if( m_ManageLocal ) { fullTitle.LoadString( IDS_MANAGE_LOCAL ); } else if( !m_HsmName.IsEmpty( ) ) { AfxFormatString1( fullTitle, IDS_HSM_NAME_PREFIX, m_HsmName ); } else { fullTitle = HSMADMIN_NO_HSM_NAME; } WsbAffirmHr( Retrieve( fullTitle, ((wcslen( fullTitle ) + 1) * sizeof(wchar_t)), lpMedium ) ); } WsbCatch( hr ); return( hr ); } HRESULT CSakData::RetrieveNodeTypeData( LPSTGMEDIUM lpMedium ) /*++ Routine Description: Retrieve from a dataobject with the NodeType (GUID) data in it. Arguments: lpMedium - Storage to set information into. Return Value: S_OK - Storage set. E_xxxxxxxxxxx - Failure occurred. --*/ { return Retrieve( (const void*)(&cGuidHsmCom), sizeof(GUID), lpMedium ); } HRESULT CSakData::RetrieveClsid( LPSTGMEDIUM lpMedium ) /*++ Routine Description: Retrieve from a dataobject with the CLSID data in it. Arguments: lpMedium - Storage to set information into. Return Value: S_OK - Storage set. E_xxxxxxxxxxx - Failure occurred. --*/ { GUID guid = GetCoClassID(); return Retrieve( (const void*) &guid, sizeof(CLSID), lpMedium ); } HRESULT CSakData::RetrieveNodeTypeStringData( LPSTGMEDIUM lpMedium ) /*++ Routine Description: Retrieve from a dataobject with the node type object in GUID string format Arguments: lpMedium - Storage to set information into. Return Value: S_OK - Storage set. E_xxxxxxxxxxx - Failure occurred. --*/ { CWsbStringPtr guidString = cGuidHsmCom; return Retrieve( guidString, ((wcslen( guidString ) + 1 ) * sizeof(wchar_t)), lpMedium ); } HRESULT CSakData::Retrieve( IN const void* pBuffer, IN DWORD len, OUT LPSTGMEDIUM lpMedium) /*++ Routine Description: Retrieve FROM a dataobject INTO a lpMedium. The data object can be one of several types of data in it (nodetype, nodetype string, display name). This function moves data from pBuffer to the lpMedium->hGlobal Arguments: pBuffer - Buffer to copy contents out of. len - Length of buffer in bytes. lpMedium - Storage to set information into. Return Value: S_OK - Storage set. E_xxxxxxxxxxx - Failure occurred. --*/ { HRESULT hr = S_OK; try { // // Check Parameters // WsbAffirmPointer( pBuffer ); WsbAffirmPointer( lpMedium ); WsbAffirm( lpMedium->tymed == TYMED_HGLOBAL, E_FAIL ); // // Create the stream on the hGlobal passed in. When we write to the stream, // it simultaneously writes to the hGlobal the same information. // CComPtr lpStream; WsbAffirmHr( CreateStreamOnHGlobal( lpMedium->hGlobal, FALSE, &lpStream ) ); // // Write 'len' number of bytes from pBuffer into the stream. When we write // to the stream, it simultaneously writes to the global memory we // associated it with above. // ULONG numBytesWritten; WsbAffirmHr( lpStream->Write( pBuffer, len, &numBytesWritten ) ); } WsbCatch( hr ); return( hr ); } /////////////////////////////////////////////////////////////////////// // ISakSnapAsk /////////////////////////////////////////////////////////////////////// STDMETHODIMP CSakData::GetHsmName( OUT OLECHAR ** pszName OPTIONAL ) /*++ Routine Description: Retrieves the IUnknown pointer of a UI node given the node type. This will return the first node found of this type. Arguments: pszName - Return of the name of the computer (can be NULL). Return Value: S_OK - Managing remote machine - computer name given. S_FALSE - Managing local machine - *pszName set to local name. --*/ { WsbTraceIn( L"CSakData::GetHsmName", L"pszName = <0x%p>", pszName ); HRESULT hr = S_OK; try { CWsbStringPtr name = m_HsmName; if( m_ManageLocal ) { hr = S_FALSE; } if( pszName ) { WsbAffirmHr( name.GiveTo( pszName ) ); } } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetHsmName", L"hr = <%ls>, *pszName = <%ls>", WsbHrAsString( hr ), WsbPtrToStringAsString( pszName ) ); return( hr ); } STDMETHODIMP CSakData::GetNodeOfType( IN REFGUID nodetype, OUT ISakNode** ppNode ) /*++ Routine Description: Retrieves the IUnknown pointer of a UI node given the node type. This will return the first node found of this type. Arguments: nodetype - The GUID node type to look for. ppUiNode - returned IUnknown interface. Return Value: S_OK - Found. S_FALSE - No Error, not found. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetNodeOfType", L"nodetype = <%ls>, ppUiNode = <0x%p>", WsbGuidAsString( nodetype ), ppNode ); HRESULT hr = S_OK; try { // // Verify Params // WsbAffirmPointer( ppNode ); *ppNode = NULL; // // Call on base node to search down the node tree. // Save result, verify no error // CComPtr pBaseHsm; WsbAffirmHr( m_pRootNode.QueryInterface( &pBaseHsm ) ); hr = pBaseHsm->FindNodeOfType( nodetype, ppNode ); WsbAffirmHr( hr ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetNodeOfType", L"hr = <%ls>, *ppNode = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppNode ) ); return( hr ); } STDMETHODIMP CSakData::GetHsmServer( OUT IHsmServer** ppHsmServer ) /*++ Routine Description: Retrieve an interface pointer to the HSM server the snapin is managing. Arguments: ppHsmServer - returned HSM server interface pointer. Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetHsmServer", L"ppHsmServer = <0x%p>", ppHsmServer ); HRESULT hr = S_OK; try { // // Check Params // WsbAffirmPointer( ppHsmServer ); *ppHsmServer = 0; WsbAffirmHrOk( AffirmServiceConnection( HSMCONN_TYPE_HSM ) ); // // The connection should now be valid // WsbAffirmPointer( m_pHsmServer ); // // Return the connection to the caller // m_pHsmServer.CopyTo( ppHsmServer ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetHsmServer", L"hr = <%ls>, *ppHsmServer = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppHsmServer ) ); return( hr ); } STDMETHODIMP CSakData::GetRmsServer( OUT IRmsServer** ppRmsServer ) /*++ Routine Description: Retrieve an interface pointer to the RMS server the snapin is managing. Arguments: ppRmsServer - returned HSM server interface pointer. Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetRmsServer", L"ppRmsServer = <0x%p>", ppRmsServer ); HRESULT hr = S_OK; try { // // Check Params // WsbAffirmPointer( ppRmsServer ); *ppRmsServer = 0; WsbAffirmHrOk( AffirmServiceConnection( HSMCONN_TYPE_RMS ) ); // // We should now be connected // WsbAffirmPointer( m_pRmsServer ); m_pRmsServer.CopyTo( ppRmsServer ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetRmsServer", L"hr = <%ls>, *ppRmsServer = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppRmsServer ) ); return( hr ); } STDMETHODIMP CSakData::GetFsaServer( OUT IFsaServer** ppFsaServer ) /*++ Routine Description: Retrieve an interface pointer to the Fsa server the snapin is managing. Arguments: ppFsaServer - returned HSM server interface pointer. Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetFsaServer", L"ppFsaServer = <0x%p>", ppFsaServer ); HRESULT hr = S_OK; try { // // Check Params // WsbAffirmPointer( ppFsaServer ); *ppFsaServer = 0; WsbAffirmHrOk( AffirmServiceConnection( HSMCONN_TYPE_FSA ) ); WsbAffirmPointer( m_pFsaServer ); m_pFsaServer.CopyTo( ppFsaServer ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetFsaServer", L"hr = <%ls>, *ppFsaServer = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppFsaServer ) ); return( hr ); } STDMETHODIMP CSakData::ShowPropertySheet( IN ISakNode* pNode, IN IDataObject* pDataObject, IN INT initialPage ) /*++ Routine Description: Create a property sheet for this node with the given page displayed on top Arguments: pNode - node to show property sheet for initialPage - 0 based index of initial page to show Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::ShowPropertySheet", L"pNode = <0x%p>, initialPage = <%d>", pNode, initialPage ); HRESULT hr = S_OK; HRESULT hrInternal = S_OK; try { WsbAffirmPointer( pNode ); // // Get the property sheet provider interface from IConsole // CComPtr pProvider; WsbAffirmHr( m_pConsole.QueryInterface( &pProvider ) ); // // Get the component data pointer // CComPtr pComponent; pComponent = (IComponent *) this; // // If the sheet is already loaded, just show it // hrInternal = pProvider->FindPropertySheet( 0, pComponent, pDataObject ); if( hrInternal != S_OK ) { // // Not loaded, create it // CComPtr pNodeProp; WsbAffirmHr( RsQueryInterface( pNode, ISakNodeProp, pNodeProp ) ); CWsbBstrPtr pszName; WsbAffirmHr( pNodeProp->get_DisplayName( &pszName ) ); // // If multiselect, append ellipses // if( IsDataObjectMultiSelect( pDataObject ) == S_OK ) { pszName.Append( L", ..."); } // // Create the property sheet // WsbAffirmHr( pProvider->CreatePropertySheet (pszName, TRUE, 0, pDataObject, 0 ) ); // // Tell the IComponentData interface to add pages // CComPtr pUnkComponentData; pUnkComponentData = (IUnknown *) (IComponentData*) this; WsbAffirmHr( pProvider->AddPrimaryPages( pUnkComponentData, TRUE, 0, TRUE ) ); WsbAffirmHr( pProvider->Show( 0, initialPage ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::ShowPropertySheet", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::RefreshNode( IN ISakNode* pNode ) /*++ Routine Description: Refresh scope pane from this node on down Arguments: pNode - node to refresh Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::RefreshNode", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; try { WsbAffirmPointer( m_pWnd->GetSafeHwnd( ) ); // // Post it to handle later // MMC_COOKIE cookie; WsbAffirmHr( GetCookieFromBaseHsm( pNode, &cookie ) ); m_pWnd->PostRefreshNode( cookie ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::RefreshNode", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::InternalRefreshNode( IN MMC_COOKIE Cookie ) /*++ Routine Description: Refresh scope pane from this node on down. Arguments: pNode - node to refresh Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::InternalRefreshNode", L"Cookie = <0x%p>", Cookie ); HRESULT hr = S_OK; try { // // Decode the node, make sure still exists // CComPtr pNode; WsbAffirmHr( GetBaseHsmFromCookie( Cookie, &pNode ) ); // // Recursively update tree // WsbAffirmHr( RefreshNodeEx( pNode ) ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::InternalRefreshNode", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RefreshNodeEx( IN ISakNode* pNode ) /*++ Routine Description: Refresh scope pane from this node on down. This is recursively called. Arguments: pNode - node to refresh Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::RefreshNodeEx", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; try { // // Refresh this node // WsbAffirmHr( pNode->RefreshObject( ) ); // // Refresh Icon and Text if container // if( S_OK == pNode->IsContainer( ) ) { SCOPEDATAITEM sdi; ZeroMemory( &sdi, sizeof sdi ); sdi.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE; WsbAffirmHr( pNode->GetScopeID( &sdi.ID ) ); sdi.displayname = MMC_CALLBACK; WsbAffirmHr( pNode->GetScopeCloseIcon( m_State, &sdi.nImage ) ); WsbAffirmHr( pNode->GetScopeOpenIcon( m_State, &sdi.nOpenImage ) ); WsbAffirmHr( m_pNameSpace->SetItem( &sdi ) ); } // // If this is a container with dynamic children, then we // want to just cause our contents to be recreated // if( S_OK == pNode->HasDynamicChildren( ) ) { WsbAffirmHr( FreeEnumChildren( pNode ) ); WsbAffirmHr( pNode->InvalidateChildren() ) WsbAffirmHr( EnsureChildrenAreCreated( pNode ) ); HSCOPEITEM scopeID; WsbAffirmHr( pNode->GetScopeID( &scopeID ) ); WsbAffirmHr( EnumScopePane( pNode, (HSCOPEITEM)( scopeID ) ) ); } else { // // Loop over the children and call // CComPtr pEnum; if( ( pNode->EnumChildren( &pEnum ) ) == S_OK ) { CComPtr pChildNode; CComPtr pUnk; while( S_OK == pEnum->Next( 1, &pUnk, NULL ) ) { WsbAffirmHr( pUnk.QueryInterface( &pChildNode ) ); WsbAffirmHr( RefreshNodeEx( pChildNode ) ); // // must release even for smart pointer because of re-assign. // pChildNode.Release( ); pUnk.Release( ); } } } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::RefreshNodeEx", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::InternalUpdateAllViews( IN MMC_COOKIE Cookie ) /*++ Routine Description: Calls MMC to update all views Arguments: pUnkNode - node to refresh Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::InternalUpdateAllViews", L"Cookie = <0x%p>", Cookie ); HRESULT hr = S_OK; try { // // Decode the node // CComPtr pDataObject; WsbAffirmHr( GetDataObjectFromCookie( Cookie, &pDataObject ) ); // // Call MMC // WsbAffirmHr( m_pConsole->UpdateAllViews( pDataObject, 0L, 0L ) ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::InternalUpdateAllViews", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::UpdateAllViews ( IN ISakNode* pNode ) /*++ Routine Description: Calls MMC to update all views Arguments: pUnkNode - node to refresh Return Value: S_OK - Return fine. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::UpdateAllViews", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; try { WsbAffirmPointer( m_pWnd->GetSafeHwnd( ) ); // // Post it to handle later // MMC_COOKIE cookie; WsbAffirmHr( GetCookieFromBaseHsm( pNode, &cookie ) ); m_pWnd->PostUpdateAllViews( cookie ); } WsbCatch ( hr ); WsbTraceOut( L"CSakData::UpdateAllViews", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } /////////////////////////////////////////////////////////////////////// // Node type manipulation routines /////////////////////////////////////////////////////////////////////// HRESULT CSakData::GetBaseHsmFromDataObject ( IN IDataObject *pDataObject, OUT ISakNode **ppBaseHsm, OUT IEnumGUID **ppEnumObjectId, OUT IEnumUnknown **ppEnumUnkNode ) /*++ Routine Description: Retrieves the ISakNode for the object referenced by the given data object. Arguments: pDataObject - identifies the node to be worked on. ppBaseHSM - returned IBaseHSM interface. ppEnumObjectId - returned interface to enumeration of object Ids. Can be NULL. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetBaseHsmFromDataObject", L"pDataObject = <0x%p>, ppBaseHsm = <0x%p>, ppEnumObjectId = <0x%p>", pDataObject, ppBaseHsm, ppEnumObjectId ); HRESULT hr = S_OK; try { *ppBaseHsm = 0; if ( ppEnumObjectId ) *ppEnumObjectId = NULL; // // Get the base hsm pointer depending on the data object type // if (IsDataObjectMs( pDataObject ) == S_OK) { WsbAffirmHr( GetBaseHsmFromMsDataObject( pDataObject, ppBaseHsm, ppEnumObjectId, ppEnumUnkNode ) ); } else if (IsDataObjectOt( pDataObject ) == S_OK) { WsbAffirmHr( GetBaseHsmFromOtDataObject( pDataObject, ppBaseHsm, ppEnumObjectId, ppEnumUnkNode ) ); } else { // Assume single select WsbAffirmPointer( pDataObject ); WsbAffirmHr( RsQueryInterface2( pDataObject, ISakNode, ppBaseHsm ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetBaseHsmFromDataObject", L"hr = <%ls>, *ppBaseHsm = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppBaseHsm ) ); return ( hr ); } HRESULT CSakData::GetBaseHsmFromMsDataObject ( IN IDataObject *pDataObject, OUT ISakNode **ppBaseHsm, OUT IEnumGUID **ppEnumObjectId, OUT IEnumUnknown **ppEnumUnkNode ) /*++ Routine Description: Retrieves the ISakNode for the object referenced by the given data object. Arguments: pDataObject - identifies the node to be worked on. ppBaseHSM - returned IBaseHSM interface. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetBaseHsmFromMsDataObject", L"pDataObject = <0x%p>, ppBaseHsm = <0x%p>", pDataObject, ppBaseHsm ); HRESULT hr = S_OK; try { // We've got an MMC mutli-select data object. Get the first // data object from it's array of data objects FORMATETC fmt = {(CLIPFORMAT)m_cfMultiSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgm = {TYMED_HGLOBAL, NULL}; WsbAffirmHr ( pDataObject->GetData( &fmt, &stgm ) == S_OK ); DWORD count; memcpy( &count, stgm.hGlobal, sizeof (DWORD) ); if ( count > 0 ) { // // The following code is admittedly UGLY // We have a data stream where we need to skip past the // first DWORD count and grab an interface pointer. // Other snapins code does it as follows: // IDataObject * pDO; // memcpy( &pDO, (DWORD *) stgm.hGlobal + 1, sizeof(IDataObject*) ); // // However, since this code does an indirect cast (via memcpy) // from DWORD to IDataObject*, and does not keep a true reference // on the interface pointer, we will use a smart pointer. // The (DWORD*) and +1 operation bump our pointer past the count. // We then need to grab the next bytes in the buffer and use them // as a IDataObject *. // CComPtr pOtDataObject; pOtDataObject = *( (IDataObject**)( (DWORD *) stgm.hGlobal + 1 ) ); // // Note: When we can be extended we need to check to see if this is one of ours // WsbAffirmHr( GetBaseHsmFromOtDataObject ( pOtDataObject, ppBaseHsm, ppEnumObjectId, ppEnumUnkNode ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetBaseHsmFromMsDataObject", L"hr = <%ls>, *ppBaseHsm = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppBaseHsm ) ); return ( hr ); } HRESULT CSakData::GetBaseHsmFromOtDataObject ( IN IDataObject *pDataObject, OUT ISakNode **ppBaseHsm, OUT IEnumGUID **ppEnumObjectId, OUT IEnumUnknown **ppEnumUnkNode ) /*++ Routine Description: Retrieves the ISakNode for the object referenced by the given data object. Arguments: pDataObject - identifies the node to be worked on. ppBaseHSM - returned IBaseHSM interface. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetBaseHsmFromOtDataObject", L"pDataObject = <0x%p>, ppBaseHsm = <0x%p>", pDataObject, ppBaseHsm ); HRESULT hr = S_OK; try { // we've got an object types mutli-select data object. Get the first node selected // from the data object. CComPtr pMsDataObject; CComPtr pUnkNode; CComPtr pEnumUnkNode; CComPtr pNode; WsbAffirmHr( RsQueryInterface( pDataObject, IMsDataObject, pMsDataObject ) ); WsbAffirmHr( pMsDataObject->GetNodeEnumerator( &pEnumUnkNode ) ); WsbAffirmHr( pEnumUnkNode->Next( 1, &pUnkNode, NULL ) ); WsbAffirmHr( pUnkNode.QueryInterface( &pNode ) ); WsbAffirmHr( pEnumUnkNode->Reset() ); // This enumeration is passed on, so we must reset it if( ppBaseHsm ) { pNode.CopyTo( ppBaseHsm ); } if( ppEnumObjectId ) { pMsDataObject->GetObjectIdEnumerator( ppEnumObjectId ); } if( ppEnumUnkNode ) { pEnumUnkNode.CopyTo( ppEnumUnkNode ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetBaseHsmFromOtDataObject", L"hr = <%ls>, *ppBaseHsm = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppBaseHsm ) ); return ( hr ); } HRESULT CSakData::GetDataObjectFromBaseHsm ( IN ISakNode * pBaseHsm, OUT IDataObject* *ppDataObject ) /*++ Routine Description: Retrieves the dataobject for the object referenced by the given IBaseHSM. Arguments: pBaseHsm - identifies the node to be worked on. ppDataObject - returned IDataObject interface. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetDataObjectFromBaseHsm", L"pBaseHsm = <0x%p>, ppDataObject = <0x%p>", pBaseHsm, ppDataObject ); HRESULT hr = S_OK; try { *ppDataObject = 0; if( pBaseHsm ) { WsbAffirmHr( RsQueryInterface2( pBaseHsm, IDataObject, ppDataObject ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::GetDataObjectFromBaseHsm", L"hr = <%ls>, *ppDataObject = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppDataObject ) ); return ( hr ); } HRESULT CSakData::GetBaseHsmFromCookie ( IN MMC_COOKIE Cookie, OUT ISakNode ** ppBaseHsm ) /*++ Routine Description: Retrieves the ISakNode for the object referenced by the given cookie. Arguments: Cookie - identifies the node to be worked on. ppBaseHsm - returned ISakNode interface. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetBaseHsmFromCookie", L"Cookie = <0x%p>, ppBaseHsm = <0x%p>", Cookie, ppBaseHsm ); HRESULT hr = S_OK; try { // // Cookies are pointers to CSakDataNodePrivate classes, which // contain smart pointers to their nodes. // NULL cookie means root snapin. // if( ( 0 == Cookie ) || ( EXTENSION_RS_FOLDER_PARAM == Cookie ) ) { WsbAffirmHr( GetCookieFromBaseHsm( m_pRootNode, &Cookie ) ); } WsbAffirmPointer( Cookie ); CSakDataNodePrivate* pNodePriv = (CSakDataNodePrivate*)Cookie; WsbAffirmHr( CSakDataNodePrivate::Verify( pNodePriv ) ); WsbAffirmHr( pNodePriv->m_pNode.QueryInterface( ppBaseHsm ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetBaseHsmFromCookie", L"hr = <%ls>, *ppBaseHsm = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppBaseHsm ) ); return ( hr ); } HRESULT CSakData::GetCookieFromBaseHsm ( IN ISakNode * pNode, OUT MMC_COOKIE * pCookie ) /*++ Routine Description: Retrieves the cookie for the object referenced by the given IBaseHSM. Arguments: pBaseHsm - identifies the node to be worked on. pCookie - returned Cookie. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetCookieFromBaseHsm", L"pNode = <0x%p>, pCookie = <0x%p>", pNode, pCookie ); HRESULT hr = S_OK; try { WsbAffirmPointer( pNode ); // // Ask the node for our private data back // RS_PRIVATE_DATA data; WsbAffirmHr( pNode->GetPrivateData( &data ) ); if( !data ) { CSakDataNodePrivate *pNodePriv = new CSakDataNodePrivate( pNode ); WsbAffirmAlloc( pNodePriv ); WsbAffirmHr( pNode->GetPrivateData( &data ) ); } WsbAffirmHr( CSakDataNodePrivate::Verify( (CSakDataNodePrivate*)data ) ); *pCookie = (MMC_COOKIE)data; } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetCookieFromBaseHsm", L"hr = <%ls>, *pCookie = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)pCookie ) ); return( hr ); } HRESULT CSakData::GetDataObjectFromCookie ( IN MMC_COOKIE Cookie, OUT IDataObject **ppDataObject ) /*++ Routine Description: Retrieves the IDataObject for the object referenced by the given cookie. Arguments: Cookie - identifies the node to be worked on. ppDataObject - returned IDataObject interface. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::GetDataObjectFromCookie", L"Cookie = <0x%p>, ppDataObject = <0x%p>", Cookie, ppDataObject ); HRESULT hr = S_OK; try { // // Check Params // WsbAffirmPointer( ppDataObject ); // // Use GetBaseHsmFromCookie to resolve to node object // CComPtr pNode; WsbAffirmHr( GetBaseHsmFromCookie( Cookie, &pNode ) ); WsbAffirmPointer( pNode ); WsbAffirmHr( RsQueryInterface2( pNode, IDataObject, ppDataObject ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetDataObjectFromCookie", L"hr = <%ls>, *ppDataObject = <%ls>", WsbHrAsString( hr ), WsbPtrToPtrAsString( (void**)ppDataObject ) ); return( hr ); } HRESULT CSakData::SetContextType( IDataObject* pDataObject, DATA_OBJECT_TYPES type ) /*++ Routine Description: Set the MMC context type in the data object for later retrieval by any method which receives this dataobject (CCT_SNAPIN_MANAGER, CCT_SCOPE, CCT_RESULT, etc). Arguments: pDataObject - identifies the node to be worked on. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::SetContextType", L"pDataObject = <0x%p>, type = <%d>", pDataObject, type ); // Prepare structures to store an HGLOBAL from the dataobject. // Allocate memory for the stream which will contain the SakSnap GUID. STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)CSakNode::m_cfInternal, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = S_OK; try { // Allocate space in which to place the data stgmedium.hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(INTERNAL)); WsbAffirm( stgmedium.hGlobal != NULL, E_POINTER ); // Put the data into the global memory. This is what will eventually be // copied down into the member variables of the dataobject, itself. memcpy(&stgmedium.hGlobal, &type, sizeof(type)); // Copy this data into the dataobject. WsbAffirmHr( pDataObject->SetData(&formatetc, &stgmedium, FALSE )); } WsbCatch( hr ); WsbTraceOut( L"CSakData::SetContextType", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::InitializeRootNode( void ) /*++ Routine Description: The initialization of the root node is separate in order to allow reconnect multiple times (as needed). This is the implementation of initialization. Arguments: pDataObject - identifies the node to be worked on. Return Value: S_OK - Node found and returned. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::InitializeRootNode", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); HRESULT hr = S_OK; try { // Make sure the computer name is set in CSakdata if we are managing the local // Hsm if( m_ManageLocal ) { WCHAR computerName[ MAX_COMPUTERNAME_LENGTH + 1 ]; DWORD dw = MAX_COMPUTERNAME_LENGTH + 1; GetComputerName( computerName, &dw ); m_HsmName = computerName; } // // Initialize the static root node (no recursion. Descendants are NOT created here) // WsbAffirmPointer( m_pRootNode ); WsbAffirmHr( m_pRootNode->InitNode( (ISakSnapAsk*)this, NULL, NULL ) ); // // Set the Display Name in the object // CString fullTitle; if( IsPrimaryImpl( ) ) { // // We're standalone, so show the targeted server // if( m_ManageLocal ) { fullTitle.LoadString( IDS_MANAGE_LOCAL ); } else if( !m_HsmName.IsEmpty( ) ) { AfxFormatString1( fullTitle, IDS_HSM_NAME_PREFIX, m_HsmName ); } else { fullTitle = HSMADMIN_NO_HSM_NAME; } } else { // // We're an extension, so just show app name // fullTitle.LoadString( AFX_IDS_APP_TITLE ); } // Put the displayname CComPtr pRootNodeProp; WsbAffirmHr( RsQueryInterface( m_pRootNode, ISakNodeProp, pRootNodeProp ) ); WsbAffirmHr( pRootNodeProp->put_DisplayName( (LPWSTR)(LPCWSTR) fullTitle ) ); WsbAffirmHr( m_pRootNode->RefreshObject() ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::InitializeRootNode", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::AffirmServiceConnection( INT ConnType ) /*++ Routine Description: Validates that the connection to the requested HSM service is still valid. If not, attempts to reconnect to the service. Arguments: ConnType - type of service connection being checked Return Value: S_OK - Node created and bound to server. S_FALSE - Service has not yet been setup or stopped. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::AffirmServiceConnection", L"" ); HRESULT hr = S_OK; AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); BOOL previouslyConnected = ( GetState() == S_OK ); BOOL firstTime = m_FirstTime; CString szMessage; CWsbStringPtr computerName; try { // // Handle this first so reentrancy is not a problem // if( m_FirstTime ) { m_FirstTime = FALSE; } WsbAffirmHr( WsbGetComputerName( computerName ) ); // // See if snapin is supposed to be disabled. If so, then // don't do anything. // if( m_Disabled ) { WsbThrow( RS_E_DISABLED ); } // // We want to avoid starting the services if they are stopped. // So, check the service state before continuing. // HRESULT hrCheck; { // // Potentially a long operation - show wait cursor if possible // CWaitCursor waitCursor; hrCheck = WsbCheckService( m_HsmName, APPID_RemoteStorageEngine ); } if( S_FALSE == hrCheck ) { // // Engine service is not running // WsbThrow( S_FALSE ); } else if( ( HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) == hrCheck ) || ( E_ACCESSDENIED == hrCheck ) ) { // // Engine is not installed (or at least we can't check // because local privs don't allow, but may on a different // server) // // If we are set to "Manage Local" then we will provide the // opportunity to look at a different machine // if( firstTime && m_ManageLocal ) { // // If we get back "File not found" then the engine was // not installed, so we need to ask for a different machine // to administer // hrCheck = RetargetSnapin( ); WsbAffirmHrOk( hrCheck ); } else { // // we want to return the true error if access is denied // and can't retarget to another machine without same error // if( E_ACCESSDENIED == hrCheck ) { WsbThrow( hrCheck ); } else { WsbThrow( RS_E_NOT_INSTALLED ); } } } // // Is the current connection still valid? // Test the connection. If it's OK, return it. If not, // re-establish the connection. // HRESULT hrConnected = VerifyConnection( ConnType ); WsbAffirmHr( hrConnected ); // // If it looks like we're not connected, then connect // if( S_FALSE == hrConnected ) { // // Connect to engine first and see if we are setup. // Don't process any further if not setup. // WsbAffirmHr( RawConnect( HSMCONN_TYPE_HSM ) ); HRESULT hrSetup = RsIsRemoteStorageSetupEx( m_pHsmServer ); WsbAffirmHr( hrSetup ); if( S_FALSE == hrSetup ) { // // Not setup - see if we are local // if( computerName.IsEqual( m_HsmName ) && firstTime ) { hrSetup = RunSetupWizard( m_pHsmServer ); } // // By this point, if hrSetup is not S_OK, // we are not configured. // if( S_OK != hrSetup ) { WsbThrow( RS_E_NOT_CONFIGURED ); } } // // At this point we should be setup and ready to connect // WsbAffirmHrOk( RawConnect( ConnType ) ); } // // We're connected // SetState( TRUE ); } WsbCatchAndDo( hr, // // Need to decide if we should ignore the error or not. // Note that even if the error is ignored here, its // returned still to the caller // BOOL ignoreError = FALSE; // // if RMS error of not ready, and we received this last time RMS // connection was made, ignore the error. // if( HSMCONN_TYPE_RMS == ConnType ) { HRESULT hrPrevConnect = m_HrRmsConnect; m_HrRmsConnect = hr; if( ( RsIsRmsErrorNotReady( hr ) == S_OK ) && ( RsIsRmsErrorNotReady( hrPrevConnect ) == S_OK ) ) { ignoreError = TRUE; } } if( !ignoreError ) { // // Set up state conditions before anything else // ClearConnections( ); SetState( FALSE ); // // If we were previously connected or this is the first connect, // report the error // if( previouslyConnected || firstTime ) { // // Temporarily set to disable so we don't recurse when dialog is up // BOOL disabled = m_Disabled; m_Disabled = TRUE; CString msg; switch( hr ) { case S_OK: // // Connected OK - no error // break; case RS_E_DISABLED: // // Disabled - just ignore // break; case S_FALSE: // // Service not running // AfxFormatString1( msg, IDS_ERR_SERVICE_NOT_RUNNING, m_HsmName ); AfxMessageBox( msg, RS_MB_ERROR ); break; case RS_E_NOT_CONFIGURED: // // If remote, let user know it needs to be set up locally // if( ! computerName.IsEqual( m_HsmName ) ) { AfxFormatString1( msg, IDS_ERR_SERVICE_NOT_SETUP_REMOTE, m_HsmName ); AfxMessageBox( msg, RS_MB_ERROR ); } break; case RS_E_NOT_INSTALLED: // // Give indication of where this can be setup // AfxFormatString1( msg, IDS_ERR_SERVICE_NOT_INSTALLED, m_HsmName ); AfxMessageBox( msg, RS_MB_ERROR ); break; case RS_E_CANCELLED: // // User cancelled - there's no error to notify // break; default: // // Report the error // AfxFormatString1( msg, IDS_ERR_SERVICE_NOT_CONNECTING, m_HsmName ); AfxMessageBox( msg, RS_MB_ERROR ); if( HSMCONN_TYPE_RMS == ConnType ) { disabled = TRUE; } } // // Restore disabledness // m_Disabled = disabled; } } ); // // Need to track RMS connections separately // if( HSMCONN_TYPE_RMS == ConnType ) { m_HrRmsConnect = hr; } // // If our state of "Connection" changed, cause a refresh // BOOL connected = ( GetState() == S_OK ); if( ( connected != previouslyConnected ) && ( ! firstTime ) ) { RefreshNode( m_pRootNode ); } WsbTraceOut( L"CSakData::AffirmServiceConnection", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::VerifyConnection( INT ConnType ) /*++ Routine Description: Verify whether the indicated connection is still good or not. Does not attempt to reconnect. Arguments: ConnType - type of service connection being checked Return Value: S_OK - Connected. S_FALSE - Not connected. E_* - Error occurred while checking --*/ { WsbTraceIn( L"CSakData::VerifyConnection", L"" ); HRESULT hr = S_FALSE; try { switch( ConnType ) { case HSMCONN_TYPE_HSM: if( m_pHsmServer ) { GUID id; WsbAffirmHr( m_pHsmServer->GetID( &id ) ); hr = S_OK; } break; case HSMCONN_TYPE_RMS: if( m_pRmsServer ) { WsbAffirmHr( m_pRmsServer->IsReady( ) ); hr = S_OK; } break; case HSMCONN_TYPE_FSA: if( m_pFsaServer ) { CWsbStringPtr pszName; WsbAffirmHr( m_pFsaServer->GetName( &pszName, 0 ) ); hr = S_OK; } break; } } WsbCatchAndDo( hr, ClearConnections( ); ); WsbTraceOut( L"CSakData::VerifyConnection", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RawConnect( INT ConnType ) /*++ Routine Description: Do low level connection to service specified Arguments: ConnType - type of service connection Return Value: S_OK - Connected. E_* - Error occurred while checking --*/ { WsbTraceIn( L"CSakData::RawConnect", L"" ); HRESULT hr = S_OK; try { // // Potentially a long operation - show wait cursor if possible // CWaitCursor waitCursor; switch( ConnType ) { case HSMCONN_TYPE_HSM: if( ! m_pHsmServer ) { WsbAffirmHr( HsmConnectFromName( HSMCONN_TYPE_HSM, m_HsmName, IID_IHsmServer, (void**)&m_pHsmServer ) ); } break; case HSMCONN_TYPE_RMS: if( ! m_pRmsServer ) { CComPtr pHsm; WsbAffirmHr( HsmConnectFromName( HSMCONN_TYPE_HSM, m_HsmName, IID_IHsmServer, (void**)&pHsm ) ); WsbAffirmPointer(pHsm); WsbAffirmHr(pHsm->GetHsmMediaMgr(&m_pRmsServer)); WsbAffirmHrOk( VerifyConnection( HSMCONN_TYPE_RMS ) ); } break; case HSMCONN_TYPE_FSA: if( ! m_pFsaServer ) { CWsbStringPtr LogicalName( m_HsmName ); // // FSA confuses things by having a // extra level for the "type" // LogicalName.Append( "\\NTFS" ); WsbAffirmHr( HsmConnectFromName( HSMCONN_TYPE_FSA, LogicalName, IID_IFsaServer, (void**)&m_pFsaServer ) ); } break; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::RawConnect", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::ClearConnections( ) /*++ Routine Description: Clear cached connections Arguments: none. Return Value: S_OK - Cleared. E_* - Error occurred while checking --*/ { WsbTraceIn( L"CSakData::ClearConnections", L"" ); HRESULT hr = S_OK; try { m_pHsmServer = 0; m_pRmsServer = 0; m_pFsaServer = 0; } WsbCatch( hr ); WsbTraceOut( L"CSakData::ClearConnections", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RunSetupWizard( IHsmServer * pServer ) /*++ Routine Description: Run the setup wizard Handles disabling / enabling as needed Arguments: pServer - interface to engine Return Value: S_OK - Setup Correctly. S_FALSE - Canceled E_* - Error occurred while setting up --*/ { WsbTraceIn( L"CSakData::RunSetupWizard", L"" ); HRESULT hr = S_OK; try { // // use wizard to create manage volume // CComObject* pWizard = new CComObject; WsbAffirmAlloc( pWizard ); CComPtr pSakWizard = (ISakWizard*)pWizard; WsbAffirmHr( CreateWizard( pSakWizard ) ); // // RS_E_CANCELED indicates canceled, and FAILEd indicates error. // If so, then throw "Not set up" // if( S_OK != pWizard->m_HrFinish ) { WsbThrow( S_FALSE ); } WsbAffirmHrOk( RsIsRemoteStorageSetupEx( pServer ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::RunSetupWizard", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RetargetSnapin( ) /*++ Routine Description: Run the small choose server dialog Arguments: none. Return Value: S_OK - Setup Correctly. S_FALSE - Canceled E_* - Error occurred while changing --*/ { WsbTraceIn( L"CSakData::RetargetSnapin", L"" ); HRESULT hr = S_OK; try { if( IsPrimaryImpl( ) ) { // // Bring up dialog // CChooseHsmQuickDlg dlg; dlg.m_pHsmName = &m_HsmName; if( IDOK == dlg.DoModal( ) ) { m_PersistManageLocal = FALSE; m_ManageLocal = FALSE; // // We want the name shown to be accurate, regardless // of whether they targetted to a valid machine. // So, re-initialize the root node before going // any further. // WsbAffirmHr( InitializeRootNode( ) ); // // Make sure we hook up OK. If not, just disable // Note that since we set "First" flag at beginning // of the block, this will not endlessly recurse // hr = AffirmServiceConnection( HSMCONN_TYPE_HSM ); if( FAILED( hr ) ) { Disable( ); WsbThrow( hr ); } } else { // // They canceled out, so just disable // Disable( ); WsbThrow( RS_E_CANCELLED ); } } else { // // As extension we don't allow retargeting, so we just disable // Disable( ); WsbThrow( S_FALSE ); } } WsbCatch( hr ); WsbTraceOut( L"CSakData::RetargetSnapin", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::CreateChildNodes( ISakNode* pParentNode ) /*++ Routine Description: Create and initialize the children of an existing COM parent. Currently, this initialization is being done from HSM object. Arguments: pNode - The node to create the children of. Return Value: S_OK - Children created. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::CreateChildNodes", L"pParentNode = <0x%p>", pParentNode ); HRESULT hr = S_OK; try { // // Initialize the child nodes - first delete existing children from UI, // then initialize new children into UI. No recursion. Decendents are // NOT created here. // CComPtr pNode; WsbAffirmHr( RsQueryInterface( pParentNode, ISakNode, pNode ) ); WsbAffirmHr( pNode->DeleteAllChildren( ) ); WsbAffirmHr( pNode->CreateChildren( ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::CreateChildNodes", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::FreeEnumChildren( ISakNode* pParentNode ) /*++ Routine Description: Recursively (bottom-up) free the SCOPEDATAITEM children of the pParent enumerated node Arguments: pParentNode - identifies the node to be worked on. Return Value: S_OK - Children freed successfully. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::FreeEnumChildren", L"pParentNode = <0x%p>", pParentNode ); HRESULT hr = S_OK; try { HSCOPEITEM scopeIDParent; pParentNode->GetScopeID( &scopeIDParent ); WsbAffirm( scopeIDParent > 0, E_FAIL ) WsbAffirmHr( m_pNameSpace->DeleteItem( scopeIDParent, FALSE ) ); pParentNode->SetEnumState( FALSE ); } WsbCatch (hr); WsbTraceOut( L"CSakData::FreeEnumChildren", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } ///////////////////////////////////////////////////////////////////////////////////////// // // IPersistStream implementation // STDMETHODIMP CSakData::Save( IStream *pStm, BOOL fClearDirty ) /*++ Routine Description: Save the information we need to reconstruct the root node in the supplied stream. Arguments: pStm I: Console-supplied stream fClearDirty I: The console tells us to clear our dirty flag Return Value: S_OK - Saved successfully. E_* - Some error occurred. --*/ { WsbTraceIn( L"CSakData::Save", L"pStm = <0x%p>, fClearDirty", pStm, WsbBoolAsString( fClearDirty ) ); HRESULT hr = S_OK; try { ULONG version = HSMADMIN_CURRENT_VERSION; WsbAffirmHr( WsbSaveToStream( pStm, version ) ); if( m_PersistManageLocal ) { WsbAffirmHr( WsbSaveToStream( pStm, m_ManageLocal ) ); CWsbStringPtr pHsmName( m_HsmName ); WsbAffirmHr( WsbSaveToStream( pStm, pHsmName ) ); } else { WsbAffirmHr( WsbSaveToStream( pStm, (BOOL)TRUE ) ); CWsbStringPtr pHsmName( "" ); WsbAffirmHr( WsbSaveToStream( pStm, pHsmName ) ); } // Set the dirty flag if( fClearDirty ) ClearDirty( ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::Save", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::Load( IStream *pStm ) /*++ Routine Description: Load the information we need to reconstruct the root node from the supplied stream. Arguments: pStm IConsole-supplied stream Return Value: S_OK - Saved successfully. E_* - Some error occurred. --*/ { WsbTraceIn( L"CSakData::Load", L"pStm = <0x%p>", pStm ); HRESULT hr = S_OK; try { ULONG version = 0; WsbAffirmHr( WsbLoadFromStream( pStm, &version ) ); WsbAssert( ( version == 1 ), E_FAIL ); // Get the flag for local or named HSM WsbLoadFromStream( pStm, &m_ManageLocal ); CWsbStringPtr pHsmName; // Get the HSM name ("" for local HSM) WsbLoadFromStream( pStm, &pHsmName, 0 ); m_HsmName = pHsmName; // Grab any options from the command line after loading InitFromCommandLine( ); // Set the Hsm name in SakData and HsmCom objects WsbAffirmHr( InitializeRootNode() ); ClearDirty(); } WsbCatch (hr); WsbTraceOut( L"CSakData::Load", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::IsDirty( void ) /*++ Routine Description: The console asks us if we are dirty. Arguments: None Return Value: S_OK - Dirty. S_FALSE - Not Dirty. --*/ { WsbTraceIn( L"CSakData::IsDirty", L"" ); HRESULT hr = ThisIsDirty() ? S_OK : S_FALSE; WsbTraceOut( L"CSakData::IsDirty", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::GetSizeMax( ULARGE_INTEGER * /*pcbSize*/ ) /*++ Routine Description: Not currently used by the console Arguments: pcbSize Return Value: E_NOTIMPL --*/ { WsbTraceIn( L"CSakData::GetSizeMax", L"" ); HRESULT hr = E_NOTIMPL; WsbTraceOut( L"CSakData::GetSizeMax", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::GetClassID( CLSID *pClassID ) /*++ Routine Description: Not currently used by the console Arguments: pClassID - The class ID for the snapin Return Value: S_OK --*/ { WsbTraceIn( L"CSakData::GetClassID", L"pClassID = <0x%p>", pClassID ); HRESULT hr = S_OK; *pClassID = CLSID_HsmAdmin; WsbTraceOut( L"CSakData::GetClassID", L"hr = <%ls>, *pClassID = <%ls>", WsbHrAsString( hr ), WsbPtrToGuidAsString( pClassID ) ); return( hr ); } ///////////////////////////////////////////////////////////////////////////// // // Adds images to the consoles image list from the static array // HRESULT CSakData::OnAddImages() { HRESULT hr = S_OK; HICON hIcon; try { // // Put the images from the static array into the image list // for the scope pane // for( INT i = 0; i < m_nImageCount; i++ ) { // Load the icon using the resource Id stored in the // static array and get the handle. hIcon = LoadIcon( _Module.m_hInst, MAKEINTRESOURCE( m_nImageArray [i] ) ); // Add to the Console's Image list WsbAffirmHr( m_pImageScope->ImageListSetIcon( (RS_WIN32_HANDLE*)hIcon, i ) ); } } WsbCatch (hr); return hr; } ////////////////////////////////////////////////////////////////////////////////// // // Description: Add the supplied resource ID to the list of resource IDs for // the scope pane. Returns the index into the array. // INT CSakData::AddImage( UINT rId ) { INT nIndex = -1; if (CSakData::m_nImageCount < RS_SCOPE_IMAGE_ARRAY_MAX) { CSakData::m_nImageArray[CSakData::m_nImageCount] = rId; nIndex = CSakData::m_nImageCount; CSakData::m_nImageCount++; } return nIndex; } void CSakData::SetState (BOOL State) { m_State = State; } STDMETHODIMP CSakData::GetState () { return ((m_State) ? S_OK : S_FALSE); } STDMETHODIMP CSakData::Disable( IN BOOL Disable ) { WsbTraceIn( L"CSakData::Disable", L"Disable = <%ls>", WsbBoolAsString( Disable ) ); HRESULT hr = S_OK; m_Disabled = Disable ? TRUE : FALSE; // Force values to TRUE or FALSE // // Make sure state is correct as well // if( Disable ) { SetState( FALSE ); } WsbTraceOut( L"CSakData::Disable", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::IsDisabled( ) { WsbTraceIn( L"CSakData::IsDisabled", L"" ); HRESULT hr = m_Disabled ? S_OK : S_FALSE; WsbTraceOut( L"CSakData::IsDisabled", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } // Is the dataobject either type of multi-select dataobject? HRESULT CSakData::IsDataObjectMultiSelect ( IDataObject *pDataObject ) { HRESULT hr = S_OK; WsbTraceThreadOff( ); hr = ( ( (IsDataObjectOt( pDataObject ) ) == S_OK ) || ( (IsDataObjectMs( pDataObject ) ) == S_OK ) ) ? S_OK : S_FALSE; WsbTraceThreadOn( ); return( hr ); } // Is the dataobject an Object Types dataobject? HRESULT CSakData::IsDataObjectOt ( IDataObject *pDataObject ) { HRESULT hr = S_FALSE; WsbTraceThreadOff( ); // Is this a mutli-select data object? FORMATETC fmt = {(CLIPFORMAT)m_cfObjectTypes, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgm = {TYMED_HGLOBAL, NULL}; if ( pDataObject->GetData( &fmt, &stgm ) == S_OK ) { hr = S_OK; } ReleaseStgMedium( &stgm ); WsbTraceThreadOn( ); return( hr ); } // Is the dataobject a Mutli-Select dataobject? HRESULT CSakData::IsDataObjectMs ( IDataObject *pDataObject ) { HRESULT hr = S_FALSE; WsbTraceThreadOff( ); // Is this a mutli-select data object? FORMATETC fmt = {(CLIPFORMAT)m_cfMultiSelect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; STGMEDIUM stgm = {TYMED_HGLOBAL, NULL}; if ( pDataObject->GetData( &fmt, &stgm ) == S_OK ) { hr = S_OK; } ReleaseStgMedium( &stgm ); WsbTraceThreadOn( ); return( hr ); } #if 0 HRESULT CSakData::SaveColumnWidths( USHORT listCtrlId, CListCtrl *pListCtrl ) { WsbTraceIn( L"CSakData::SaveColumnWidths", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; HRESULT hrInternal; UINT columnWidth; GUID nodeTypeGuid; BOOL exists = FALSE; UINT updateIndex; UINT col; try { WsbAssertPointer( pListCtrl ); // Search to see if the listCtrlId already has an entry for( INT index = 0; index < m_cListViewWidths; index++ ) { if ( m_ListViewWidths[ index ].listCtrlId == listCtrlId ) { updateIndex = index; exists = TRUE; } } if ( !exists ) { // Create a new entry WsbAssert( m_cListViewWidths < BHSM_MAX_NODE_TYPES - 1, E_FAIL ); updateIndex = m_cListViewWidths; m_ListViewWidths[ updateIndex ].listCtrlId = listCtrlId; m_cListViewWidths++; } // Now set the column widths col = 0; hrInternal = S_OK; while( hrInternal == S_OK ) { hrInternal = pListCtrl->GetColumnWidth( col, &columnWidth ); if (hrInternal == S_OK) { m_ListViewWidths[ updateIndex ].columnWidths[ col ] = columnWidth; col++; } } // if we failed totally to get column widths, don't wipe out the previous value if ( col > 0 ) { m_ListViewWidths[ updateIndex ].colCount = col; } } WsbCatch (hr); WsbTraceOut( L"CSakData::SaveColumnWidths", L"hr = <%ls>", WsbHrAsString( hr ) ); return hr; } HRESULT CSakData::GetSavedColumnWidths( USHORT listCtrlId, CListCtrl *pListCtrl ) { WsbTraceIn( L"CSakData::SaveColumnWidths", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; GUID nodeTypeGuid; BOOL exists = FALSE; INT col; try { WsbAssertPointer( pNode ); // Search to see if the listCtrlId already has an entry for ( INT index = 0; index < m_cListViewWidths; index++ ) { if ( m_ListViewWidths[ index ].listCtrlId == listCtrlId ) { for ( col = 0; col < m_ListViewWidths[ index ].colCount; col++) { // Return the column widths pColumnWidths[ col ] = m_ListViewWidths[ index ].columnWidths[ col ]; } *pColCount = m_ListViewWidths[ index ].colCount; exists = TRUE; } } if ( !exists ) { return WSB_E_NOTFOUND; } } WsbCatch (hr); WsbTraceOut( L"CSakData::SaveColumnWidths", L"hr = <%ls>", WsbHrAsString( hr ) ); return hr; } #endif void CSakData::InitFromCommandLine( void ) /*++ Routine Description: Retreive the command line info and fill in appropriate fields. Arguments: none. Return Value: none. --*/ { WsbTraceIn( L"CSakData::InitFromCommandLine", L"" ); g_App.ParseCommandLine( m_Parse ); if( m_Parse.m_SetManageLocal ) m_ManageLocal = m_Parse.m_ManageLocal; if( m_Parse.m_SetHsmName ) m_HsmName = m_Parse.m_HsmName; if( m_Parse.m_SetPersistManageLocal ) m_PersistManageLocal = m_Parse.m_PersistManageLocal; } ///////////////////////////////////////////////////////////////////////////// // CSakDataWnd BOOL CSakDataWnd::Create( CSakData * pSakData ) { WsbTraceIn( L"CSakDataWnd::Create", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); m_pSakData = pSakData; BOOL retval = CWnd::CreateEx( 0, AfxRegisterWndClass( 0 ), _T("RSAdmin MsgWnd"), WS_OVERLAPPED, 0, 0, 0, 0, 0, 0 ); WsbTraceOut( L"CSakDataWnd::Create", L"retval = <%ls>", WsbBoolAsString( retval ) ); return( retval ); } void CSakDataWnd::PostNcDestroy( ) { WsbTraceIn( L"CSakDataWnd::PostNcDestroy", L"" ); AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); CWnd::PostNcDestroy( ); // // Cleanup object // delete this; WsbTraceOut( L"CSakDataWnd::PostNcDestroy", L"" ); } BEGIN_MESSAGE_MAP(CSakDataWnd, CWnd) //{{AFX_MSG_MAP(CSakDataWnd) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP ON_MESSAGE( WM_SAKDATA_UPDATE_ALL_VIEWS, OnUpdateAllViews ) ON_MESSAGE( WM_SAKDATA_REFRESH_NODE, OnRefreshNode ) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSakDataWnd message handlers LONG CSakDataWnd::OnUpdateAllViews( IN UINT, IN LONG lParam ) { WsbTraceIn( L"CSakDataWnd::OnUpdateAllViews", L"" ); HRESULT hr = S_OK; try { // // Call the internal update // WsbAffirmHr( m_pSakData->InternalUpdateAllViews( (MMC_COOKIE)lParam ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakDataWnd::OnUpdateAllViews", L"" ); return( 0 ); } void CSakDataWnd::PostUpdateAllViews( IN MMC_COOKIE Cookie ) { WsbTraceIn( L"CSakDataWnd::PostUpdateAllViews", L"" ); PostMessage( WM_SAKDATA_UPDATE_ALL_VIEWS, 0, Cookie ); WsbTraceOut( L"CSakDataWnd::PostUpdateAllViews", L"" ); } LONG CSakDataWnd::OnRefreshNode( IN UINT, IN LONG lParam ) { WsbTraceIn( L"CSakDataWnd::OnRefreshNode", L"" ); HRESULT hr = S_OK; try { // // Call the internal update // WsbAffirmHr( m_pSakData->InternalRefreshNode( (MMC_COOKIE)lParam ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakDataWnd::OnRefreshNode", L"" ); return( 0 ); } void CSakDataWnd::PostRefreshNode( IN MMC_COOKIE Cookie ) { WsbTraceIn( L"CSakDataWnd::PostRefreshNode", L"" ); PostMessage( WM_SAKDATA_REFRESH_NODE, 0, Cookie ); WsbTraceOut( L"CSakDataWnd::PostRefreshNode", L"" ); } ULONG CSakData::InternalAddRef( ) { WsbTraceIn( L"CSakData::InternalAddRef", L"" ); ULONG retval = CComObjectRoot::InternalAddRef( ); WsbTraceOut( L"CSakData::InternalAddRef", L"retval = <%lu>", retval ); return( retval ); } ULONG CSakData::InternalRelease( ) { WsbTraceIn( L"CSakData::InternalRelease", L"" ); ULONG retval = CComObjectRoot::InternalRelease( ); WsbTraceOut( L"CSakData::InternalRelease", L"retval = <%lu>", retval ); return( retval ); } STDMETHODIMP CSakData::GetHelpTopic( LPOLESTR* pTopic ) { WsbTraceIn( L"CSakData::GetHelpTopic", L"" ); HRESULT hr = S_OK; try { WsbAffirmPointer( pTopic ); *pTopic = 0; CWsbStringPtr topic; WsbAffirmHr( topic.LoadFromRsc( _Module.m_hInst, IDS_HELPFILE ) ); #if 1 // Hopefully temporary hack since MMC can't find the help directory WsbAffirmHr( topic.Prepend( L"\\help\\" ) ); CWsbStringPtr winDir; WsbAffirmHr( winDir.Alloc( RS_WINDIR_SIZE ) ); WsbAffirmStatus( ::GetWindowsDirectory( (WCHAR*)winDir, RS_WINDIR_SIZE ) != 0 ); WsbAffirmHr( topic.Prepend( winDir ) ); #endif WsbAffirmHr( topic.GiveTo( pTopic ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetHelpTopic", L"hr = <%ls>, *pTopic = <%ls>", WsbHrAsString( hr ), WsbPtrToStringAsString( pTopic ) ); return( hr ); } STDMETHODIMP CSakData::GetLinkedTopics( LPOLESTR* pTopic ) { WsbTraceIn( L"CSakData::GetLinkedTopics", L"" ); HRESULT hr = S_OK; try { WsbAffirmPointer( pTopic ); *pTopic = 0; CWsbStringPtr topic; WsbAffirmHr( topic.LoadFromRsc( _Module.m_hInst, IDS_HELPFILELINK ) ); #if 1 // Hopefully temporary hack since MMC can't find the help directory WsbAffirmHr( topic.Prepend( L"\\help\\" ) ); CWsbStringPtr winDir; WsbAffirmHr( winDir.Alloc( RS_WINDIR_SIZE ) ); WsbAffirmStatus( ::GetWindowsDirectory( (WCHAR*)winDir, RS_WINDIR_SIZE ) != 0 ); WsbAffirmHr( topic.Prepend( winDir ) ); #endif WsbAffirmHr( topic.GiveTo( pTopic ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetLinkedTopics", L"hr = <%ls>, *pTopic = <%ls>", WsbHrAsString( hr ), WsbPtrToStringAsString( pTopic ) ); return( hr ); } STDMETHODIMP CSakData::CreateWizard( IN ISakWizard * pWizard ) { WsbTraceIn( L"CSakData::CreateWizard", L"" ); HRESULT hr = S_OK; try { WsbAffirmPointer( pWizard ); // // Need to get prop sheet privider and create wizard // CComPtr pProvider; WsbAffirmHr( m_pConsole.QueryInterface( &pProvider ) ); // // Create it // CWsbStringPtr pszName; WsbAffirmHr( pWizard->GetTitle( &pszName ) ); // // Create the property sheet // CComPtr pDataObject; WsbAffirmHr( RsQueryInterface( pWizard, IDataObject, pDataObject ) ); WsbAffirmHr( pProvider->CreatePropertySheet( pszName, FALSE, 0, pDataObject, MMC_PSO_NEWWIZARDTYPE ) ); // // Tell the IComponentData interface to add pages // CComPtr pUnkComponentData; pUnkComponentData = (IUnknown *) (IComponentData*) this; WsbAffirmHr( pProvider->AddPrimaryPages( pUnkComponentData, TRUE, 0, TRUE ) ); // // And show it // HWND mainWnd; WsbAffirmHr( m_pConsole->GetMainWindow( &mainWnd ) ); WsbAffirmHr( pProvider->Show( reinterpret_cast(mainWnd), 0 ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::CreateWizard", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::GetWatermarks( IN LPDATAOBJECT pDataObject, OUT HBITMAP* pWatermark, OUT HBITMAP* pHeader, OUT HPALETTE* pPalette, OUT BOOL* pStretch ) { WsbTraceIn( L"CSakData::GetWatermarks", L"" ); HRESULT hr = S_OK; try { // // Need to get the ISakWizard interface to do actual work // CComPtr pWizard; WsbAffirmHr( RsQueryInterface( pDataObject, ISakWizard, pWizard ) ); // // And make the call // WsbAffirmHr( pWizard->GetWatermarks( pWatermark, pHeader, pPalette, pStretch ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::GetWatermarks", L"" ); return( hr ); } CSakDataNodePrivate::CSakDataNodePrivate( ISakNode* pNode ) { m_pNode = pNode; RS_PRIVATE_DATA data = (RS_PRIVATE_DATA)this; if( SUCCEEDED( pNode->SetPrivateData( data ) ) ) { m_Magic = RS_NODE_MAGIC_GOOD; } else { m_Magic = RS_NODE_MAGIC_DEFUNCT; } } CSakDataNodePrivate::~CSakDataNodePrivate( ) { m_Magic = RS_NODE_MAGIC_DEFUNCT; if( m_pNode ) { m_pNode->SetPrivateData( 0 ); } } HRESULT CSakDataNodePrivate::Verify( CSakDataNodePrivate* pNodePriv ) { HRESULT hr = E_POINTER; if( !IsBadWritePtr( pNodePriv, sizeof( CSakDataNodePrivate ) ) ) { if( RS_NODE_MAGIC_GOOD == pNodePriv->m_Magic ) { hr = S_OK; } } return( hr ); }