WINE_DEFAULT_DEBUG_CHANNEL(dmenu);
+
+// FIXME: 260 is correct, but should this be part of the SDK or just MAX_PATH?
+#define MAX_VERB 260
+
+static HRESULT
+SHELL_GetRegCLSID(HKEY hKey, LPCWSTR SubKey, LPCWSTR Value, CLSID &clsid)
+{
+ WCHAR buf[42];
+ DWORD cb = sizeof(buf);
+ DWORD err = RegGetValueW(hKey, SubKey, Value, RRF_RT_REG_SZ, NULL, buf, &cb);
+ return !err ? CLSIDFromString(buf, &clsid) : HRESULT_FROM_WIN32(err);
+}
+
static inline bool RegValueExists(HKEY hKey, LPCWSTR Name)
{
return RegQueryValueExW(hKey, Name, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
class CDefaultContextMenu :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IContextMenu3,
- public IObjectWithSite
+ public IObjectWithSite,
+ public IServiceProvider
{
private:
CComPtr<IUnknown> m_site;
STDMETHOD(SetSite)(IUnknown *pUnkSite) override;
STDMETHOD(GetSite)(REFIID riid, void **ppvSite) override;
+ // IServiceProvider
+ virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID svc, REFIID riid, void**ppv)
+ {
+ return IUnknown_QueryService(m_site, svc, riid, ppv);
+ }
+
BEGIN_COM_MAP(CDefaultContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
+ COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
END_COM_MAP()
};
/* By default use verb for menu item name */
mii.dwTypeData = (LPWSTR)info.Verb.GetString();
- WCHAR wszKey[256];
+ WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
HRESULT hr;
hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
if (FAILED_UNEXPECTEDLY(hr))
return NULL;
}
-// FIXME: 260 is correct, but should this be part of the SDK or just MAX_PATH?
-#define MAX_VERB 260
-
BOOL
CDefaultContextMenu::MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode)
{
CComPtr<IShellBrowser> psb;
HWND hwndTree;
LPCWSTR FlagsName;
- WCHAR wszKey[256];
+ WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
HRESULT hr;
DWORD wFlags;
DWORD cbVerb;
PStaticShellEntry pEntry = &m_StaticEntries.GetAt(it);
+ CRegKey VerbKey;
+ WCHAR VerbKeyPath[sizeof("shell\\") + MAX_VERB];
+ hr = StringCbPrintfW(VerbKeyPath, sizeof(VerbKeyPath), L"shell\\%s", pEntry->Verb.GetString());
+ if (SUCCEEDED(hr) && m_pDataObj &&
+ VerbKey.Open(pEntry->hkClass, VerbKeyPath, KEY_READ) == ERROR_SUCCESS)
+ {
+ CLSID clsid;
+
+ DWORD KeyState = 0;
+ if (lpcmi->fMask & CMIC_MASK_SHIFT_DOWN)
+ KeyState |= MK_SHIFT;
+ if (lpcmi->fMask & CMIC_MASK_CONTROL_DOWN)
+ KeyState |= MK_CONTROL;
+
+ POINTL *pPtl = NULL;
+ C_ASSERT(sizeof(POINT) == sizeof(POINTL));
+ if (lpcmi->fMask & CMIC_MASK_PTINVOKE)
+ pPtl = (POINTL*)&lpcmi->ptInvoke;
+
+ // TODO: IExecuteCommand
+
+ CComPtr<IDropTarget> pDT;
+ hr = SHELL_GetRegCLSID(VerbKey, L"DropTarget", L"CLSID", clsid);
+ if (SUCCEEDED(hr))
+ hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IDropTarget, &pDT));
+ if (SUCCEEDED(hr))
+ {
+ IUnknown_SetSite(pDT, static_cast<IContextMenu*>(this));
+ hr = SHSimulateDrop(pDT, m_pDataObj, KeyState, pPtl, NULL);
+ IUnknown_SetSite(pDT, NULL);
+ return hr;
+ }
+ }
+
/* Get the browse flags to see if we need to browse */
DWORD wFlags = BrowserFlagsFromVerb(lpcmi, pEntry);
{
LocalInvokeInfo.lpVerb -= m_iIdSCMFirst;
Result = InvokeRegVerb(&LocalInvokeInfo);
+ // TODO: if (FAILED(Result) && !(lpcmi->fMask & CMIC_MASK_FLAG_NO_UI)) SHELL_ErrorBox(m_pSite, Result);
return Result;
}