Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
openwith.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 33k
Category:
Windows Kernel
Development Platform:
Visual C++
- //---------------------------------------------------------------------------
- //
- // Copyright (c) Microsoft Corporation
- //
- // File: openwith.cpp
- //
- // This file contains the implementation of COpenWithMenu, a context menu handler
- //
- // History:
- // 2-27-98 by ningz
- // 3-SEP-98 ZekeL - rewrote ExtAppList() and moved it here
- //------------------------------------------------------------------------
- #include "shellprv.h"
- #include <fsmenu.h>
- #include "ids.h"
- #include <shlwapi.h>
- #include "openwith.h"
- #include "uemapp.h"
- #define TF_OPENWITHMENU 0x00004000
- #define SZOPENWITHLIST TEXT("OpenWithList")
- #define REGSTR_PATH_EXPLORER_FILEEXTS TEXT("Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts")
- #define _OpenWithListMaxItems() 10
- typedef struct _OpenWithList {
- HANDLE hMRU;
- HANDLE hMutex;
- HKEY hkLM;
- HKEY hkCU;
- } OPENWITHLIST, *POPENWITHLIST;
- LONG _CreateListMutex(LPCTSTR pszExt, HANDLE *phMutex)
- {
- TCHAR szMutex[MAX_PATH];
- wnsprintf(szMutex, SIZECHARS(szMutex), TEXT("%s%s"), SZOPENWITHLIST, pszExt);
- CharLower(szMutex);
- *phMutex = CreateMutex(CreateAllAccessSecurityAttributes(NULL, NULL, NULL), FALSE, szMutex);
- if (!*phMutex)
- return GetLastError();
- return NOERROR;
- }
- inline BOOL _GrabMutex(HANDLE hMutex)
- {
- DWORD dwResult = WaitForSingleObject(hMutex, INFINITE);
- return (WAIT_OBJECT_0 == dwResult) ;
- }
- //
- // OpenWithListClose()
- // Frees up resources allocated by OpenWithListOpen(). No return value.
- //
- void OpenWithListClose(IN HANDLE hList)
- {
- POPENWITHLIST pList = (POPENWITHLIST) hList;
- TraceMsg(TF_OPENWITHMENU, "[%X] OpenWithListClose() called", pList);
- if (pList)
- {
- if (pList->hMutex)
- CloseHandle(pList->hMutex);
- if (pList->hkCU)
- RegCloseKey(pList->hkCU);
- if (pList->hkLM)
- RegCloseKey(pList->hkLM);
- if (pList->hMRU)
- FreeMRUList(pList->hMRU);
- LocalFree(pList);
- }
- return;
- }
- //
- // OpenWithListOpen()
- // allocates and initializes the state for the openwithlist
- //
- HRESULT OpenWithListOpen(IN LPCTSTR pszExt, HANDLE *phList)
- {
- LONG lResult;
- if (!pszExt || !*pszExt || !phList)
- return E_INVALIDARG;
- *phList = NULL;
- POPENWITHLIST pList = (POPENWITHLIST) LocalAlloc(LPTR, sizeof(OPENWITHLIST));
- if (!pList)
- return E_OUTOFMEMORY;
- lResult = _CreateListMutex(pszExt, &pList->hMutex);
- if (NOERROR == lResult)
- {
- TCHAR szSubKey[MAX_PATH];
- // Build up the subkey string.
- wnsprintf(szSubKey, SIZECHARS(szSubKey), TEXT("%s\%s\%s"), REGSTR_PATH_EXPLORER_FILEEXTS, pszExt, SZOPENWITHLIST);
- MRUINFO mi = {sizeof(mi), _OpenWithListMaxItems(), 0, HKEY_CURRENT_USER, szSubKey, NULL};
- pList->hMRU = CreateMRUList(&mi);
- // the MRU list initializes the key a specific way so that
- // it is a real MRU...
- if (pList->hMRU)
- {
- lResult = RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0L,
- MAXIMUM_ALLOWED, &(pList->hkCU));
- if (ERROR_SUCCESS == lResult)
- {
- // make different subkey for LM
- wnsprintf(szSubKey, SIZECHARS(szSubKey), TEXT("%s\%s"), pszExt, SZOPENWITHLIST);
- RegOpenKeyEx(HKEY_CLASSES_ROOT, szSubKey, 0L,
- MAXIMUM_ALLOWED, &(pList->hkLM));
- }
- }
- else // !pList->hMRU
- lResult = ERROR_BADKEY;
- }
- if (NOERROR != lResult)
- {
- OpenWithListClose((HANDLE)pList);
- TraceMsg(TF_OPENWITHMENU, "OpenWithListOpen() failed on %s, err = %d", pszExt, lResult);
- return HRESULT_FROM_WIN32(lResult);
- }
- TraceMsg(TF_OPENWITHMENU, "[%X] OpenWithListOpen() created on %s", pList, pszExt);
- *phList = (HANDLE) pList;
- return S_OK;
- }
- HRESULT _AddItem(HANDLE hMRU, HKEY hkList, LPCTSTR pszName)
- {
- HRESULT hr = S_OK;
- if (hMRU)
- {
- int cItems = EnumMRUList(hMRU, -1, NULL, 0L);
- // just trim us down to make room...
- while (cItems >= _OpenWithListMaxItems())
- DelMRUString(hMRU, --cItems);
- if (0 > AddMRUString(hMRU, pszName))
- hr = E_UNEXPECTED;
- }
- return hr;
- }
- void _DeleteItem(POPENWITHLIST pList, LPCTSTR pszName)
- {
- int iItem = FindMRUString(pList->hMRU, pszName, NULL);
- if (0 <= iItem) {
- DelMRUString(pList->hMRU, iItem);
- }
- }
- STDAPI OpenWithListRegister(DWORD dwFlags, LPCTSTR pszExt, LPCTSTR pszVerb, HKEY hkProgid)
- {
- if (!pszExt || !hkProgid)
- return E_INVALIDARG;
- POPENWITHLIST pList;
- //
- // ----> Peruser entries are stored here
- // HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerFileExts
- // .Ext
- // Application = "foo.exe"
- // OpenWithList
- // MRUList = "ab"
- // a = "App.exe"
- // b = "foo.exe"
- //
- // ----> for permanent entries are stored un HKCR
- // HKCR
- // .Ext
- // OpenWithList
- // app.exe
- //
- // ----> and applications or the system can write app association here
- // Applications
- // APP.EXE
- // shell...
- // foo.exe
- // shell...
- //
- //
- HRESULT hr = OpenWithListOpen(pszExt, (HANDLE *)&pList);
- if (SUCCEEDED(hr))
- {
- if (_GrabMutex(pList->hMutex))
- {
- TCHAR szPath[MAX_PATH];
- HRESULT hr = AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, hkProgid, pszVerb, szPath, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(szPath)));
- if (SUCCEEDED(hr))
- {
- LPCTSTR pszExe = PathFindFileName(szPath);
- if (IsPathInOpenWithKillList(pszExe))
- hr = E_ACCESSDENIED;
- else
- hr = AssocMakeApplicationByKey(ASSOCMAKEF_VERIFY, hkProgid, pszVerb);
- if (SUCCEEDED(hr))
- {
- TraceMsg(TF_OPENWITHMENU, "[%X] OpenWithListRegister() adding %s",pList, pszExe);
- hr = _AddItem(pList->hMRU, pList->hkCU, pszExe);
- }
- if (FAILED(hr))
- _DeleteItem(pList, pszExe);
- }
- ReleaseMutex(pList->hMutex);
- }
- else
- hr = E_UNEXPECTED;
- OpenWithListClose(pList);
- }
- return hr;
- }
- STDAPI_(void) OpenWithListSoftRegisterProcess(DWORD dwFlags, LPCTSTR pszExt)
- {
- if (!pszExt || !*pszExt)
- return;
- POPENWITHLIST pList;
- if (SUCCEEDED(OpenWithListOpen(pszExt, (HANDLE *)&pList)))
- {
- if (_GrabMutex(pList->hMutex))
- {
- TCHAR szApp[MAX_PATH];
- if (GetModuleFileName(NULL, szApp, SIZECHARS(szApp))
- && !IsPathInOpenWithKillList(szApp))
- _AddItem(pList->hMRU, pList->hkCU, PathFindFileName(szApp));
- ReleaseMutex(pList->hMutex);
- }
- OpenWithListClose(pList);
- }
- }
- typedef struct _OpenWithItem
- {
- LPTSTR pszFriendly;
- LPTSTR pszVerb;
- HKEY hKey;
- } OPENWITHITEM, *POPENWITHITEM;
- BOOL _GetAppKey(LPCTSTR pszApp, HKEY *phkApp)
- {
- ASSERT(pszApp && *pszApp);
- TCHAR szKey[MAX_PATH];
- lstrcpy(szKey, TEXT("Applications\"));
- StrCatBuff(szKey, pszApp, SIZECHARS(szKey));
- return (NOERROR == RegOpenKeyEx(
- HKEY_CLASSES_ROOT,
- szKey,
- 0L,
- MAXIMUM_ALLOWED,
- phkApp));
- }
- DWORD _AppListEnumLM(HKEY hkey, HANDLE hMRU, LPCTSTR pszVerb, POPENWITHITEM pItems, ULONG cItems, DWORD index)
- {
- for (DWORD iItem = 0; index < cItems; iItem++)
- {
- TCHAR sz[MAX_PATH];
- DWORD cch;
- HKEY hkItem;
- cch = SIZECHARS(sz);
- if (NOERROR != RegEnumKeyEx(hkey, iItem, sz, &cch,
- NULL, NULL, NULL, NULL))
- break;
- // if we already tried this from the MRU or
- // if the APP key doesnt exist here, then
- // just continue on to the next item
- if ((0 <= FindMRUString(hMRU, sz, NULL))
- || IsPathInOpenWithKillList(sz)
- || !_GetAppKey(sz, &hkItem))
- continue;
- ASSERT(hkItem);
- //
- // this will filter out apps that dont support the specified verb
- // we reuse sz here.
- if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY | ASSOCF_OPEN_BYEXENAME, ASSOCSTR_FRIENDLYAPPNAME, hkItem, pszVerb, sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
- {
- pItems[index].pszFriendly = StrDup(sz);
- pItems[index].pszVerb = pszVerb ? StrDup(pszVerb) : NULL;
- pItems[index].hKey = hkItem;
- hkItem = NULL;
- index++;
- }
- if (hkItem)
- RegCloseKey(hkItem);
- } // for
- return index;
- }
- void _ReleaseListItem(POPENWITHITEM pItem)
- {
- if (pItem->pszFriendly)
- LocalFree(pItem->pszFriendly);
- if (pItem->pszVerb)
- LocalFree(pItem->pszVerb);
- if (pItem->hKey)
- RegCloseKey(pItem->hKey);
- // since this is called from only one place,
- // we dont actually need to clear the values...
- // ZeroMemory(pItem, SIZEOF(OPENWITHITEM))
- }
- //
- // Must declare an explicit structure to keep Win64 happy.
- // We actually hand out an internal pointer to the rgItems array,
- // but occasionally we need to peek at the cItems.
- //
- typedef struct ITEMSLIST {
- DWORD cItems;
- OPENWITHITEM rgItems[1];
- } ITEMSLIST, *PITEMSLIST;
- void OpenWithListReleaseList(POPENWITHITEM pItems)
- {
- if (pItems)
- {
- PITEMSLIST pList = CONTAINING_RECORD(pItems, ITEMSLIST, rgItems);
- DWORD cItems = pList->cItems;
- for (DWORD i = 0; i < cItems; i++)
- _ReleaseListItem(&pList->rgItems[i]);
- LocalFree(pList);
- }
- }
- DWORD _AllocList(POPENWITHLIST pList, POPENWITHITEM *ppItems)
- {
- DWORD cResult = (DWORD) EnumMRUList(pList->hMRU, -1, NULL, 0L);
- if (cResult == (DWORD)-1)
- cResult = 0;
- if (pList->hkLM)
- {
- DWORD dw = 0;
- RegQueryInfoKey(
- pList->hkLM,
- NULL,
- NULL,
- NULL,
- &dw,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- );
- cResult += dw;
- }
- if (cResult)
- {
- PITEMSLIST pList = (PITEMSLIST)LocalAlloc(LPTR, FIELD_OFFSET(ITEMSLIST, rgItems[cResult]));
- if(pList)
- *ppItems = &pList->rgItems[0];
- else
- cResult = 0;
- }
- return cResult;
- }
- DWORD _AppListEnumMRU(HANDLE hMRU, LPCTSTR pszVerb, POPENWITHITEM pItems, ULONG cItems, DWORD index)
- {
- for (int iItem = 0; index < cItems; iItem++)
- {
- TCHAR sz[MAX_PATH];
- HKEY hkItem;
- if (0 > EnumMRUList(hMRU, iItem, sz, SIZECHARS(sz)))
- break;
- // dont quit if we couldnt get this key...
- if (IsPathInOpenWithKillList(sz) || !_GetAppKey(sz, &hkItem))
- continue;
- ASSERT(hkItem);
- //
- // this will filter out apps that dont support the specified verb
- // we reuse sz here.
- if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY | ASSOCF_OPEN_BYEXENAME, ASSOCSTR_FRIENDLYAPPNAME, hkItem, pszVerb, sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz)))))
- {
- pItems[index].pszFriendly = StrDup(sz);
- pItems[index].pszVerb = pszVerb ? StrDup(pszVerb) : NULL;
- pItems[index].hKey = hkItem;
- hkItem = NULL;
- index++;
- }
- if (hkItem)
- RegCloseKey(hkItem);
- } // for
- return index;
- }
- //
- // OpenWithListGetList()
- //
- // Allocates and initializes a list of all the openwithlist items
- // that are associated with the pszExt, and can shellexecute pszVerb.
- // if the pszVerb is NULL, the default verbs are allowed
- //
- DWORD OpenWithListGetList(LPCTSTR pszExt, LPCTSTR pszVerb, POPENWITHITEM *ppItems)
- {
- POPENWITHLIST pList;
- DWORD cResult = 0;
- if (!pszExt || !ppItems)
- return 0;
- *ppItems = NULL;
- if (SUCCEEDED(OpenWithListOpen(pszExt, (HANDLE *)&pList)))
- {
- if (_GrabMutex(pList->hMutex))
- {
- POPENWITHITEM pItems;
- LONG cItems = _AllocList(pList, &pItems);
- if (cItems)
- {
- // enum the MRU first, and then if there are
- // any that were under HKCR, them we will add them too.
- cResult = _AppListEnumMRU(pList->hMRU, pszVerb, pItems, cItems, 0);
- if (pList->hkLM)
- cResult =_AppListEnumLM(pList->hkLM, pList->hMRU, pszVerb, pItems, cItems, cResult);
- if (cResult)
- {
- PITEMSLIST pList = CONTAINING_RECORD(pItems, ITEMSLIST, rgItems);
- pList->cItems = cResult;
- *ppItems = pItems;
- }
- else
- {
- OpenWithListReleaseList(pItems);
- }
- }
- ReleaseMutex(pList->hMutex);
- }
- OpenWithListClose((HANDLE)pList);
- }
- return cResult;
- }
- typedef struct
- {
- TCHAR szMenuText[MAX_PATH];
- int iImage;
- DWORD dwFlags;
- } OPENWITHMENUITEMINFO, * LPOPENWITHMENUITEMINFO;
- // format strings
- const TCHAR c_szSShellSCommand[] = TEXT("%s\Shell\%s\Command");
- const TCHAR c_szSShell[] = TEXT("%s\Shell");
- class COpenWithMenu : public IContextMenu3, IShellExtInit,IObjectWithSite
- {
- // IUnknown
- STDMETHOD(QueryInterface)(REFIID riid, void **ppvObj);
- STDMETHOD_(ULONG,AddRef)(void);
- STDMETHOD_(ULONG,Release)(void);
- // IContextMenu
- STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
- STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici);
- STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uType, UINT *pRes, LPSTR pszName, UINT cchMax);
- // IContextMenu2
- STDMETHOD(HandleMenuMsg)(UINT uMsg, WPARAM wParam, LPARAM lParam);
- // IContextMenu3
- STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam,LRESULT *lResult);
- // IShellExtInit
- STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
- //IObjectWithSite
- STDMETHOD(SetSite)(IUnknown*);
- STDMETHOD(GetSite)(REFIID,void**);
- int _cRef;
- HMENU _hMenu;
- UINT _idCmdFirst;
- int _nItems;
- UINT _uFlags;
- POPENWITHITEM _pItems;
- TCHAR _szPath[MAX_PATH];
- HIMAGELIST _himlSystemImageList;
- IDataObject *_pdtobj;
- IShellView2 *_pShellView2;
- LPCITEMIDLIST _pidlFolder;
- COpenWithMenu();
- ~COpenWithMenu();
- friend HRESULT COpenWithMenu_CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut);
- private:
- //Handle Menu messages submitted to HandleMenuMsg
- void DrawItem(DRAWITEMSTRUCT *lpdi);
- LRESULT MeasureItem(MEASUREITEMSTRUCT *lpmi);
- BOOL InitMenuPopup(HMENU hMenu);
- //Internal Helpers
- POPENWITHITEM GetItemData(HMENU hmenu, UINT iItem);
- };
- COpenWithMenu::COpenWithMenu() : _cRef(1)
- {
- TraceMsg(TF_OPENWITHMENU, "ctor COpenWithMenu %x", this);
- }
- COpenWithMenu::~COpenWithMenu()
- {
- TraceMsg(TF_OPENWITHMENU, "dtor COpenWithMenu %x", this);
- if (_pdtobj)
- _pdtobj->Release();
- if (_pItems)
- {
- OpenWithListReleaseList(_pItems);
- }
- //Safety Net: Release my site in case I manage to get
- // Released without my site SetSite(NULL) first.
- ATOMICRELEASE(_pShellView2);
- }
- STDAPI COpenWithMenu_CreateInstance(IUnknown* pUnkOuter, REFIID riid, OUT LPVOID * ppvOut)
- {
- HRESULT hr = E_FAIL;
- TraceMsg(TF_OPENWITHMENU, "COpenWithMenu_CreateInstance()");
- *ppvOut = NULL;
- if (pUnkOuter)
- return CLASS_E_NOAGGREGATION;
- COpenWithMenu * powm = new COpenWithMenu();
- if (!powm)
- return E_OUTOFMEMORY;
- hr = powm->QueryInterface(riid, (LPVOID *)ppvOut);
- powm->Release();
- return hr;
- }
- HRESULT COpenWithMenu::QueryInterface(REFIID riid, void **ppvObj)
- {
- if (IsEqualIID(riid, IID_IUnknown) ||
- IsEqualIID(riid, IID_IContextMenu) ||
- IsEqualIID(riid, IID_IContextMenu2) ||
- IsEqualIID(riid, IID_IContextMenu3))
- {
- *ppvObj = SAFECAST(this, IContextMenu3 *);
- }
- else if (IsEqualIID(riid, IID_IShellExtInit))
- {
- *ppvObj = SAFECAST(this, IShellExtInit *);
- }
- else if (IsEqualIID(riid, IID_IObjectWithSite))
- {
- *ppvObj = SAFECAST(this, IObjectWithSite *);
- }
- else
- {
- *ppvObj = NULL;
- return E_NOINTERFACE;
- }
- AddRef();
- return NOERROR;
- }
- ULONG COpenWithMenu::AddRef()
- {
- _cRef++;
- TraceMsg(TF_OPENWITHMENU, "COpenWithMenu::AddRef = %x", _cRef);
- return _cRef;
- }
- ULONG COpenWithMenu::Release()
- {
- _cRef--;
- TraceMsg(TF_OPENWITHMENU, "COpenWithMenu::Release = %x", _cRef);
- if (_cRef > 0)
- return _cRef;
- delete this;
- return 0;
- }
- /*
- Purpose:
- Add verb to extension app list
- */
- VOID AddVerbItem(IQueryAssociations *pqa, HKEY hkeyClass, LPCTSTR pszExt, LPCTSTR pszVerb)
- {
- WCHAR wsz[MAX_PATH];
- WCHAR wszVerb[MAX_PATH];
- // HackHack: we don't want to put msohtmed.exe in openwithlist
- if (pszVerb)
- SHTCharToUnicode(pszVerb, wszVerb, SIZECHARS(wszVerb));
- if (SUCCEEDED(pqa->GetString(0, ASSOCSTR_EXECUTABLE, pszVerb ? wszVerb : NULL, wsz,(LPDWORD)MAKEINTRESOURCE(SIZECHARS(wsz))))
- && (StrStrIW(wsz, L"msohtmed")))
- return;
- OpenWithListRegister(0, pszExt, pszVerb, hkeyClass);
- }
- /*
- Purpose:
- Add Open/Edit/Default verb to extension app list
- */
- HRESULT AddVerbItems(LPCTSTR pszExt)
- {
- IQueryAssociations *pqa;
- HRESULT hr = E_FAIL;
- if (SUCCEEDED(AssocCreate(CLSID_QueryAssociations, IID_IQueryAssociations, (LPVOID *)&pqa)))
- {
- HKEY hkeyClass;
- WCHAR wszExt[MAX_PATH];
- SHTCharToUnicode(pszExt, wszExt, SIZECHARS(wszExt));
- if (SUCCEEDED(pqa->Init(0, wszExt, NULL, NULL))
- && (SUCCEEDED(pqa->GetKey(0, ASSOCKEY_SHELLEXECCLASS, NULL, &hkeyClass))))
- {
- AddVerbItem(pqa, hkeyClass, pszExt, NULL);
- AddVerbItem(pqa, hkeyClass, pszExt, c_szOpen);
- AddVerbItem(pqa, hkeyClass, pszExt, c_szEdit);
- RegCloseKey(hkeyClass);
- hr = S_OK;
- }
- pqa->Release();
- }
- return hr;
- }
- HRESULT COpenWithMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
- {
- MENUITEMINFO mii;
- LPTSTR pszExt;
- TCHAR szOpenWithMenu[80];
- _idCmdFirst = idCmdFirst;
- _uFlags = uFlags;
- if (SUCCEEDED(PathFromDataObject(_pdtobj, _szPath, ARRAYSIZE(_szPath))))
- {
- // No openwith context menu for executables.
- if (PathIsExe(_szPath))
- return NOERROR;
- pszExt = PathFindExtension(_szPath);
- if (pszExt && *pszExt)
- {
- // Add Open/Edit/Default verb to extension app list
- if (SUCCEEDED(AddVerbItems(pszExt)))
- {
- // Do this only if AddVerbItems succeeded; otherwise,
- // we would create an empty MRU for a nonexisting class,
- // causing the class to spring into existence and cause
- // the "Open With" dialog to think we are overriding
- // rather than creating new.
- // get extension app list
- _nItems = OpenWithListGetList(pszExt, NULL, &_pItems);
- }
- }
- }
- // For known file type(there is at least one verb under its progid),
- // if there is only one item in its openwithlist, don't show open with sub menu
- if (1 == _nItems)
- {
- TCHAR szExe[MAX_PATH];
- DWORD cch = ARRAYSIZE(szExe);
- if (SUCCEEDED(AssocQueryString(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, pszExt, NULL, szExe, &cch)))
- {
- TCHAR szItem[MAX_PATH];
- cch = ARRAYSIZE(szItem);
- if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, _pItems[0].hKey, _pItems[0].pszVerb, szItem, &cch))
- && 0 == StrCmpI(szExe, szItem))
- {
- OpenWithListReleaseList(_pItems);
- _pItems = NULL;
- _nItems = 0;
- }
- }
- }
- LoadString(g_hinst, (_nItems ? IDS_OPENWITH : IDS_OPENWITHNEW), szOpenWithMenu, ARRAYSIZE(szOpenWithMenu));
- if (_nItems)
- {
- _hMenu = CreatePopupMenu();
- mii.cbSize = sizeof(MENUITEMINFO);
- mii.fMask = MIIM_ID|MIIM_TYPE|MIIM_DATA;
- mii.wID = idCmdFirst+1;
- mii.fType = MFT_STRING;
- mii.dwTypeData = szOpenWithMenu;
- mii.dwItemData = 0;
- InsertMenuItem(_hMenu,0,TRUE,&mii);
- mii.fMask = MIIM_ID|MIIM_SUBMENU|MIIM_TYPE;
- mii.fType = MFT_STRING;
- mii.wID = idCmdFirst;
- mii.hSubMenu = _hMenu;
- mii.dwTypeData = szOpenWithMenu;
- InsertMenuItem(hmenu,indexMenu,TRUE,&mii);
- return ResultFromShort(_nItems + 2);
- }
- else
- {
- _hMenu = hmenu;
- mii.cbSize = sizeof(MENUITEMINFO);
- mii.fMask = MIIM_ID|MIIM_TYPE|MIIM_DATA;
- mii.fType = MFT_STRING;
- mii.wID = idCmdFirst;
- mii.dwTypeData = szOpenWithMenu;
- mii.dwItemData = 0;
- InsertMenuItem(hmenu,indexMenu,TRUE,&mii);
- return ResultFromShort(1);
- }
- }
- HRESULT COpenWithMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
- {
- HRESULT hres = E_OUTOFMEMORY;
- CMINVOKECOMMANDINFOEX ici;
- LPVOID pvFree;
- // maybe these two routines should be collapsed into one?
- if ((IS_INTRESOURCE(pici->lpVerb) || 0 == lstrcmpiA(pici->lpVerb, "openas"))
- && SUCCEEDED(ICI2ICIX(pici, &ici, &pvFree)))
- {
- SHELLEXECUTEINFO ei = {0};
- if (SUCCEEDED(ICIX2SEI(&ici, &ei)))
- {
- POPENWITHITEM pItem;
- ei.lpFile = _szPath;
- if (IS_INTRESOURCE(pici->lpVerb))
- pItem = GetItemData(_hMenu, LOWORD(pici->lpVerb));
- else
- pItem = NULL;
- if (pItem)
- {
- // if pitem is there, this means that we are using
- // something that was in the openwith list MRU.
- ei.lpVerb = pItem->pszVerb;
- ei.hkeyClass = pItem->hKey;
- // make sure to update the MRU
- OpenWithListRegister(0, PathFindExtension(_szPath), pItem->pszVerb, pItem->hKey);
- }
- else
- {
- // use the "Unknown" key so we get the openwith prompt
- RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("Unknown"), 0L, MAXIMUM_ALLOWED, &ei.hkeyClass);
- if (!(_uFlags & CMF_DEFAULTONLY))
- {
- // defview sets CFM_DEFAULTONLY when the user is double-clicking. We check it
- // here since we want do NOT want to query the class store if the user explicitly
- // right-clicked on the menu and choo se openwith.
- // pop up open with dialog without querying class store
- ei.fMask |= SEE_MASK_NOQUERYCLASSSTORE;
- }
- }
- // if we got the key then we are good to go!
- if (ei.hkeyClass)
- {
- ei.fMask |= SEE_MASK_CLASSKEY;
- #ifdef WINNT
- // Shrink the shell since the user is about to run an application.
- ShrinkWorkingSet();
- #endif
- if (FALSE != ShellExecuteEx(&ei))
- {
- hres = NOERROR;
- #ifdef WINNT
- // Shrink the shell since the user just ran an application.
- ShrinkWorkingSet();
- #endif
- if (UEMIsLoaded())
- {
- // note that we already got a UIBL_DOTASSOC (from
- // OpenAs_RunDLL or whatever it is that 'Unknown'
- // runs). so the Uassist analysis app will have to
- // subtract it off
- UEMFireEvent(&UEMIID_SHELL, UEME_INSTRBROWSER, UEMF_INSTRUMENT, UIBW_RUNASSOC, UIBL_DOTNOASSOC);
- }
- }
- else
- {
- hres = E_FAIL;
- }
- // Close the Unknown key if we opened it
- if (!pItem && ei.hkeyClass)
- {
- RegCloseKey(ei.hkeyClass);
- }
- }
- }
- if (pvFree)
- LocalFree(pvFree);
- }
- return hres;
- }
- HRESULT COpenWithMenu::GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pRes, LPSTR pszName, UINT cchMax)
- {
- return E_NOTIMPL;
- }
- HRESULT COpenWithMenu::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- return HandleMenuMsg2(uMsg,wParam,lParam,NULL);
- }
- HRESULT COpenWithMenu::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam,LRESULT *lResult)
- {
- switch (uMsg)
- {
- case WM_INITMENUPOPUP:
- {
- InitMenuPopup(_hMenu);
- }
- break;
- /*
- case WM_DRAWITEM:
- {
- DRAWITEMSTRUCT * pdi = (DRAWITEMSTRUCT *)lParam;
- DrawItem(pdi);
- }
- break;
- case WM_MEASUREITEM:
- {
- MEASUREITEMSTRUCT *pmi = (MEASUREITEMSTRUCT *)lParam;
- MeasureItem(pmi);
- }
- break;
- case WM_MENUCHAR:
- {
- int c = GetMenuItemCount(_hMenu);
- for (int i = 0; i < c; i++)
- {
- LPOPENWITHMENUITEMINFO lpomi = GetItemData(_hMenu, i);
- if(lpomi && _MenuCharMatch(lpomi->szMenuText,(TCHAR)LOWORD(wParam),FALSE))
- {
- _lpomiLast = lpomi;
- if(lResult) *lResult = MAKELONG(i,MNC_EXECUTE);
- return S_OK;
- }
- }
- if(lResult) *lResult = MAKELONG(0,MNC_IGNORE);
- return S_FALSE;
- }
- */
- }
- return NOERROR;
- }
- HRESULT COpenWithMenu::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
- {
- if (_pdtobj)
- _pdtobj->Release();
- _pidlFolder = pidlFolder;
- _pdtobj = pdtobj;
- if (_pdtobj)
- _pdtobj->AddRef();
- return NOERROR;
- }
- void COpenWithMenu::DrawItem(DRAWITEMSTRUCT *lpdi)
- {
- /*
- if ((lpdi->itemAction & ODA_SELECT) || (lpdi->itemAction & ODA_DRAWENTIRE))
- {
- DWORD dwRop;
- int x, y;
- SIZE sz;
- LPOPENWITHMENUITEMINFO lpomi = (LPOPENWITHMENUITEMINFO)lpdi->itemData;
- // Draw the image (if there is one).
- GetTextExtentPoint(lpdi->hDC, lpomi->szMenuText, lstrlen(lpomi->szMenuText), &sz);
- if (lpdi->itemState & ODS_SELECTED)
- {
- SetBkColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHT));
- SetTextColor(lpdi->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
- // REVIEW HACK - keep track of the last selected item.
- _lpomiLast = lpomi;
- dwRop = SRCSTENCIL;
- FillRect(lpdi->hDC,&lpdi->rcItem,GetSysColorBrush(COLOR_HIGHLIGHT));
- }
- else
- {
- dwRop = SRCAND;
- SetTextColor(lpdi->hDC, GetSysColor(COLOR_MENUTEXT));
- FillRect(lpdi->hDC,&lpdi->rcItem,GetSysColorBrush(COLOR_MENU));
- }
- RECT rc = lpdi->rcItem;
- rc.left += +2*CXIMAGEGAP+g_cxSmIcon;
- DrawText(lpdi->hDC,lpomi->szMenuText,lstrlen(lpomi->szMenuText),
- &rc,DT_SINGLELINE|DT_VCENTER);
- if (lpomi->iImage != -1)
- {
- x = lpdi->rcItem.left+CXIMAGEGAP;
- y = (lpdi->rcItem.bottom+lpdi->rcItem.top-g_cySmIcon)/2;
- ImageList_Draw(g_himlSysSmall, lpomi->iImage, lpdi->hDC, x, y, ILD_TRANSPARENT);
- }
- else
- {
- x = lpdi->rcItem.left+CXIMAGEGAP;
- y = (lpdi->rcItem.bottom+lpdi->rcItem.top-g_cySmIcon)/2;
- }
- }
- */
- }
- LRESULT COpenWithMenu::MeasureItem(MEASUREITEMSTRUCT *lpmi)
- {
- LRESULT lres = FALSE;
- /*
- LPOPENWITHMENUITEMINFO lpomi = (LPOPENWITHMENUITEMINFO)lpmi->itemData;
- if (lpomi)
- {
- // Get the rough height of an item so we can work out when to break the
- // menu. User should really do this for us but that would be useful.
- HDC hdc = GetDC(NULL);
- if (hdc)
- {
- // REVIEW cache out the menu font?
- NONCLIENTMETRICS ncm;
- ncm.cbSize = SIZEOF(NONCLIENTMETRICS);
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, SIZEOF(ncm), &ncm, FALSE))
- {
- HFONT hfont = CreateFontIndirect(&ncm.lfMenuFont);
- if (hfont)
- {
- SIZE sz;
- HFONT hfontOld = (HFONT)SelectObject(hdc, hfont);
- GetTextExtentPoint(hdc, lpomi->szMenuText, lstrlen(lpomi->szMenuText), &sz);
- lpmi->itemHeight = max (g_cySmIcon+CXIMAGEGAP/2, ncm.iMenuHeight);
- lpmi->itemWidth = g_cxSmIcon + 2*CXIMAGEGAP + sz.cx;
- //lpmi->itemWidth = 2*CXIMAGEGAP + sz.cx;
- SelectObject(hdc, hfontOld);
- DeleteObject(hfont);
- lres = TRUE;
- }
- }
- ReleaseDC(NULL, hdc);
- }
- }
- else
- {
- TraceMsg(TF_OPENWITHMENU, TEXT("fm_mi: Filemenu is invalid."));
- }
- */
- return lres;
- }
- BOOL COpenWithMenu::InitMenuPopup(HMENU hmenu)
- {
- TCHAR szMenuText[80];
- MENUITEMINFO mii;
- TraceMsg(TF_OPENWITHMENU, "COpenWithMenu::InitMenuPopup");
- if (!_nItems || !_pItems)
- return FALSE;
- if (GetItemData(hmenu, 0)) // already initialized.
- return FALSE;
- // remove the place holder.
- DeleteMenu(hmenu,0,MF_BYPOSITION);
- // add app's in mru list to context menu
- for (int i = 0; i < _nItems; i++)
- {
- mii.cbSize = sizeof(MENUITEMINFO);
- mii.fMask = MIIM_ID|MIIM_TYPE|MIIM_DATA;
- mii.wID = _idCmdFirst + i;
- mii.fType = MFT_STRING;
- mii.dwTypeData = _pItems[i].pszFriendly;
- mii.dwItemData = (DWORD_PTR)&_pItems[i];
- InsertMenuItem(hmenu,GetMenuItemCount(hmenu),TRUE,&mii);
- }
- // add seperator
- AppendMenu(hmenu,MF_SEPARATOR,0,NULL);
- // add "&Browse..."
- LoadString(g_hinst, IDS_OPENWITHBROWSE, szMenuText, ARRAYSIZE(szMenuText));
- mii.cbSize = sizeof(MENUITEMINFO);
- mii.fMask = MIIM_ID|MIIM_TYPE|MIIM_DATA;
- mii.wID = _idCmdFirst + _nItems + 1;
- mii.fType = MFT_STRING;
- mii.dwTypeData = szMenuText;
- mii.dwItemData = 0;
- InsertMenuItem(hmenu,GetMenuItemCount(hmenu),TRUE,&mii);
- return TRUE;
- }
- POPENWITHITEM COpenWithMenu::GetItemData(HMENU hmenu, UINT iItem)
- {
- MENUITEMINFO mii;
- mii.cbSize = SIZEOF(MENUITEMINFO);
- mii.fMask = MIIM_DATA | MIIM_STATE;
- mii.cch = 0; // just in case...
- if (GetMenuItemInfo(hmenu, iItem, TRUE, &mii))
- return (POPENWITHITEM)mii.dwItemData;
- return NULL;
- }
- HRESULT COpenWithMenu::SetSite(IUnknown* pUnk)
- {
- ATOMICRELEASE(_pShellView2);
- TraceMsg(TF_OPENWITHMENU, "COpenWithMenu::SetSite = 0x%x", pUnk);
- if(pUnk)
- return pUnk->QueryInterface(IID_IShellView2,(void**)&_pShellView2);
- return NOERROR;
- }
- HRESULT COpenWithMenu::GetSite(REFIID riid,void** ppvObj)
- {
- if(_pShellView2)
- return _pShellView2->QueryInterface(riid,ppvObj);
- else
- {
- ASSERT(ppvObj != NULL);
- *ppvObj = NULL;
- return E_NOINTERFACE;
- }
- }