390 lines
8.9 KiB
C++
390 lines
8.9 KiB
C++
/*++
|
||
|
||
© 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<ISakNode> pNode;
|
||
CComPtr<IEnumGUID> 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<ISakNode> pNode;
|
||
CComPtr<IEnumGUID> 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 );
|
||
}
|
||
|