windows-nt/Source/XPSP1/NT/shell/ext/inetfind/fndcm.c
2020-09-26 16:20:57 +08:00

376 lines
9.2 KiB
C

/*****************************************************************************
*
* fndcm.c - IContextMenu interface
*
*****************************************************************************/
#include "fnd.h"
/*****************************************************************************
*
* The sqiffle for this file.
*
*****************************************************************************/
#define sqfl sqflCm
/*****************************************************************************
*
* PICI
*
* I'm getting lazy.
*
*****************************************************************************/
typedef LPCMINVOKECOMMANDINFO PICI;
/*****************************************************************************
*
* Declare the interfaces we will be providing.
*
* We must implement an IShellExtInit so the shell
* will know that we are ready for action.
*
*****************************************************************************/
Primary_Interface(CFndCm, IContextMenu);
Secondary_Interface(CFndCm, IShellExtInit);
/*****************************************************************************
*
* CFndCm
*
* The context menu extension for "Find .... On the &Internet".
*
*****************************************************************************/
typedef struct CFndCm {
/* Supported interfaces */
IContextMenu cm;
IShellExtInit sxi;
} CFndCm, FCM, *PFCM;
typedef IContextMenu CM, *PCM;
typedef IShellExtInit SXI, *PSXI;
typedef IDataObject DTO, *PDTO;
/*****************************************************************************
*
* CFndCm_QueryInterface (from IUnknown)
*
* We need to check for our additional interfaces before falling
* through to Common_QueryInterface.
*
*****************************************************************************/
STDMETHODIMP
CFndCm_QueryInterface(PCM pcm, RIID riid, PPV ppvObj)
{
PFCM this = IToClass(CFndCm, cm, pcm);
HRESULT hres;
if (IsEqualIID(riid, &IID_IShellExtInit)) {
*ppvObj = &this->sxi;
Common_AddRef(this);
hres = NOERROR;
} else {
hres = Common_QueryInterface(this, riid, ppvObj);
}
AssertF(fLimpFF(FAILED(hres), *ppvObj == 0));
return hres;
}
/*****************************************************************************
*
* CFndCm_AddRef (from IUnknown)
* CFndCm_Release (from IUnknown)
*
*****************************************************************************/
#ifdef DEBUG
Default_AddRef(CFndCm)
Default_Release(CFndCm)
#else
#define CFndCm_AddRef Common_AddRef
#define CFndCm_Release Common_Release
#endif
/*****************************************************************************
*
* CFndCm_Finalize (from Common)
*
* Release the resources of an CFndCm.
*
*****************************************************************************/
void EXTERNAL
CFndCm_Finalize(PV pv)
{
PFCM this = pv;
EnterProc(CFndCm_Finalize, (_ "p", pv));
ExitProc();
}
/*****************************************************************************
*
* CFndCm_QueryContextMenu (From IContextMenu)
*
* Given an existing context menu hmenu, insert new context menu
* items at location imi (imi = index to menu imi), returning the
* number of menu items added.
*
* Our job is to add the "Find ... On the Internet" menu option.
*
* hmenu - destination menu
* imi - location at which menu items should be inserted
* idcMin - first available menu identifier
* idcMax - first unavailable menu identifier
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
TCHAR c_tszMyself[] = TEXT(".{37865980-75d1-11cf-bfc7-444553540000}");
#pragma END_CONST_DATA
STDMETHODIMP
CFndCm_QueryContextMenu(PCM pcm, HMENU hmenu, UINT imi,
UINT idcMin, UINT idcMax, UINT uFlags)
{
PFCM this = IToClass(CFndCm, cm, pcm);
HRESULT hres;
MENUITEMINFO mii;
TCHAR tsz[256];
SHFILEINFO sfi;
EnterProc(CFndCm_QueryContextMenu, (_ "pu", pcm, idcMin));
LoadString(g_hinst, IDS_ONTHEINTERNET, tsz, cA(tsz));
SHGetFileInfo(c_tszMyself, FILE_ATTRIBUTE_DIRECTORY, &sfi, cbX(sfi),
SHGFI_SMALLICON |
SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_DATA | MIIM_ID | MIIM_TYPE;
mii.fType = MFT_STRING;
mii.fState = MFS_UNCHECKED;
mii.wID = idcMin;
mii.dwItemData = sfi.iIcon;
mii.dwTypeData = tsz;
InsertMenuItem(hmenu, imi, TRUE, &mii);
hres = hresUs(1);
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* _CFndCm_InvokeFind
*
* Go find it by launching the search URL.
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
TCHAR c_tszIEMain[] = TEXT("Software\\Microsoft\\Internet Explorer\\Main");
TCHAR c_tszSearch[] = TEXT("Search Page");
TCHAR c_tszDefSearch[] = TEXT("http://http://www.msn.com/access/allinone.htm");
#pragma END_CONST_DATA
STDMETHODIMP
_CFndCm_InvokeFind(void)
{
HRESULT hres;
HKEY hk;
if (RegOpenKeyEx(HKEY_CURRENT_USER, c_tszIEMain,
0, KEY_ALL_ACCESS, &hk) == 0) {
TCHAR tsz[MAX_PATH];
LPCTSTR ptsz;
DWORD cb = cbX(tsz);
if (RegQueryValueEx(hk, c_tszSearch, 0, 0, tsz, &cb) == 0) {
ptsz = tsz;
} else {
ptsz = c_tszDefSearch;
}
if (ShellExecute(0, 0, tsz, 0, 0, SW_NORMAL)) {
hres = S_OK;
} else {
hres = E_FAIL;
}
RegCloseKey(hk);
} else {
hres = E_FAIL;
}
return hres;
}
/*****************************************************************************
*
* CFndCm_InvokeCommand (from IContextMenu)
*
* We have only one command, called "find".
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
TCHAR c_tszFind[] = TEXT("find");
#pragma END_CONST_DATA
STDMETHODIMP
CFndCm_InvokeCommand(PCM pcm, PICI pici)
{
PFCM this = IToClass(CFndCm, cm, pcm);
HRESULT hres;
EnterProc(CFndCm_InvokeCommand,
(_ HIWORD(pici->lpVerb) ? "pA" : "pu", pcm, pici->lpVerb));
if (pici->cbSize >= sizeof(*pici)) {
if (
#ifdef SHELL32_IS_BUG_FREE //;Internal
(HIWORD(pici->lpVerb) && lstrcmpi(c_tszFind, pici->lpVerb) == 0) || //;Internal
pici->lpVerb == 0 //;Internal
#else //;Internal
fLimpFF(HIWORD(pici->lpVerb), lstrcmpi(c_tszFind, pici->lpVerb) == 0)
#endif //;Internal
) {
hres = _CFndCm_InvokeFind();
} else {
hres = E_INVALIDARG;
}
} else {
hres = E_INVALIDARG;
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* CFndCm_GetCommandString (from IContextMenu)
*
* Somebody wants to convert a command id into a string of some sort.
*
*****************************************************************************/
STDMETHODIMP
CFndCm_GetCommandString(PCM pcm, UINT_PTR idCmd, UINT uFlags, UINT *pwRsv,
LPSTR pszName, UINT cchMax)
{
PFCM this = IToClass(CFndCm, cm, pcm);
HRESULT hres;
EnterProc(CFndCm_GetCommandString, (_ "uu", idCmd, uFlags));
if (idCmd == 0) {
switch (uFlags) {
case GCS_HELPTEXT:
if (cchMax) {
pszName[0] = '\0';
if (LoadString(g_hinst, IDS_FINDHELP, pszName, cchMax)) {
hres = NOERROR;
} else {
hres = E_INVALIDARG;
}
} else {
hres = E_INVALIDARG;
}
break;
case GCS_VALIDATE:
hres = NOERROR;
break;
case GCS_VERB:
lstrcpyn(pszName, c_tszFind, cchMax);
hres = NOERROR;
break;
default:
hres = E_NOTIMPL;
break;
}
} else {
hres = E_INVALIDARG;
}
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* CFndCm_SXI_Initialize (from IShellExtension)
*
*****************************************************************************/
STDMETHODIMP
CFndCm_SXI_Initialize(PSXI psxi, PCIDL pidlFolder, PDTO pdto, HKEY hk)
{
PFCM this = IToClass(CFndCm, sxi, psxi);
HRESULT hres;
EnterProc(CFndCm_SXI_Initialize, (_ ""));
hres = S_OK;
ExitOleProc();
return hres;
}
/*****************************************************************************
*
* CFndCm_New (from IClassFactory)
*
* Note that we release the pfcm that Common_New created, because we
* are done with it. The real refcount is handled by the
* CFndCm_QueryInterface.
*
*****************************************************************************/
STDMETHODIMP
CFndCm_New(RIID riid, PPV ppvObj)
{
HRESULT hres;
EnterProc(CFndCm_New, (_ "G", riid));
*ppvObj = 0;
hres = Common_New(CFndCm, ppvObj);
if (SUCCEEDED(hres)) {
PFCM pfcm = *ppvObj;
pfcm->sxi.lpVtbl = Secondary_Vtbl(CFndCm, IShellExtInit);
hres = CFndCm_QueryInterface(&pfcm->cm, riid, ppvObj);
Common_Release(pfcm);
}
ExitOleProcPpv(ppvObj);
return hres;
}
/*****************************************************************************
*
* The long-awaited vtbls
*
*****************************************************************************/
#pragma BEGIN_CONST_DATA
Primary_Interface_Begin(CFndCm, IContextMenu)
CFndCm_QueryContextMenu,
CFndCm_InvokeCommand,
CFndCm_GetCommandString,
Primary_Interface_End(CFndCm, IContextMenu)
Secondary_Interface_Begin(CFndCm, IShellExtInit, sxi)
CFndCm_SXI_Initialize,
Secondary_Interface_End(CFndCm, IShellExtInit, sxi)