📄 commandfactory.cpp
字号:
////////////////////////////////////////////////////////////////////////////////
// File : CommandFactory.cpp
//
// Copyright (C) 2002 PGP Corporation
//
// ABSTRACT
// Create CommandFactory object.
//
// Author: Satya S. Das
//
////////////////////////////////////////////////////////////////////////////////
// include files
#include <crtdbg.h>
#include "pgpdebug.h"
#include "windows.h"
#include "shlwapi.h"
#include "gwdll.h"
#include "gwoapi.h"
#include "gwc3po.h"
#include "gwc3cmd.h"
#include "CommandFactory.h"
#include "GwCommand.h"
#include "util.h"
#include "ofcmndr.h"
#include "globals.h"
#include "resource.h"
#include "globals.h"
#include "globdefs.h"
#include "pgpclientprefs.h"
// Globals
int AcceptFlag=0;
//external functions
extern HRESULT Publish(LPCSTR szTokenBuf, BSTR *pbstrResult);
// external data
extern IC3POManager *m_pIMgr;
// internal functions
IUnknown * BuildIUnkDispatch(REFCLSID libid, REFCLSID iid, IUnknown *pIUnk, void *pIFac);
// private functions
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::CCommandFactory
//
// Description:CCommandFactory constructor
//
// In:none
//
// Out:none
//
// Comments:
//////////////////////////////////////////////////////////////////
CCommandFactory::CCommandFactory(IUnknown *pUnk)
{
PgpGwTrace("CCommandFactory::CCommandFactory\n");
m_pUnkOuter = pUnk;
m_pIUnkDispFact = NULL;
}
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::~CCommandFactory
//
// Description:CCommandFactory destructor
//
// In:none
//
// Out:none
//
// Comments:
//////////////////////////////////////////////////////////////////
CCommandFactory::~CCommandFactory()
{
PgpGwTrace("CCommandFactory::~CCommandFactory\n");
if(m_pIUnkDispFact)
{
m_pIUnkDispFact->Release();
m_pIUnkDispFact=NULL;
}
}
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::QueryInterface
//
// Description:QueryInterface for CCommandFactory
//
// In:REFIID riid - Reference id
//
// Out:LPVOID FAR* ppv -
//
// Comments:
////////////////////////////////////////////////////////////////////
STDMETHODIMP CCommandFactory::QueryInterface(REFIID riid, LPVOID FAR* ppv)
{
PgpGwTrace("CCommandFactory::QueryInterface\n");
if(NULL == ppv)
return E_INVALIDARG;
*ppv=NULL;
if((IID_ICommandFactory == riid ) || (IID_IUnknown == riid))
{
*ppv = this;
((LPUNKNOWN)*ppv)->AddRef();
return S_OK;
}
if(IID_IDispatch == riid)
{
if (NULL == m_pIUnkDispFact)
{
m_pIUnkDispFact = BuildIUnkDispatch(LIBID_PgpGwTypeLibrary,
IID_ICommandFactory, (IUnknown *)(ICommandFactory *)this,
(void *)(ICommandFactory *)this);
}
if (NULL != m_pIUnkDispFact)
return m_pIUnkDispFact->QueryInterface(IID_IDispatch, ppv);
}
return E_NOINTERFACE;
}
//////////////////////////////////////////////////////////////////
// Name: CCommandFactory::BuildCommand
//
// Description:This method is invoked to create a Command object.
// The C3po cannot assume that Command::WantComand
// has been called before this method is invoked.
//
//
// In: BSTR bstrContext - This is the context for the command. The
// context string contains either the class of a GW data object
// (e.g. GW.MESSAGE.MAIL.X) or the class of the specific user
// interface(e.g. GW.APPLICATION.BROWSER).
//
// BSTR bstrPersistentID - This can be either a "pre-defined" ID
// or is an ID provided in a previous run of GW.
//
// IDispatch * pIDispBaseCommand - The command object of the
// command being overridden.
//
// IDispatch * pIDispParameters - The parameter list of the command.
//
// Out:IDispatch * FAR* ppIDispGWCommand - Command object for persistentID.
//
// Comments:Each time the BuildCommand is invoked, the C3po should
// return a new instance of a GWCommand object. This is
// neccessary because BuildCommand can be called recursively.
////////////////////////////////////////////////////////////////////
STDMETHODIMP CCommandFactory::BuildCommand(BSTR bstrContext,
BSTR bstrPersistentID, IDispatch * pIDispBaseCommand,
IDispatch * pIDispParameters, IDispatch * FAR* ppIDispGWCommand)
{
PgpGwTrace("CCommandFactory::BuildCommand(context=%S, id=%S)\n",
bstrContext, bstrPersistentID);
pgpAssert(NULL != pIDispBaseCommand);
pgpAssert(NULL != ppIDispGWCommand);
pgpAssert(0 == _wcsicmp(bstrContext, MAILMESSAGECONTEXTW));//should be a mail message
pgpAssert(0 == _wcsicmp(bstrPersistentID, wceGW_CMDID_OPEN));//should be the open command
HRESULT hrRet=S_OK;
IGWCommand *pigwBaseCmd=NULL;
CGWCommand *pcgwCmdTemp=NULL;
if((NULL == pIDispBaseCommand) || (NULL == ppIDispGWCommand))
{
hrRet=E_FAIL;
goto cleanup;
}
//check if we have expired. if so we do not show any commands
if(TRUE == g_bPlugInExpired)
{
hrRet=E_FAIL;
goto cleanup;
}
try
{
//create a new command object.
pcgwCmdTemp= new CGWCommand(IDM_MAIL_OPEN, CUIO_IS_AN_OPERATION);
}
catch(...)
{
hrRet=E_OUTOFMEMORY;
goto cleanup;
}
pgpAssert(NULL != pcgwCmdTemp);
if(NULL == pcgwCmdTemp)
{
hrRet=E_OUTOFMEMORY;
goto cleanup;
}
//request command interface pointer from the dispatch passed
hrRet=pIDispBaseCommand->QueryInterface(IID_IGWCommand, (void**)&pigwBaseCmd);
pgpAssert(SUCCEEDED(hrRet) && (NULL != pigwBaseCmd));
if(FAILED(hrRet) || (NULL == pigwBaseCmd))
goto cleanup;
//put the base command dispatch in the object
pcgwCmdTemp->Set_BaseCommand(pigwBaseCmd);
//request a dispatch interface. GW frees up this later. evidently it does not
//do addref and assumes it is already addrefed
hrRet=pcgwCmdTemp->QueryInterface(IID_IDispatch, (void**)ppIDispGWCommand);
pgpAssert(SUCCEEDED(hrRet) && (NULL != *ppIDispGWCommand));
if(FAILED(hrRet) || (NULL == *ppIDispGWCommand))
goto cleanup;
cleanup:
return S_OK;
}
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::WantCommand
//
// Description:This method is used to query the C3po for it's
// intention to support a predefined command.
//
// In:BSTR bstrContext This is the actual object class associates
// with the command.
// BSTR bstrPersistentID This can be either a "pre-defined"
// ID or is an ID provided in a previous run of GW.
//
// Out:VARIANT_BOOL FAR* pbChanged
// TRUE - I do want to support this predefined command
// FALSE - I do not want to support this predefined command
//
// Comments: Not Implemented
////////////////////////////////////////////////////////////////////
STDMETHODIMP CCommandFactory::WantCommand(BSTR bstrContext,
BSTR bstrPersistentID, VARIANT_BOOL FAR* pbChanged)
{
PgpGwTrace("CCommandFactory::WantCommand(context=%S, id=%S)\n",
bstrContext, bstrPersistentID);
//if it is a mail or the attachment viewer being opened
if(((0 != wcsstr(bstrContext, MAILMESSAGECONTEXTW)) ||
(0 != wcsstr(bstrContext, ATTCHVIEWERCONTEXTW))) &&
(0 == _wcsicmp(bstrPersistentID, wceGW_CMDID_OPEN)))
{
//check if auto-decrypt bit on open is set in pgp options
PGPBoolean pgpbFlag=FALSE;
BOOL bRet=PgpGwGetBoolPref(kPGPPrefAutoDecrypt, pgpbFlag);
pgpAssert(TRUE == bRet);
//we trap open only if the the bit is set
*pbChanged=pgpbFlag;
}
else
*pbChanged=FALSE;
return S_OK;
}
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::CustomizeContextMenu
//
// Description:Method to customize the menu.
//
// In:BSTR bstrContext The context string property is the class of the
// containing window. For example "GW.APPLICATION.BROWSER"
// IDispatch * pIDispGWMenu - The main menu object being modified.
//
// Out:TOleBool - The return value indicates whether the modifications
// to the menu were "volatile". If the return value is TRUE,
// CustomizeMenu() will continue to be called each time the menu
// may need to be updated e.g. at each popup creation). Otherwise,
// C3PO servers can safely assume that CustomizeMenu is called only
// once for any single instance of a menu. This simplifies the
// resulting code because there is no need to check for commands
// that might already be on the menu. That is, the C3PO's command
// are guaranteed to be absent from the menu at the time of the
// first CustomizeMenu call.
//
// Comments:
////////////////////////////////////////////////////////////////////
STDMETHODIMP CCommandFactory::CustomizeContextMenu(BSTR bstrContext,
IDispatch * pIDispGWMenu)
{
PgpGwTrace("CCommandFactory::CustomizeContextMenu(%S)\n", bstrContext);
IGWMenu *pIMenu=NULL;
IGWMenuItems *pIMenuItems=NULL;
IDispatch *pIDisp=NULL;
IGWClientState *pClientState=NULL;
IGWMessageList *pMsgs=NULL;
HRESULT hrRet=S_OK;
VARIANT vr={0};
BSTR bstrCaption=NULL;
LONG lMsgCount=0;
int iResult=0;
BSTR bstrResult=NULL;
VARIANT_BOOL bResult;
TCHAR *pstr=NULL;
if (0 != wcsstr(bstrContext, MAILMESSAGECONTEXTW)) // See if it is the correct context
{
//get client state to determine if we're being called
//from the main browser, not from inside a view.
hrRet=m_pIMgr->get_ClientState(&pIDisp);
hrRet=pIDisp->QueryInterface(IID_IClientState, (void **)&pClientState);
pIDisp->Release();
pIDisp = NULL;
hrRet = pClientState->get_SelectedMessages (&pIDisp);
hrRet = pIDisp->QueryInterface(IID_IGWMessageList, (void **)&pMsgs);
pIDisp->Release ();
pIDisp = NULL;
hrRet = pMsgs->get_Count (&lMsgCount);
pClientState->Release ();
pClientState = NULL;
if (0 == lMsgCount)
{
// We're in a view, now see if it's a compose view
g_pigwcCommander->Execute (g_bstrValidateCmd, &bstrResult, &bResult);
pstr = FROM_OLE_STRING(bstrResult);
// Handle OnReady event
if (strcmp(pstr, NEWMESSAGEMSGIDA) == 0)
{
hrRet = pIDispGWMenu->QueryInterface(IID_IGWMenu, (void**)&pIMenu);
//Add menu item
// Get Menu Items menu
hrRet = pIMenu->get_MenuItems(&pIDisp);
pIMenu->Release();
// Get Cts Menu Items interfaces
hrRet = pIDisp->QueryInterface(IID_IGWMenuItems, (void**)&pIMenuItems);
pIDisp->Release();
// Create new GWCommand object for menu item
CGWCommand *Cmd01 = new CGWCommand(IDC_ODMA_ATTACH, 0);
Cmd01->QueryInterface(IID_IDispatch, (void**)&pIDisp);
bstrCaption = SysAllocString(L"Attach ODMA Document...");
VariantInit(&vr);
vr.lVal = 3;
vr.vt = VT_I4;
hrRet = pIMenuItems->Add(bstrCaption, pIDisp, vr, &pIDisp ); //Add menu item to menu
SysFreeString(bstrCaption);
Cmd01->m_bstrLongPrompt = SysAllocString(L"Add attachments from an ODMA Document Management System"); // Set Long Prompt for menu item
Cmd01->Release();
pIDisp->Release();
pIMenuItems->Release();
}
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////
// Name:CCommandFactory::CustomizeMenu
//
// Description:Method to customise the menu.
//
// In:BSTR bstrContext - The context string property is the class
// of the containing window. For example "GW.APPLICATION.BROWSER"
// IDispatch * pIDispGWMenu - The main menu object being modified.
//
// Out:VARIANT_BOOL FAR* pbChanged - The return value indicates
// whether the modifications to the menu were "volatile". If
// the return value is TRUE, CustomizeMenu() will continue to
// be called each time the menu may need to be updated e.g. at
// each popup creation). Otherwise, C3PO servers can safely
// assume that CustomizeMenu is called only once for any single
// instance of a menu. This simplifies the resulting code because
// there is no need to check for commands that might already be on
// the menu. That is, the C3PO's command are guaranteed to be
// absent from the menu at the time of the first CustomizeMenu
// call.
//
// Comments:
////////////////////////////////////////////////////////////////////
STDMETHODIMP CCommandFactory::CustomizeMenu(BSTR bstrContext,
IDispatch * pIDispGWMenu, VARIANT_BOOL FAR* pbChanged)
{
PgpGwTrace("CCommandFactory::CustomizeMenu(%S)\n", bstrContext);
IGWMenu *pIMenu=NULL;
IGWMenuItems *pIMenuItems=NULL;
IDispatch *pIDispTemp=NULL, *pIDispTempTwo=NULL;
HRESULT hrRet=S_OK;
BOOL bRet=TRUE;
VARIANT vTmpOne={0};
VARIANT vTmpTwo={0};
char *pszPrependMenuString=NULL, *pszMainMenuString=NULL;
BSTR bstrCaption=NULL;
BSTR bstrMessageId=NULL;
CGWCommand *pcgwCmdTemp=NULL;
DWORD dwCmdUiOptions=CUIO_IS_MENUBAR_ITEM;
//if it is the main browser window
if(0 != wcsstr(bstrContext, MAINWINDOWCONTEXTW))
dwCmdUiOptions |= CUIO_MAINWND_CONTEXT;
//or if it is a mail message
else if (0 != wcsstr(bstrContext, MAILMESSAGECONTEXTW))
{
dwCmdUiOptions |= CUIO_MAIL_CONTEXT;
//additionally if it is a discussion post
if(0 != wcsstr(bstrContext, DISCUSSIONCONTEXTW))
dwCmdUiOptions |= CUIO_DISCUSSION_CONTEXT;
//discussion post context is unfortunately a subclass of mail context
//so this check needs to be done so we know later that it is a discussion
//rather than normal mail. the "post" of discussion will kick our tph
//which would ignore any operations upon detecting this flag
}
//or if it is the attachment window
else if(0 != wcsstr(bstrContext, ATTCHVIEWERCONTEXTW))
dwCmdUiOptions |= CUIO_ATTVIEW_CONTEXT;
else//if it is neither a mail message nor the main window nor
{ //the attachment viewer window
pgpAssert(FALSE);//erroneous install/faulty hooking
goto cleanup;//bail out (we are done)
}
//request IGWMenu interface of the menu passed
pgpAssert((NULL != pIDispGWMenu) && (NULL == pIMenu));
hrRet = pIDispGWMenu->QueryInterface(IID_IGWMenu, (void**)&pIMenu);
pgpAssert(SUCCEEDED(hrRet) && (NULL != pIMenu));
if(FAILED(hrRet) || (NULL == pIMenu))
goto cleanup;
TraceRefCount(pIMenu);//***
//query for the read only property MenuItems (of the menu object)
pgpAssert(NULL == pIDispTemp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -