/*++ © 1998 Seagate Software, Inc. All rights reserved. Module Name: SakMenu.cpp Abstract: Implements all the context menu interface to the individual nodes, including getting menu resources and turning into MMC menus, and forwarding on command messages. Author: Rohde Wakefield [rohde] 09-Dec-1996 Revision History: --*/ #include "stdafx.h" #include "CSakData.h" #include "CSakSnap.h" // // Mask for a long value out of a short value's range // #define SHORT_VALUE_RANGE (MAXULONG ^ ((unsigned short)MAXSHORT)) static HRESULT AddMmcMenuItems ( IN CMenu * pMenu, IN LONG lInsertionPointID, IN ISakNode * pNode, IN IContextMenuCallback * pContextMenuCallback ) /*++ Routine Description: Called for any node clicked on with right mouse. Goes to the node object to construct the MMC menu. Arguments: pDataObject - identifies the node to be worked on. pContextMenuCallback - The MMC menu interface to use. Return Value: S_OK - All added fine - continue. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"AddMmcMenuItems", L"lInsertionPointID = <0x%p>, pNode = <0x%p>", lInsertionPointID, pNode ); HRESULT hr = S_OK; try { // // It is ok to pass a NULL pMenu - means do not add // any entries // if ( 0 != pMenu ) { CString menuText; CString statusText; BSTR bstr; CONTEXTMENUITEM menuItem; memset ( (void*)&menuItem, 0, sizeof ( menuItem ) ); menuItem.lInsertionPointID = lInsertionPointID; UINT menuCount = pMenu->GetMenuItemCount ( ); for ( UINT index = 0; index < menuCount; index++ ) { // // For each menu item, fill out MMC's CONTEXTMENUITEM struct // appropriately and call AddItem // menuItem.lCommandID = pMenu->GetMenuItemID ( index ); pMenu->GetMenuString ( index, menuText, MF_BYPOSITION ); menuItem.strName = (LPTSTR)(LPCTSTR)menuText; WsbAffirmHr ( pNode->GetMenuHelp ( menuItem.lCommandID, &bstr ) ); if ( 0 != bstr ) { statusText = bstr; SysFreeString ( bstr ); menuItem.strStatusBarText = (LPTSTR)(LPCTSTR)statusText; } else { menuItem.strStatusBarText = 0; } menuItem.fFlags = pMenu->GetMenuState ( index, MF_BYPOSITION ); menuItem.fSpecialFlags = 0; // // Since AppStudio does not make available the MFS_DEFUALT flag, // we will use the MF_HELP flag for default entry. // if ( 0 != ( menuItem.fFlags & MF_HELP ) ) { menuItem.fFlags &= ~MF_HELP; menuItem.fSpecialFlags |= CCM_SPECIAL_DEFAULT_ITEM; } pContextMenuCallback->AddItem ( &menuItem ); } } } WsbCatch ( hr ); WsbTraceOut( L"AddMmcMenuItems", L"hr = <%ls>", WsbHrAsString( hr ) ); return ( hr ); } STDMETHODIMP CSakData::AddMenuItems ( IN LPDATAOBJECT pDataObject, IN LPCONTEXTMENUCALLBACK pContextMenuCallback, OUT LONG* pInsertionAllowed ) /*++ Routine Description: Called for any node clicked on with right mouse. Goes to the node object to construct the MMC menu. Arguments: pDataObject - identifies the node to be worked on. pContextMenuCallback - The MMC menu interface to use. Return Value: S_OK - All added fine - continue. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::AddMenuItems", L"pDataObject = <0x%p>", pDataObject ); HRESULT hr = S_OK; BOOL bMultiSelect; try { // // Note - snap-ins need to look at the data object and determine // in what context, menu items need to be added. // We should be expecting either single data object or Multi-Select // data object. Not Object Types data object. // CComPtr pNode; CComPtr pEnumObjectId; WsbAffirmHr( GetBaseHsmFromDataObject( pDataObject, &pNode, &pEnumObjectId ) ); bMultiSelect = pEnumObjectId ? TRUE : FALSE; CMenu menu; HMENU hMenu; WsbAffirmHr( pNode->GetContextMenu ( bMultiSelect, &hMenu ) ); menu.Attach( hMenu ); // // Any menu returned by GetContextMenu should have three // top-level popups for the following portions of the // MMC context menu: // // 1. Root (Above all other items) // 2. Create New // 3. Task // // If any of these should not have any items added for them, // the top-level item should not be a pop (sans MF_POPUP) // if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP ) { WsbAffirmHr ( AddMmcMenuItems ( menu.GetSubMenu ( MENU_INDEX_ROOT ), CCM_INSERTIONPOINTID_PRIMARY_TOP, pNode, pContextMenuCallback ) ); } if( *pInsertionAllowed & CCM_INSERTIONALLOWED_NEW ) { WsbAffirmHr ( AddMmcMenuItems ( menu.GetSubMenu ( MENU_INDEX_NEW ), CCM_INSERTIONPOINTID_PRIMARY_NEW, pNode, pContextMenuCallback ) ); } if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TASK ) { WsbAffirmHr ( AddMmcMenuItems ( menu.GetSubMenu ( MENU_INDEX_TASK ), CCM_INSERTIONPOINTID_PRIMARY_TASK, pNode, pContextMenuCallback ) ); } } WsbCatch ( hr ); WsbTraceOut( L"CSakData::AddMenuItems", L"hr = <%ls>", WsbHrAsString( hr ) ); return ( hr ); } STDMETHODIMP CSakData::Command ( IN long nCommandID, IN LPDATAOBJECT pDataObject ) /*++ Routine Description: Called for any node receiving a menu command. Goes to the node object to handle the command, and allows general (not node-specific) commands to be handled centrally. Arguments: nCommandID - ID of command. pDataObject - Data object representing the node. Return Value: S_OK - Handled. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakData::Command", L"nCommandID = <%ld>, pDataObject = <0x%p>", nCommandID, pDataObject ); HRESULT hr = S_OK; try { HRESULT resultCommand = S_FALSE; // // All node commands are SHORT values. Check range first. // if ( 0 == ( nCommandID & SHORT_VALUE_RANGE ) ) { // // We start by getting the corresponding ISakNode interface // to the node // CComPtr pNode; CComPtr pEnumObjectId; WsbAffirmHr( GetBaseHsmFromDataObject ( pDataObject, &pNode, &pEnumObjectId ) ); // // Then see if it wants to handle the command // WsbAffirmHr( ( resultCommand = pNode->InvokeCommand ( (SHORT)nCommandID, pDataObject ) ) ); } } WsbCatch ( hr ) WsbTraceOut( L"CSakData::Command", L"hr = <%ls>", WsbHrAsString( hr ) ); return ( hr ); } STDMETHODIMP CSakSnap::AddMenuItems ( IN LPDATAOBJECT pDataObject, IN LPCONTEXTMENUCALLBACK pContextMenuCallback, OUT LONG* pInsertionAllowed ) /*++ Routine Description: Called for any node clicked on with right mouse in result pane. Delegates to CSakData. Arguments: pDataObject - identifies the node to be worked on. pContextMenuCallback - The MMC menu interface to use. Return Value: S_OK - All added fine - continue. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakSnap::AddMenuItems", L"pDataObject = <0x%p>", pDataObject ); HRESULT hr = S_OK; try { WsbAffirmHr( m_pSakData->AddMenuItems( pDataObject, pContextMenuCallback, pInsertionAllowed ) ); } WsbCatch( hr ); WsbTraceOut( L"CSakSnap::AddMenuItems", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); } STDMETHODIMP CSakSnap::Command ( IN long nCommandID, IN LPDATAOBJECT pDataObject ) /*++ Routine Description: Called for any node receiving a menu command. Delegated to CSakData. Arguments: nCommandID - ID of command. pDataObject - Data object representing the node. Return Value: S_OK - Handled. E_UNEXPECTED - Some error occurred. --*/ { WsbTraceIn( L"CSakSnap::Command", L"nCommandID = <%ld>, pDataObject = <0x%p>", nCommandID, pDataObject ); HRESULT hr; try { hr = m_pSakData->Command( nCommandID, pDataObject ); } WsbCatch( hr ); WsbTraceOut( L"CSakSnap::Command", L"hr = <%ls>", WsbHrAsString( hr ) ); return( hr ); }