/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: evntdata.cpp Abstract: This module is responsible for handling the notification calls from MMC CSakData. Author: Rohde Wakefield [rohde] 06-Mar-1997 Revision History: --*/ #include "stdafx.h" #include "CSakSnap.h" #include "CSakData.h" UINT CSakData::m_CFMachineName = RegisterClipboardFormat( L"MMC_SNAPIN_MACHINE_NAME" ); HRESULT CSakData::OnFolder( IN IDataObject* pDataObject, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: Param is the unique identifier ( an HSCOPEITEM of the expanding or contracting item ) Arguments: pNode - The node which is expanding. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnFolder", L"pDataObject = <0x%p>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, arg, arg, param, param ); HRESULT hr = S_OK; AFX_MANAGE_STATE( AfxGetStaticModuleState( ) ); try { // if the arg is TRUE, the node is being expanded. if( arg ) { CComPtr pNode; // Get the basehsm out of the data record. GetBaseHsmFromDataObject ( pDataObject, &pNode ); if( !pNode ) { // The dataobject is not one of ours - we must be extending another // snapin. // Get the root node from UnkRootNode ( it has already been created // by Initialize ) WsbAffirmPointer( m_pRootNode ); // We're an extension snapin. // Get the server focus from the data object. // CString hsmName; WsbAffirmHr( GetServerFocusFromDataObject( pDataObject, hsmName ) ); if( hsmName == "" ) { m_ManageLocal = TRUE; m_HsmName = ""; } else { m_ManageLocal = FALSE; // eliminate starting \\ if there is one. Computer management // precedes the server name with \\. if( hsmName.Left( 2 ) == L"\\\\" ) { int len = hsmName.GetLength( ); m_HsmName = hsmName.Right( len - 2 ); } else { m_HsmName = hsmName; } } // Set the Hsm name in SakData and HsmCom objects WsbAffirmHr( InitializeRootNode( ) ); // Create a scope pane item and insert it SCOPEDATAITEM sdi; ZeroMemory( &sdi, sizeof sdi ); sdi.mask = SDI_STR | SDI_PARAM | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARENT; sdi.relativeID = ( HSCOPEITEM )( param ); sdi.displayname = MMC_CALLBACK; WsbAffirmHr( m_pRootNode->GetScopeCloseIcon( m_State, &sdi.nImage ) ); WsbAffirmHr( m_pRootNode->GetScopeOpenIcon( m_State, &sdi.nOpenImage ) ); // This is a special token for the extension root node sdi.lParam = EXTENSION_RS_FOLDER_PARAM; // Insert the node into the scope pane and save the scope ID WsbAffirmHr( m_pNameSpace->InsertItem( &sdi ) ); WsbAffirmHr( m_pRootNode->SetScopeID( ( HSCOPEITEM )( sdi.ID ) ) ); m_RootNodeInitialized = TRUE; } else { GUID nodeGuid; WsbAffirmHr( pNode->GetNodeType( &nodeGuid ) ); if( IsEqualGUID( nodeGuid, cGuidHsmCom ) ) { if( !m_RootNodeInitialized ) { m_RootNodeInitialized = TRUE; // // Set the scopeitem in the node // WsbAffirmHr( pNode->SetScopeID( ( HSCOPEITEM )( param ) ) ); // // Update the text and icon ( text is wrong if loaded // from file and command line switch given for // different machine // SCOPEDATAITEM sdi; ZeroMemory( &sdi, sizeof sdi ); sdi.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE; sdi.ID = ( HSCOPEITEM )( param ); sdi.displayname = MMC_CALLBACK; WsbAffirmHr( pNode->GetScopeCloseIcon( m_State, &sdi.nImage ) ); WsbAffirmHr( pNode->GetScopeOpenIcon( m_State, &sdi.nOpenImage ) ); WsbAffirmHr( m_pNameSpace->SetItem( &sdi ) ); } } // // Initialize child node list prior to graphically enumerating them // WsbAffirmHr( EnsureChildrenAreCreated( pNode ) ); // // Param contains the HSCOPEITEM of the node being opened. // WsbAffirmHr( EnumScopePane( pNode, ( HSCOPEITEM )( param ) ) ); } } } WsbCatch( hr ); WsbTraceOut( L"CSakData::OnFolder", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } //////////////////////////////////////////////////////////////////////////////////// // // Description: Get the server name from the supplied data object. The dataobject // is implemented by the snapin we are extending // HRESULT CSakData::GetServerFocusFromDataObject( IDataObject *pDataObject, CString& HsmName ) { HRESULT hr = S_OK; try { STGMEDIUM stgmedium = { TYMED_HGLOBAL, NULL }; FORMATETC formatetc = { (CLIPFORMAT)m_CFMachineName, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; // Allocate memory for the stream // Note: we add 2 bytes because Computer Management puts \\ at the // beginning of the computer name. - AHB 12/22/97 // stgmedium.hGlobal = GlobalAlloc( GMEM_SHARE, sizeof( WCHAR ) * ( MAX_PATH + 1 + 2 ) ); WsbAffirmPointer( stgmedium.hGlobal ) // Attempt to get data from the object WsbAffirmHr( pDataObject->GetDataHere( &formatetc, &stgmedium ) ); HsmName = ( OLECHAR * ) stgmedium.hGlobal; GlobalFree( stgmedium.hGlobal ); } WsbCatch ( hr ) ; return hr; } HRESULT CSakData::OnShow( IN IDataObject* pDataObject, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: The result view is just about to be shown. Set the headers for the result view. Param is the unique identifier ( an HSCOPEITEM ) of the selected or deselected item. Arguments: pNode - The node which is showing. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnShow", L"pDataObject = <0x%p>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, arg, arg, param, param ); HRESULT hr = S_OK; try { CComPtr pNode; // Get the basehsm out of the data record. GetBaseHsmFromDataObject ( pDataObject, &pNode ); // // Arg is TRUE when it is time to enumerate // if( arg ) { // // Initialize child node list prior to graphically enumerating them // WsbAffirmHr( EnsureChildrenAreCreated( pNode ) ); // // Enumerate both the scope and result views. "Param" contains the // HSCOPEITEM of the node being shown. // WsbAffirmHr( EnumScopePane( pNode, ( HSCOPEITEM )( param ) ) ); } else { // // Free data associated with the result pane items, because // your node is no longer being displayed. // Note: The console will remove the items from the result pane // } } WsbCatch( hr ); WsbTraceOut( L"CSakData::OnShow", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::OnSelect( IN IDataObject* pDataObject, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: Called when a "folder" ( node ) is going to be opened ( not expanded ). Param is the unique identifier ( an HSCOPEITEM of the expanding or contracting item ) Arguments: pNode - The node which is expanding. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnSelect", L"pDataObject = <0x%p>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, arg, arg, param, param ); HRESULT hr = S_OK; WsbTraceOut( L"CSakData::OnSelect", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::OnMinimize( IN IDataObject* pDataObject, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: Arguments: pNode - The node which is expanding. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnMinimize", L"pDataObject = <0x%p>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, arg, arg, param, param ); HRESULT hr = S_OK; WsbTraceOut( L"CSakData::OnMinimize", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::OnContextHelp( IN IDataObject* pDataObject, IN LPARAM arg, IN LPARAM param ) /*++ Routine Description: Called when help is selected on a node. Shows the top level help. Arguments: pNode - The node which is requesting help. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnContextHelp", L"pDataObject = <0x%p>, arg = <%ld><0x%p>, param = <%ld><0x%p>", pDataObject, arg, arg, param, param ); HRESULT hr = S_OK; try { // // Get the help interface // CComPtr pDisplayHelp; WsbAffirmHr( m_pConsole.QueryInterface( &pDisplayHelp ) ); // // Form up the correct name // CWsbStringPtr helpFile; WsbAffirmHr( helpFile.LoadFromRsc( _Module.m_hInst, IDS_HELPFILELINK ) ); WsbAffirmHr( helpFile.Append( L"::/rss_node_howto.htm" ) ); // // And show it // WsbAffirmHr( pDisplayHelp->ShowTopic( helpFile ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::OnContextHelp", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::EnumScopePane( IN ISakNode* pNode, IN HSCOPEITEM pParent ) /*++ Routine Description: Insert the items into the scopepane under the item which is represented by cookie and pParent. Arguments: pNode - The node which is expanding. arg - param - Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::EnumScopePane", L"pNode = <0x%p>, pParent = <0x%p>", pNode, pParent ); HRESULT hr = S_OK; try { // // Verify params // WsbAffirmPointer( pNode ); WsbAffirmPointer( pParent ); // // make sure we QI'ed for the interface // WsbAffirmPointer( m_pNameSpace ); // // Avoid enumerating the same node twice. Once enumerated, a node remembers it. // BOOL isEnumerated; WsbAffirmHr( pNode->GetEnumState( &isEnumerated ) ); if( !isEnumerated ) { // // This node has NOT been enumerated in the tree. // if( S_OK == pNode->IsContainer( ) ) { CComPtr pEnum; // child enumerator object CComQIPtr pBaseHsmChild; // child pointer to BaseHsm interface // Create an Enumeration object for the children and enumerate them WsbAffirmHr( pNode->EnumChildren( &pEnum ) ); CComPtr pUnkChild; // pointer to next child in list while( pEnum->Next( 1, &pUnkChild, NULL ) == S_OK ) { pBaseHsmChild = pUnkChild; WsbAffirmPointer( pBaseHsmChild ); // // If this is a leaf node, don't enumerate in scope pane. // if( pBaseHsmChild->IsContainer( ) != S_OK ) { pBaseHsmChild.Release( ); pUnkChild.Release( ); continue; } // // Set up a SCOPEDATAITEM for this child node and insert the child into the scope treeview // SCOPEDATAITEM childScopeItem; memset( &childScopeItem, 0, sizeof( SCOPEDATAITEM ) ); // // Set String to be callback // childScopeItem.displayname = MMC_CALLBACK; childScopeItem.mask |= SDI_STR; // // Add "expandable" indicator to tree node if // this node has children. Fake out number // of children. // if( pBaseHsmChild->IsContainer( ) == S_OK ) { childScopeItem.cChildren = 1; childScopeItem.mask |= SDI_CHILDREN; } // // Set child node's scope item parent. // childScopeItem.relativeID = pParent; childScopeItem.mask |= SDI_PARENT; // // Set the param in the ScopeItem to the unknown pointer // to this node, so that when this scopeitem is sent back // to us, we can get it out and use it to look up // node-specific info. // WsbAffirmHr( GetCookieFromBaseHsm( pBaseHsmChild, (MMC_COOKIE*)(&childScopeItem.lParam) ) ); childScopeItem.mask |= SDI_PARAM; childScopeItem.mask |= SDI_STATE; childScopeItem.nState = 0; // // Note - After insertion into the tree, the SCOPEITEM ID member contains the handle to // the newly inserted item // WsbAffirmHr ( pBaseHsmChild->GetScopeCloseIcon( m_State, &childScopeItem.nImage ) ); childScopeItem.mask |= SDI_IMAGE; WsbAffirmHr ( pBaseHsmChild->GetScopeOpenIcon( m_State, &childScopeItem.nOpenImage ) ); childScopeItem.mask |= SDI_OPENIMAGE; WsbAffirmHr( m_pNameSpace->InsertItem( &childScopeItem ) ); WsbAffirm( childScopeItem.ID != NULL, E_UNEXPECTED ); // // Set the scopeitem id in the node object // WsbAffirmHr( pBaseHsmChild->SetScopeID( childScopeItem.ID ) ); // // release the test interface pointer and string for next node // pBaseHsmChild.Release( ); pUnkChild.Release( ); } // // Indicate that this node has been enumerated // WsbAffirmHr( pNode->SetEnumState( TRUE ) ); } } } WsbCatch( hr ); WsbTraceOut( L"CSakData::EnumScopePane", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::EnsureChildrenAreCreated( IN ISakNode * pNode ) /*++ Routine Description: Guarantee that the immediate children of a particular node are created in our hierarchical list of nodes. Arguments: pNode - The node to check. Return Value: S_OK - Created successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::EnsureChildrenAreCreated", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; try { // // Create the node's children if the node's list of children is // currently invalid ( i.e. - never created, or out-of-date ) // if( pNode->ChildrenAreValid( ) == S_FALSE ) { WsbAffirmHr( CreateChildNodes( pNode ) ); } } WsbCatch( hr ); WsbTraceOut( L"CSakData::EnsureChildrenAreCreated", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::OnRemoveChildren( IN IDataObject* pDataObject ) /*++ Routine Description: Arguments: pDataObject - The node Return Value: S_OK - Removed successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::OnRemoveChildren", L"pDataObject = <0x%p>", pDataObject ); HRESULT hr = S_OK; try { CComPtr pNode; WsbAffirmHr( GetBaseHsmFromDataObject( pDataObject, &pNode ) ); WsbAffirmHr( RemoveChildren( pNode ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakData::OnRemoveChildren", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } HRESULT CSakData::RemoveChildren( IN ISakNode* pNode ) /*++ Routine Description: Recursively clean up the cookies for this node's children, but not this node itself. Arguments: pNode - The node Return Value: S_OK - Removed successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::RemoveChildren", L"pNode = <0x%p>", pNode ); HRESULT hr = S_OK; try { CComPtr pEnum; // child enumerator object CComPtr pChild; // child pointer to BaseHsm interface // Create an Enumeration object for the children and enumerate them WsbAffirmHr( pNode->EnumChildren( &pEnum ) ); CComPtr pUnkChild; // pointer to next child in list while( pEnum->Next( 1, &pUnkChild, NULL ) == S_OK ) { WsbAffirmHr( pUnkChild.QueryInterface( &pChild ) ); RemoveChildren( pChild ); // OK to fail and keep going DetachFromNode( pChild ); pUnkChild.Release( ); pChild.Release( ); } } WsbCatch( hr ); WsbTraceOut( L"CSakData::RemoveChildren", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakData::DetachFromNode( IN ISakNode* pNode ) /*++ Routine Description: Called when a node is terminating in order for sakdata to remove any cookies holding onto node. Arguments: pNode - The node Return Value: S_OK - Removed successfully. E_xxxxxxxxxxx - Failure occurred. --*/ { WsbTraceIn( L"CSakData::DetachFromNode", L"" ); HRESULT hr = S_OK; try { WsbAffirmPointer( pNode ); RS_PRIVATE_DATA data; WsbAffirmHr( pNode->GetPrivateData( &data ) ); CSakDataNodePrivate* pNodePriv = (CSakDataNodePrivate*)data; if( pNodePriv && SUCCEEDED( CSakDataNodePrivate::Verify( pNodePriv ) ) ) { delete pNodePriv; } } WsbCatch( hr ); WsbTraceOut( L"CSakData::DetachFromNode", L"" ); return( hr ); }