ReactOS 0.4.16-dev-980-g00983aa
CDefaultContextMenu.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: shell32
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/shell32/shv_item_new.c
5 * PURPOSE: provides default context menu implementation
6 * PROGRAMMERS: Johannes Anderwald (johannes.anderwald@reactos.org)
7 */
8
9#include "precomp.h"
10#include <compat_undoc.h>
11
13
14// FIXME: 260 is correct, but should this be part of the SDK or just MAX_PATH?
15#define MAX_VERB 260
16
17static HRESULT
19{
20 WCHAR buf[42];
21 DWORD cb = sizeof(buf);
24}
25
27{
28 MENUITEMINFOW mii;
29 mii.cbSize = FIELD_OFFSET(MENUITEMINFOW, hbmpItem); // USER32 version agnostic
30 mii.fMask = MIIM_TYPE;
31 mii.fType = Flags;
32 return InsertMenuItemW(hMenu, Pos, TRUE, &mii);
33}
34
35typedef struct _DynamicShellEntry_
36{
42
43typedef struct _StaticShellEntry_
44{
48
49#define DCM_FCIDM_SHVIEW_OFFSET 0x7000 // Offset from the menu ids in the menu resource to FCIDM_SHVIEW_*
50
51//
52// verbs for InvokeCommandInfo
53//
54static const struct _StaticInvokeCommandMap_
55{
60{
61 { "RunAs", 0 }, // Unimplemented
62 { "Print", 0 }, // Unimplemented
63 { "Preview", 0 }, // Unimplemented
64 { "Open", FCIDM_SHVIEW_OPEN },
65 { CMDSTR_NEWFOLDERA, FCIDM_SHVIEW_NEWFOLDER, (SHORT)DFM_CMD_NEWFOLDER },
66 { "cut", FCIDM_SHVIEW_CUT, /* ? */ },
73 { "copyto", FCIDM_SHVIEW_COPYTO },
74 { "moveto", FCIDM_SHVIEW_MOVETO },
75};
76
78{
79 for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); ++i)
80 {
81 if (!lstrcmpiA(g_StaticInvokeCmdMap[i].szStringVerb, verba))
82 return (int)g_StaticInvokeCmdMap[i].DfmCmd;
83 }
84 return 0;
85}
86
87static HRESULT
88MapVerbToCmdId(PVOID Verb, BOOL IsUnicode, IContextMenu *pCM, UINT idFirst, UINT idLast)
89{
90 const UINT gcs = IsUnicode ? GCS_VERBW : GCS_VERBA;
91 for (UINT id = idFirst; id <= idLast; ++id)
92 {
95 HRESULT hr = pCM->GetCommandString(id, gcs, NULL, (LPSTR)buf, _countof(buf));
96 if (FAILED(hr) || !*buf)
97 continue;
98 else if (IsUnicode && !_wcsicmp((LPWSTR)Verb, buf))
99 return id;
100 else if (!IsUnicode && !lstrcmpiA((LPSTR)Verb, (LPSTR)buf))
101 return id;
102 }
104}
105
106static inline bool IsVerbListSeparator(WCHAR Ch)
107{
108 return Ch == L' ' || Ch == L','; // learn.microsoft.com/en-us/windows/win32/shell/context-menu-handlers
109}
110
112{
113 for (UINT index = 0; *List; ++index)
114 {
115 while (IsVerbListSeparator(*List))
116 List++;
118 while (*List && !IsVerbListSeparator(*List))
119 List++;
120 // "List > Start" to verify that the list item is non-empty to avoid the edge case where Verb is "" and the list contains ",,"
121 if (!_wcsnicmp(Verb, Start, List - Start) && List > Start)
122 return index;
123 }
124 return -1;
125}
126
128{
129 for (UINT i = 0; *List; ++i)
130 {
131 while (IsVerbListSeparator(*List))
132 List++;
134 while (*List && !IsVerbListSeparator(*List))
135 List++;
136 if (List > Start && i == Index)
138 }
140}
141
143 public CComObjectRootEx<CComMultiThreadModelNoCS>,
144 public IContextMenu3,
145 public IObjectWithSite,
146 public IServiceProvider
147{
148 private:
161 UINT m_iIdSHEFirst; /* first used id */
162 UINT m_iIdSHELast; /* last used id */
164 UINT m_iIdSCMFirst; /* first static used id */
165 UINT m_iIdSCMLast; /* last static used id */
166 UINT m_iIdCBFirst; /* first callback used id */
167 UINT m_iIdCBLast; /* last callback used id */
168 UINT m_iIdDfltFirst; /* first default part id */
169 UINT m_iIdDfltLast; /* last default part id */
170 HWND m_hwnd; /* window passed to callback */
172
175 void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb, UINT uFlags);
177 void TryPickDefault(HMENU hMenu, UINT idCmdFirst, UINT DfltOffset, UINT uFlags);
181 UINT AddShellExtensionsToMenu(HMENU hMenu, UINT* pIndexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
182 UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT* IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags);
199 BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode);
200
201 public:
205
206 // IContextMenu
207 STDMETHOD(QueryContextMenu)(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override;
209 STDMETHOD(GetCommandString)(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override;
210
211 // IContextMenu2
213
214 // IContextMenu3
215 STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) override;
216
217 // IObjectWithSite
218 STDMETHOD(SetSite)(IUnknown *pUnkSite) override;
219 STDMETHOD(GetSite)(REFIID riid, void **ppvSite) override;
220
221 // IServiceProvider
223 {
224 return IUnknown_QueryService(m_site, svc, riid, ppv);
225 }
226
228 COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
229 COM_INTERFACE_ENTRY_IID(IID_IContextMenu2, IContextMenu2)
230 COM_INTERFACE_ENTRY_IID(IID_IContextMenu3, IContextMenu3)
232 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
234};
235
237 m_psf(NULL),
238 m_pmcb(NULL),
239 m_pfnmcb(NULL),
240 m_cidl(0),
241 m_apidl(NULL),
242 m_pDataObj(NULL),
243 m_aKeys(NULL),
244 m_cKeys(NULL),
245 m_pidlFolder(NULL),
246 m_bGroupPolicyActive(0),
247 m_iIdSHEFirst(0),
248 m_iIdSHELast(0),
249 m_iIdSCMFirst(0),
250 m_iIdSCMLast(0),
251 m_iIdCBFirst(0),
252 m_iIdCBLast(0),
253 m_iIdDfltFirst(0),
254 m_iIdDfltLast(0),
255 m_hwnd(NULL)
256{
258}
259
261{
262 for (POSITION it = m_DynamicEntries.GetHeadPosition(); it != NULL;)
263 {
264 const DynamicShellEntry& info = m_DynamicEntries.GetNext(it);
265 IUnknown_SetSite(info.pCM.p, NULL);
266 }
267 m_DynamicEntries.RemoveAll();
268 m_StaticEntries.RemoveAll();
269
270 for (UINT i = 0; i < m_cKeys; i++)
273
274 if (m_pidlFolder)
276 _ILFreeaPidl(const_cast<PITEMID_CHILD *>(m_apidl), m_cidl);
277}
278
280{
281 TRACE("cidl %u\n", pdcm->cidl);
282
283 if (!pdcm->pcmcb && !lpfn)
284 {
285 ERR("CDefaultContextMenu needs a callback!\n");
286 return E_INVALIDARG;
287 }
288
289 m_cidl = pdcm->cidl;
291 if (m_cidl && !m_apidl)
292 return E_OUTOFMEMORY;
293 m_psf = pdcm->psf;
294 m_pmcb = pdcm->pcmcb;
295 m_pfnmcb = lpfn;
296 m_hwnd = pdcm->hwnd;
297
298 m_cKeys = pdcm->cKeys;
299 if (pdcm->cKeys)
300 {
301 m_aKeys = (HKEY*)HeapAlloc(GetProcessHeap(), 0, sizeof(HKEY) * pdcm->cKeys);
302 if (!m_aKeys)
303 return E_OUTOFMEMORY;
304 memcpy(m_aKeys, pdcm->aKeys, sizeof(HKEY) * pdcm->cKeys);
305 }
306
307 m_psf->GetUIObjectOf(pdcm->hwnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &m_pDataObj));
308
309 if (pdcm->pidlFolder)
310 {
312 }
313 else
314 {
316 if (SUCCEEDED(m_psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &pf))))
317 {
318 if (FAILED(pf->GetCurFolder(&m_pidlFolder)))
319 ERR("GetCurFolder failed\n");
320 }
321 TRACE("pidlFolder %p\n", m_pidlFolder);
322 }
323
324 return S_OK;
325}
326
328{
329 if (m_pmcb)
330 {
331 return m_pmcb->CallBack(m_psf, m_hwnd, m_pDataObj, uMsg, wParam, (LPARAM)lParam);
332 }
333 else if(m_pfnmcb)
334 {
336 }
337
338 return E_FAIL;
339}
340
341void CDefaultContextMenu::AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb, UINT uFlags)
342{
343 POSITION it = m_StaticEntries.GetHeadPosition();
344 while (it != NULL)
345 {
346 const StaticShellEntry& info = m_StaticEntries.GetNext(it);
347 if (info.Verb.CompareNoCase(szVerb) == 0)
348 {
349 /* entry already exists */
350 return;
351 }
352 }
353
354 TRACE("adding verb %s\n", debugstr_w(szVerb));
355
356 if (!_wcsicmp(szVerb, L"open") && !(uFlags & CMF_NODEFAULT))
357 {
358 /* open verb is always inserted in front */
359 m_StaticEntries.AddHead({ szVerb, hkeyClass });
360 }
361 else
362 {
363 m_StaticEntries.AddTail({ szVerb, hkeyClass });
364 }
365}
366
368{
369 WCHAR wszName[VERBKEY_CCHMAX];
370 DWORD cchName, dwIndex = 0;
371 HKEY hShellKey;
372
373 LRESULT lres = RegOpenKeyExW(hKey, L"shell", 0, KEY_READ, &hShellKey);
374 if (lres != STATUS_SUCCESS)
375 return;
376
377 if (!*m_DefVerbs)
378 {
379 DWORD cb = sizeof(m_DefVerbs);
381 }
382
383 while(TRUE)
384 {
385 cchName = _countof(wszName);
386 if (RegEnumKeyExW(hShellKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
387 break;
388
389 AddStaticEntry(hKey, wszName, uFlags);
390 }
391
392 RegCloseKey(hShellKey);
393}
394
395static
396BOOL
398{
399 BOOL bRet = FALSE;
400 CComPtr<IDataObject> pDataObj;
401
402 if (SUCCEEDED(OleGetClipboard(&pDataObj)))
403 {
404 FORMATETC formatetc;
405
406 TRACE("pDataObj=%p\n", pDataObj.p);
407
408 /* Set the FORMATETC structure*/
409 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
410 bRet = SUCCEEDED(pDataObj->QueryGetData(&formatetc));
411 }
412
413 return bRet;
414}
415
416BOOL
418{
419 POSITION it = m_DynamicEntries.GetHeadPosition();
420 while (it != NULL)
421 {
422 const DynamicShellEntry& info = m_DynamicEntries.GetNext(it);
423 if (info.ClassID == clsid)
424 return TRUE;
425 }
426
427 return FALSE;
428}
429
432{
433 HRESULT hr;
434 TRACE("LoadDynamicContextMenuHandler entered with This %p hKey %p pclsid %s\n", this, hKey, wine_dbgstr_guid(&clsid));
435
437 return S_OK;
438
441 if (FAILED(hr))
442 {
443 ERR("SHCoCreateInstance(IContextMenu) failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(&clsid), hr);
444 return hr;
445 }
446
447 CComPtr<IShellExtInit> pExtInit;
448 hr = pcm->QueryInterface(IID_PPV_ARG(IShellExtInit, &pExtInit));
449 if (FAILED(hr))
450 {
451 ERR("IContextMenu->QueryInterface(IShellExtInit) failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(&clsid), hr);
452 return hr;
453 }
454
455 hr = pExtInit->Initialize(m_pDataObj ? NULL : m_pidlFolder, m_pDataObj, hKey);
456 if (FAILED(hr))
457 {
458 WARN("IShellExtInit::Initialize failed.clsid %s hr 0x%x\n", wine_dbgstr_guid(&clsid), hr);
459 return hr;
460 }
461
462 if (m_site)
464
465 m_DynamicEntries.AddTail({ 0, 0, clsid, pcm });
466
467 return S_OK;
468}
469
470BOOL
472{
473 WCHAR wszName[MAX_PATH], wszBuf[MAX_PATH], *pwszClsid;
475 HRESULT hr;
476 HKEY hKey;
477
478 if (RegOpenKeyExW(hRootKey, L"shellex\\ContextMenuHandlers", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
479 {
480 TRACE("RegOpenKeyExW failed\n");
481 return FALSE;
482 }
483
484 DWORD dwIndex = 0;
485 while (TRUE)
486 {
487 cchName = _countof(wszName);
488 if (RegEnumKeyExW(hKey, dwIndex++, wszName, &cchName, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
489 break;
490
491 /* Key name or key value is CLSID */
492 CLSID clsid;
493 hr = CLSIDFromString(wszName, &clsid);
494 if (hr == S_OK)
495 pwszClsid = wszName;
496 else
497 {
498 DWORD cchBuf = _countof(wszBuf);
499 if (RegGetValueW(hKey, wszName, NULL, RRF_RT_REG_SZ, NULL, wszBuf, &cchBuf) == ERROR_SUCCESS)
500 hr = CLSIDFromString(wszBuf, &clsid);
501 pwszClsid = wszBuf;
502 }
503
504 if (FAILED(hr))
505 {
506 ERR("CLSIDFromString failed for clsid %S hr 0x%x\n", pwszClsid, hr);
507 continue;
508 }
509
511 {
513 L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
514 pwszClsid,
516 NULL,
517 NULL,
519 {
520 ERR("Shell extension %s not approved!\n", pwszClsid);
521 continue;
522 }
523 }
524
526 if (FAILED(hr))
527 WARN("Failed to get context menu entires from shell extension! clsid: %S\n", pwszClsid);
528 }
529
531 return TRUE;
532}
533
534UINT
536{
537 UINT cIds = 0;
538
539 if (m_DynamicEntries.IsEmpty())
540 return cIds;
541
542 POSITION it = m_DynamicEntries.GetHeadPosition();
543 while (it != NULL)
544 {
546
547 HRESULT hr = info.pCM->QueryContextMenu(hMenu, *pIndexMenu, idCmdFirst + cIds, idCmdLast, uFlags);
548 if (SUCCEEDED(hr))
549 {
550 info.iIdCmdFirst = cIds;
551 info.NumIds = HRESULT_CODE(hr);
552 (*pIndexMenu) += info.NumIds;
553
554 cIds += info.NumIds;
555 if (idCmdFirst + cIds >= idCmdLast)
556 break;
557 }
558 TRACE("pEntry hr %x contextmenu %p cmdfirst %x num ids %x\n", hr, info.pCM.p, info.iIdCmdFirst, info.NumIds);
559 }
560 return cIds;
561}
562
563UINT
565 HMENU hMenu,
566 UINT* pIndexMenu,
567 UINT iIdCmdFirst,
568 UINT iIdCmdLast,
569 UINT uFlags)
570{
572 MENUITEMINFOW mii = { sizeof(mii) };
573 UINT idResource;
574 WCHAR wszDispVerb[80]; // The limit on XP. If the friendly string is longer, it falls back to the verb key.
575 UINT fState;
576 UINT cIds = 0, indexFirst = *pIndexMenu, indexDefault;
577 int iDefVerbIndex = -1;
578
580 mii.fType = MFT_STRING;
581
582 POSITION it = m_StaticEntries.GetHeadPosition();
583 bool first = true;
584 while (it != NULL)
585 {
587 BOOL forceFirstPos = FALSE;
588
589 fState = MFS_ENABLED;
590
591 /* set first entry as default */
592 if (first)
593 {
594 fState |= MFS_DEFAULT;
595 first = false;
596 }
597
598 if (info.Verb.CompareNoCase(L"open") == 0)
599 {
600 idResource = IDS_OPEN_VERB;
601 fState |= MFS_DEFAULT; /* override default when open verb is found */
602 forceFirstPos++;
603 }
604 else if (info.Verb.CompareNoCase(L"explore") == 0)
605 {
606 idResource = IDS_EXPLORE_VERB;
607 if (uFlags & CMF_EXPLORE)
608 {
609 fState |= MFS_DEFAULT;
610 forceFirstPos++;
611 }
612 }
613 else if (info.Verb.CompareNoCase(L"runas") == 0)
614 idResource = IDS_RUNAS_VERB;
615 else if (info.Verb.CompareNoCase(L"edit") == 0)
616 idResource = IDS_EDIT_VERB;
617 else if (info.Verb.CompareNoCase(L"find") == 0)
618 idResource = IDS_FIND_VERB;
619 else if (info.Verb.CompareNoCase(L"print") == 0)
620 idResource = IDS_PRINT_VERB;
621 else if (info.Verb.CompareNoCase(L"printto") == 0)
622 continue;
623 else
624 idResource = 0;
625
626 /* By default use verb for menu item name */
627 mii.dwTypeData = (LPWSTR)info.Verb.GetString();
628
629 WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
630 HRESULT hr;
631 hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", info.Verb.GetString());
633 {
634 continue;
635 }
636
637 UINT cmdFlags = 0;
638 bool hide = false;
639 HKEY hkVerb;
640 if (idResource > 0)
641 {
642 if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
643 {
644 if (LoadStringW(shell32_hInstance, idResource, wszDispVerb, _countof(wszDispVerb)))
645 mii.dwTypeData = wszDispVerb; /* use translated verb */
646 else
647 ERR("Failed to load string\n");
648 }
649
650 if (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) != ERROR_SUCCESS)
651 hkVerb = NULL;
652 }
653 else
654 {
655 if (RegOpenKeyW(info.hkClass, wszKey, &hkVerb) == ERROR_SUCCESS)
656 {
657 if (!(uFlags & CMF_OPTIMIZEFORINVOKE))
658 {
659 DWORD cbVerb = sizeof(wszDispVerb);
660 LONG res = RegLoadMUIStringW(hkVerb, L"MUIVerb", wszDispVerb, cbVerb, NULL, 0, NULL);
661 if (res || !*wszDispVerb)
662 res = RegLoadMUIStringW(hkVerb, NULL, wszDispVerb, cbVerb, NULL, 0, NULL);
663
664 if (res == ERROR_SUCCESS && *wszDispVerb)
665 {
666 /* use description for the menu entry */
667 mii.dwTypeData = wszDispVerb;
668 }
669 }
670 }
671 else
672 {
673 hkVerb = NULL;
674 }
675 }
676
677 if (hkVerb)
678 {
679 if (!(uFlags & CMF_EXTENDEDVERBS))
680 hide = RegValueExists(hkVerb, L"Extended");
681
682 if (!hide)
683 hide = RegValueExists(hkVerb, L"ProgrammaticAccessOnly");
684
685 if (!hide && !(uFlags & CMF_DISABLEDVERBS))
686 hide = RegValueExists(hkVerb, L"LegacyDisable");
687
688 if (RegValueExists(hkVerb, L"NeverDefault"))
689 fState &= ~MFS_DEFAULT;
690
691 if (RegValueExists(hkVerb, L"SeparatorBefore"))
692 cmdFlags |= ECF_SEPARATORBEFORE;
693 if (RegValueExists(hkVerb, L"SeparatorAfter"))
694 cmdFlags |= ECF_SEPARATORAFTER;
695
696 RegCloseKey(hkVerb);
697 }
698
699 if (((uFlags & CMF_NODEFAULT) && ntver >= _WIN32_WINNT_VISTA) ||
700 ((uFlags & CMF_DONOTPICKDEFAULT) && ntver >= _WIN32_WINNT_WIN7))
701 {
702 fState &= ~MFS_DEFAULT;
703 }
704
705 if (!hide)
706 {
707 if (cmdFlags & ECF_SEPARATORBEFORE)
708 {
709 if (InsertMenuItemAt(hMenu, *pIndexMenu, MF_SEPARATOR))
710 (*pIndexMenu)++;
711 }
712
713 UINT pos = *pIndexMenu;
714 int verbIndex = hkVerb ? FindVerbInDefaultVerbList(m_DefVerbs, info.Verb) : -1;
715 if (verbIndex >= 0)
716 {
717 if (verbIndex < iDefVerbIndex || iDefVerbIndex < 0)
718 {
719 iDefVerbIndex = verbIndex;
720 fState |= MFS_DEFAULT;
721 forceFirstPos = TRUE;
722 }
723 else
724 {
725 fState &= ~MFS_DEFAULT; // We have already set a better default
726 pos = indexDefault;
727 }
728 }
729 else if (iDefVerbIndex >= 0)
730 {
731 fState &= ~MFS_DEFAULT; // We have already set the default
732 if (forceFirstPos)
733 pos = indexDefault;
734 forceFirstPos = FALSE;
735 }
736
737 mii.fState = fState;
738 mii.wID = iIdCmdFirst + cIds;
739 if (InsertMenuItemW(hMenu, forceFirstPos ? indexFirst : pos, TRUE, &mii))
740 (*pIndexMenu)++;
741
742 if (cmdFlags & ECF_SEPARATORAFTER)
743 {
744 if (InsertMenuItemAt(hMenu, *pIndexMenu, MF_SEPARATOR))
745 (*pIndexMenu)++;
746 }
747
748 if (fState & MFS_DEFAULT)
749 indexDefault = *pIndexMenu; // This is where we want to insert "high priority" verbs
750 }
751 cIds++; // Always increment the id because it acts as the index into m_StaticEntries
752
753 if (mii.wID >= iIdCmdLast)
754 break;
755 }
756
757 return cIds;
758}
759
761 HMENU hMenu,
762 UINT indexMenu,
763 BOOL fByPosition,
764 UINT wID,
765 UINT fType,
766 LPCWSTR dwTypeData,
767 UINT fState)
768{
769 MENUITEMINFOW mii;
770 WCHAR wszText[100];
771
772 ZeroMemory(&mii, sizeof(mii));
773 mii.cbSize = sizeof(mii);
774 if (fType == MFT_SEPARATOR)
775 mii.fMask = MIIM_ID | MIIM_TYPE;
776 else if (fType == MFT_STRING)
777 {
779 if (IS_INTRESOURCE(dwTypeData))
780 {
781 if (LoadStringW(shell32_hInstance, LOWORD((ULONG_PTR)dwTypeData), wszText, _countof(wszText)))
782 mii.dwTypeData = wszText;
783 else
784 {
785 ERR("failed to load string %p\n", dwTypeData);
786 return FALSE;
787 }
788 }
789 else
790 mii.dwTypeData = (LPWSTR)dwTypeData;
791 mii.fState = fState;
792 }
793
794 mii.wID = wID;
795 mii.fType = fType;
796 return InsertMenuItemW(hMenu, indexMenu, fByPosition, &mii);
797}
798
799void
801{
802 // Are we allowed to pick a default?
803 if ((uFlags & CMF_NODEFAULT) ||
804 ((uFlags & CMF_DONOTPICKDEFAULT) && RosGetProcessEffectiveVersion() >= _WIN32_WINNT_WIN7))
805 {
806 return;
807 }
808
809 // Do we already have a default?
810 if ((int)GetMenuDefaultItem(hMenu, MF_BYPOSITION, 0) != -1)
811 return;
812
813 // Does the view want to pick one?
814 INT_PTR forceDfm = 0;
815 if (SUCCEEDED(_DoCallback(DFM_GETDEFSTATICID, 0, &forceDfm)) && forceDfm)
816 {
817 for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); ++i)
818 {
819 UINT menuItemId = g_StaticInvokeCmdMap[i].IntVerb + DfltOffset - DCM_FCIDM_SHVIEW_OFFSET;
820 if (g_StaticInvokeCmdMap[i].DfmCmd == forceDfm &&
821 SetMenuDefaultItem(hMenu, menuItemId, MF_BYCOMMAND))
822 {
823 return;
824 }
825 }
826 }
827
828 // Don't want to pick something like cut or delete as the default but
829 // a static or dynamic verb is a good default.
831 SetMenuDefaultItem(hMenu, idCmdFirst, MF_BYCOMMAND);
832}
833
835WINAPI
837 HMENU hMenu,
838 UINT IndexMenu,
839 UINT idCmdFirst,
840 UINT idCmdLast,
841 UINT uFlags)
842{
843 HRESULT hr;
844 UINT idCmdNext = idCmdFirst;
845 UINT cIds = 0;
846
847 TRACE("BuildShellItemContextMenu entered\n");
848
849 /* Load static verbs and shell extensions from registry */
850 for (UINT i = 0; i < m_cKeys && !(uFlags & CMF_NOVERBS); i++)
851 {
854 }
855
856 /* Add static context menu handlers */
857 cIds = AddStaticContextMenusToMenu(hMenu, &IndexMenu, idCmdFirst, idCmdLast, uFlags);
858 m_iIdSCMFirst = 0; // FIXME: This should be = idCmdFirst?
859 m_iIdSCMLast = cIds;
860 idCmdNext = idCmdFirst + cIds;
861
862 /* Add dynamic context menu handlers */
863 cIds += AddShellExtensionsToMenu(hMenu, &IndexMenu, idCmdNext, idCmdLast, uFlags);
865 m_iIdSHELast = cIds;
866 idCmdNext = idCmdFirst + cIds;
867 TRACE("SH_LoadContextMenuHandlers first %x last %x\n", m_iIdSHEFirst, m_iIdSHELast);
868
869 /* Now let the callback add its own items */
870 QCMINFO qcminfo = {hMenu, IndexMenu, idCmdNext, idCmdLast, NULL};
872 {
873 UINT added = qcminfo.idCmdFirst - idCmdNext;
874 cIds += added;
875 IndexMenu += added;
877 m_iIdCBLast = cIds;
878 idCmdNext = idCmdFirst + cIds;
879 }
880
881 //TODO: DFM_MERGECONTEXTMENU_BOTTOM
882
883 UINT idDefaultOffset = 0;
884 BOOL isBackgroundMenu = !m_cidl;
885 if (!(uFlags & CMF_VERBSONLY) && !isBackgroundMenu)
886 {
887 /* Get the attributes of the items */
888 SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER;
889 hr = m_psf->GetAttributesOf(m_cidl, m_apidl, &rfg);
891 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
892
893 /* Add the default part of the menu */
894 HMENU hmenuDefault = LoadMenuW(_AtlBaseModule.GetResourceInstance(), L"MENU_SHV_FILE");
895
896 /* Remove uneeded entries */
897 if (!(rfg & SFGAO_CANMOVE))
898 DeleteMenu(hmenuDefault, IDM_CUT, MF_BYCOMMAND);
899 if (!(rfg & SFGAO_CANCOPY))
900 DeleteMenu(hmenuDefault, IDM_COPY, MF_BYCOMMAND);
901 if (!((rfg & SFGAO_FILESYSTEM) && HasClipboardData()))
902 DeleteMenu(hmenuDefault, IDM_INSERT, MF_BYCOMMAND);
903 if (!(rfg & SFGAO_CANLINK))
904 DeleteMenu(hmenuDefault, IDM_CREATELINK, MF_BYCOMMAND);
905 if (!(rfg & SFGAO_CANDELETE))
906 DeleteMenu(hmenuDefault, IDM_DELETE, MF_BYCOMMAND);
907 if (!(rfg & SFGAO_CANRENAME) || !(uFlags & CMF_CANRENAME))
908 DeleteMenu(hmenuDefault, IDM_RENAME, MF_BYCOMMAND);
909 if (!(rfg & SFGAO_HASPROPSHEET))
910 DeleteMenu(hmenuDefault, IDM_PROPERTIES, MF_BYCOMMAND);
911
912 idDefaultOffset = idCmdNext;
913 UINT idMax = Shell_MergeMenus(hMenu, GetSubMenu(hmenuDefault, 0), IndexMenu, idCmdNext, idCmdLast, 0);
914 m_iIdDfltFirst = cIds;
915 cIds += idMax - idCmdNext;
916 m_iIdDfltLast = cIds;
917
918 DestroyMenu(hmenuDefault);
919 }
920
921 TryPickDefault(hMenu, idCmdFirst, idDefaultOffset, uFlags);
922
923 // TODO: DFM_MERGECONTEXTMENU_TOP
924
925 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, cIds);
926}
927
929{
930 HRESULT hr;
931
933 hr = OleGetClipboard(&pda);
935 return hr;
936
937 FORMATETC formatetc2;
938 STGMEDIUM medium2;
940
941 DWORD dwKey= 0;
942
943 if (SUCCEEDED(pda->GetData(&formatetc2, &medium2)))
944 {
945 DWORD * pdwFlag = (DWORD*)GlobalLock(medium2.hGlobal);
946 if (pdwFlag)
947 {
948 if (*pdwFlag == DROPEFFECT_COPY)
949 dwKey = MK_CONTROL;
950 else
951 dwKey = MK_SHIFT;
952 }
953 else
954 {
955 ERR("No drop effect obtained\n");
956 }
957 GlobalUnlock(medium2.hGlobal);
958 }
959
960 if (bLink)
961 {
962 dwKey = MK_CONTROL|MK_SHIFT;
963 }
964
966 if (m_cidl)
967 hr = m_psf->GetUIObjectOf(NULL, 1, &m_apidl[0], IID_NULL_PPV_ARG(IDropTarget, &pdrop));
968 else
969 hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pdrop));
970
972 return hr;
973
974 SHSimulateDrop(pdrop, pda, dwKey, NULL, NULL);
975
976 TRACE("CP result %x\n", hr);
977 return S_OK;
978}
979
982{
984 return E_FAIL;
985}
986
988{
989 if (!m_cidl || !m_pDataObj)
990 return E_FAIL;
991
993 HRESULT hr = m_psf->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget, &pDT));
995 return hr;
996
998
999 return S_OK;
1000}
1001
1003{
1004 if (!m_cidl || !m_pDataObj)
1005 return E_FAIL;
1006
1010 return hr;
1011
1012 DWORD grfKeyState = (lpcmi->fMask & CMIC_MASK_SHIFT_DOWN) ? MK_SHIFT : 0;
1013 SHSimulateDrop(pDT, m_pDataObj, grfKeyState, NULL, NULL);
1014
1015 return S_OK;
1016}
1017
1019{
1020 if (!m_cidl || !m_pDataObj)
1021 return E_FAIL;
1022
1023 FORMATETC formatetc;
1025 STGMEDIUM medium = {0};
1026 medium.tymed = TYMED_HGLOBAL;
1027 medium.hGlobal = GlobalAlloc(GHND, sizeof(DWORD));
1028 DWORD* pdwFlag = (DWORD*)GlobalLock(medium.hGlobal);
1029 if (pdwFlag)
1030 *pdwFlag = bCopy ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
1031 GlobalUnlock(medium.hGlobal);
1032 m_pDataObj->SetData(&formatetc, &medium, TRUE);
1033
1035 if (SUCCEEDED(IUnknown_QueryService(m_site, SID_SFolderView, IID_PPV_ARG(IShellFolderView, &psfv))))
1036 psfv->SetPoints(m_pDataObj);
1037
1040 return hr;
1041
1042 if (psfv)
1043 psfv->SetClipboard(!bCopy);
1044 return S_OK;
1045}
1046
1048{
1050 HRESULT hr;
1051
1052 if (!m_site || !m_cidl)
1053 return E_FAIL;
1054
1055 /* Get a pointer to the shell browser */
1058 return hr;
1059
1061 hr = psb->QueryActiveShellView(&lpSV);
1063 return hr;
1064
1065 SVSIF selFlags = SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT;
1066 hr = lpSV->SelectItem(m_apidl[0], selFlags);
1068 return hr;
1069
1070 return S_OK;
1071}
1072
1073HRESULT
1076{
1078
1079 // We are asked to run the default property sheet
1080 if (hr == S_FALSE)
1081 {
1083 }
1084
1085 return hr;
1086}
1087
1088HRESULT
1090{
1091 ERR("TODO: Undo\n");
1092 return E_NOTIMPL;
1093}
1094
1095HRESULT
1097{
1098 HRESULT hr = E_FAIL;
1099 if (!m_pDataObj)
1100 {
1101 ERR("m_pDataObj is NULL\n");
1102 return hr;
1103 }
1104
1105 CComPtr<IContextMenu> pContextMenu;
1106 if (bCopy)
1107 hr = SHCoCreateInstance(NULL, &CLSID_CopyToMenu, NULL,
1108 IID_PPV_ARG(IContextMenu, &pContextMenu));
1109 else
1110 hr = SHCoCreateInstance(NULL, &CLSID_MoveToMenu, NULL,
1111 IID_PPV_ARG(IContextMenu, &pContextMenu));
1113 return hr;
1114
1116 hr = pContextMenu->QueryInterface(IID_PPV_ARG(IShellExtInit, &pInit));
1118 return hr;
1119
1120 hr = pInit->Initialize(m_pidlFolder, m_pDataObj, NULL);
1122 return hr;
1123
1124 if (bCopy)
1125 lpici->lpVerb = "copyto";
1126 else
1127 lpici->lpVerb = "moveto";
1128
1129 return pContextMenu->InvokeCommand((LPCMINVOKECOMMANDINFO)lpici);
1130}
1131
1132// This code is taken from CNewMenu and should be shared between the 2 classes
1133HRESULT
1136{
1137 WCHAR wszPath[MAX_PATH];
1138 WCHAR wszName[MAX_PATH];
1139 WCHAR wszNewFolder[25];
1140 HRESULT hr;
1141
1142 /* Get folder path */
1145 return hr;
1146
1147 if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, _countof(wszNewFolder)))
1148 return E_FAIL;
1149
1150 /* Create the name of the new directory */
1151 if (!PathYetAnotherMakeUniqueName(wszName, wszPath, NULL, wszNewFolder))
1152 return E_FAIL;
1153
1154 /* Create the new directory and show the appropriate dialog in case of error */
1155 if (SHCreateDirectory(lpici->hwnd, wszName) != ERROR_SUCCESS)
1156 return E_FAIL;
1157
1158 /* Show and select the new item in the def view */
1159 LPITEMIDLIST pidl;
1160 PITEMID_CHILD pidlNewItem;
1162
1163 /* Notify the view object about the new item */
1165
1166 if (!m_site)
1167 return S_OK;
1168
1169 /* Get a pointer to the shell view */
1170 hr = IUnknown_QueryService(m_site, SID_SFolderView, IID_PPV_ARG(IShellView, &psv));
1172 return S_OK;
1173
1174 /* Attempt to get the pidl of the new item */
1175 hr = SHILCreateFromPathW(wszName, &pidl, NULL);
1177 return hr;
1178
1179 pidlNewItem = ILFindLastID(pidl);
1180
1181 hr = psv->SelectItem(pidlNewItem, SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE |
1182 SVSI_FOCUSED | SVSI_SELECT);
1184 return hr;
1185
1186 SHFree(pidl);
1187
1188 return S_OK;
1189}
1190
1192{
1193 POSITION it = m_DynamicEntries.GetHeadPosition();
1194 while (it != NULL)
1195 {
1197
1198 if (idCmd >= info.iIdCmdFirst + info.NumIds)
1199 continue;
1200
1201 if (idCmd < info.iIdCmdFirst || idCmd > info.iIdCmdFirst + info.NumIds)
1202 return NULL;
1203
1204 return &info;
1205 }
1206
1207 return NULL;
1208}
1209
1210BOOL
1212{
1213 WCHAR UnicodeStr[MAX_VERB];
1214
1215 /* Loop through all the static verbs looking for a match */
1216 for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++)
1217 {
1218 /* We can match both ANSI and unicode strings */
1219 if (IsUnicode)
1220 {
1221 /* The static verbs are ANSI, get a unicode version before doing the compare */
1222 SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, UnicodeStr, MAX_VERB);
1223 if (!_wcsicmp(UnicodeStr, (LPWSTR)Verb))
1224 {
1225 /* Return the Corresponding Id */
1226 *idCmd = g_StaticInvokeCmdMap[i].IntVerb;
1227 return TRUE;
1228 }
1229 }
1230 else
1231 {
1232 if (!_stricmp(g_StaticInvokeCmdMap[i].szStringVerb, (LPSTR)Verb))
1233 {
1234 *idCmd = g_StaticInvokeCmdMap[i].IntVerb;
1235 return TRUE;
1236 }
1237 }
1238 }
1239
1240 for (POSITION it = m_DynamicEntries.GetHeadPosition(); it != NULL;)
1241 {
1243 if (!entry.NumIds)
1244 continue;
1245 HRESULT hr = ::MapVerbToCmdId(Verb, IsUnicode, entry.pCM, 0, entry.NumIds - 1);
1246 if (SUCCEEDED(hr))
1247 {
1248 *idCmd = m_iIdSHEFirst + entry.iIdCmdFirst + hr;
1249 return TRUE;
1250 }
1251 }
1252 return FALSE;
1253}
1254
1255HRESULT
1258{
1259 TRACE("verb %p first %x last %x\n", lpcmi->lpVerb, m_iIdSHEFirst, m_iIdSHELast);
1260
1261 UINT idCmd = LOWORD(lpcmi->lpVerb);
1263 if (!pEntry)
1264 return E_FAIL;
1265
1266 /* invoke the dynamic context menu */
1267 lpcmi->lpVerb = MAKEINTRESOURCEA(idCmd - pEntry->iIdCmdFirst);
1268 return pEntry->pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)lpcmi);
1269}
1270
1271DWORD
1273{
1275 HWND hwndTree;
1276 LPCWSTR FlagsName;
1277 WCHAR wszKey[sizeof("shell\\") + MAX_VERB];
1278 HRESULT hr;
1279 DWORD wFlags;
1280 DWORD cbVerb;
1281
1282 if (!m_site)
1283 return 0;
1284
1285 /* Get a pointer to the shell browser */
1287 if (FAILED(hr))
1288 return 0;
1289
1290 /* See if we are in Explore or Browse mode. If the browser's tree is present, we are in Explore mode.*/
1291 if (SUCCEEDED(psb->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
1292 FlagsName = L"ExplorerFlags";
1293 else
1294 FlagsName = L"BrowserFlags";
1295
1297 if (SUCCEEDED(psb->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &pcdb))))
1298 {
1299 if (LOBYTE(GetVersion()) < 6 || FlagsName[0] == 'E')
1300 return 0; // Don't browse in-place
1301 }
1302
1303 /* Try to get the flag from the verb */
1304 hr = StringCbPrintfW(wszKey, sizeof(wszKey), L"shell\\%s", pEntry->Verb.GetString());
1306 return 0;
1307
1308 cbVerb = sizeof(wFlags);
1309 if (RegGetValueW(pEntry->hkClass, wszKey, FlagsName, RRF_RT_REG_DWORD, NULL, &wFlags, &cbVerb) == ERROR_SUCCESS)
1310 {
1311 return wFlags;
1312 }
1313
1314 return 0;
1315}
1316
1317HRESULT
1320{
1322 HRESULT hr;
1323
1324 if (!m_site)
1325 return E_FAIL;
1326
1327 /* Get a pointer to the shell browser */
1329 if (FAILED(hr))
1330 return hr;
1331
1332 PIDLIST_ABSOLUTE pidl;
1333 hr = SHILCombine(m_pidlFolder, pidlChild, &pidl);
1335 return hr;
1336
1337 hr = psb->BrowseObject(pidl, wFlags & ~SBSP_RELATIVE);
1338 ILFree(pidl);
1339 return hr;
1340}
1341
1342HRESULT
1344{
1345 const BOOL unicode = IsUnicode(*lpcmi);
1346
1347 LPITEMIDLIST pidlFull = ILCombine(m_pidlFolder, pidl);
1348 if (pidlFull == NULL)
1349 {
1350 return E_FAIL;
1351 }
1352
1353 WCHAR wszPath[MAX_PATH];
1354 BOOL bHasPath = SHGetPathFromIDListW(pidlFull, wszPath);
1355
1356 WCHAR wszDir[MAX_PATH];
1357
1358 SHELLEXECUTEINFOW sei = { sizeof(sei) };
1359 sei.fMask = SEE_MASK_CLASSKEY | SEE_MASK_IDLIST | (CmicFlagsToSeeFlags(lpcmi->fMask) & ~SEE_MASK_INVOKEIDLIST);
1360 sei.hwnd = lpcmi->hwnd;
1361 sei.nShow = lpcmi->nShow;
1362 sei.lpVerb = pEntry->Verb;
1363 sei.lpIDList = pidlFull;
1364 sei.hkeyClass = pEntry->hkClass;
1365 sei.dwHotKey = lpcmi->dwHotKey;
1366 sei.hIcon = lpcmi->hIcon;
1367 sei.lpDirectory = wszDir;
1368
1369 if (unicode && !StrIsNullOrEmpty(lpcmi->lpDirectoryW))
1370 {
1371 sei.lpDirectory = lpcmi->lpDirectoryW;
1372 }
1373 else if (bHasPath)
1374 {
1375 wcscpy(wszDir, wszPath);
1376 PathRemoveFileSpec(wszDir);
1377 }
1378 else
1379 {
1380 if (!SHGetPathFromIDListW(m_pidlFolder, wszDir))
1381 *wszDir = UNICODE_NULL;
1382 }
1383
1384 if (bHasPath)
1385 sei.lpFile = wszPath;
1386
1387 CComHeapPtr<WCHAR> pszParamsW;
1388 if (unicode && !StrIsNullOrEmpty(lpcmi->lpParametersW))
1389 sei.lpParameters = lpcmi->lpParametersW;
1390 else if (!StrIsNullOrEmpty(lpcmi->lpParameters) && __SHCloneStrAtoW(&pszParamsW, lpcmi->lpParameters))
1391 sei.lpParameters = pszParamsW;
1392
1393 if (!sei.lpClass && (lpcmi->fMask & (CMIC_MASK_HASLINKNAME | CMIC_MASK_HASTITLE)) && unicode)
1394 sei.lpClass = lpcmi->lpTitleW; // Forward .lnk path from CShellLink::DoOpen (for consrv STARTF_TITLEISLINKNAME)
1395
1396 ShellExecuteExW(&sei);
1397 ILFree(pidlFull);
1398
1399 return S_OK;
1400}
1401
1402HRESULT
1405{
1406 INT iCmd = LOWORD(lpcmi->lpVerb);
1407 HRESULT hr;
1408 UINT i;
1409
1410 POSITION it = m_StaticEntries.FindIndex(iCmd);
1411
1412 if (it == NULL)
1413 return E_INVALIDARG;
1414
1416
1417 CRegKey VerbKey;
1418 WCHAR VerbKeyPath[sizeof("shell\\") + MAX_VERB];
1419 hr = StringCbPrintfW(VerbKeyPath, sizeof(VerbKeyPath), L"shell\\%s", pEntry->Verb.GetString());
1420 if (SUCCEEDED(hr) && m_pDataObj &&
1421 VerbKey.Open(pEntry->hkClass, VerbKeyPath, KEY_READ) == ERROR_SUCCESS)
1422 {
1423 CLSID clsid;
1424
1425 DWORD KeyState = 0;
1426 if (lpcmi->fMask & CMIC_MASK_SHIFT_DOWN)
1427 KeyState |= MK_SHIFT;
1428 if (lpcmi->fMask & CMIC_MASK_CONTROL_DOWN)
1429 KeyState |= MK_CONTROL;
1430
1431 POINTL *pPtl = NULL;
1432 C_ASSERT(sizeof(POINT) == sizeof(POINTL));
1433 if (lpcmi->fMask & CMIC_MASK_PTINVOKE)
1434 pPtl = (POINTL*)&lpcmi->ptInvoke;
1435
1437 hr = SHELL_GetRegCLSID(VerbKey, L"command", L"DelegateExecute", clsid);
1438 if (SUCCEEDED(hr))
1439 hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IExecuteCommand, &pEC));
1440 if (SUCCEEDED(hr))
1441 {
1444 return InvokeIExecuteCommandWithDataObject(pEC, pEntry->Verb.GetString(), pPB, m_pDataObj,
1445 lpcmi, static_cast<IContextMenu*>(this));
1446 }
1447
1449 hr = SHELL_GetRegCLSID(VerbKey, L"DropTarget", L"CLSID", clsid);
1450 if (SUCCEEDED(hr))
1451 hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_PPV_ARG(IDropTarget, &pDT));
1452 if (SUCCEEDED(hr))
1453 {
1456 IUnknown_SetSite(pDT, static_cast<IContextMenu*>(this));
1457 IUnknown_InitializeCommand(pDT, pEntry->Verb.GetString(), pPB);
1458 hr = SHSimulateDrop(pDT, m_pDataObj, KeyState, pPtl, NULL);
1459 IUnknown_SetSite(pDT, NULL);
1460 return hr;
1461 }
1462 }
1463
1464 /* Get the browse flags to see if we need to browse */
1466
1467 for (i=0; i < m_cidl; i++)
1468 {
1469 /* Check if we need to browse */
1470 if (wFlags)
1471 {
1472 hr = TryToBrowse(lpcmi, m_apidl[i], wFlags);
1473 if (SUCCEEDED(hr))
1474 {
1475 /* In WinXP if we have browsed, we don't open any more folders.
1476 * In Win7 we browse to the first folder we find and
1477 * open new windows for each of the rest of the folders */
1479 if (ntver >= _WIN32_WINNT_VISTA)
1480 wFlags = 0; // FIXME: = SBSP_NEWBROWSER | (wFlags & ~SBSP_SAMEBROWSER);
1481 else
1482 i = m_cidl;
1483
1484 continue;
1485 }
1486 }
1487
1488 InvokePidl(lpcmi, m_apidl[i], pEntry);
1489 }
1490
1491 return S_OK;
1492}
1493
1494HRESULT
1496 LPCMINVOKECOMMANDINFOEX lpcmi, WPARAM CmdId)
1497{
1498 BOOL Unicode = IsUnicode(*lpcmi);
1499 WCHAR lParamBuf[MAX_PATH];
1500 LPARAM lParam = 0;
1501
1502 if (Unicode && lpcmi->lpParametersW)
1503 lParam = (LPARAM)lpcmi->lpParametersW;
1504 else if (lpcmi->lpParameters)
1505 lParam = SHAnsiToUnicode(lpcmi->lpParameters, lParamBuf, _countof(lParamBuf)) ? (LPARAM)lParamBuf : 0;
1506
1507 HRESULT hr;
1508#if 0 // TODO: Try DFM_INVOKECOMMANDEX first.
1509 DFMICS dfmics = { sizeof(DFMICS), lpcmi->fMask, lParam, m_iIdSCMFirst?, m_iIdDfltLast?, (LPCMINVOKECOMMANDINFO)lpcmi, m_site };
1510 hr = _DoCallback(DFM_INVOKECOMMANDEX, CmdId, &dfmics);
1511 if (hr == E_NOTIMPL)
1512#endif
1513 hr = _DoCallback(DFM_INVOKECOMMAND, CmdId, (void*)lParam);
1514 return hr;
1515}
1516
1517HRESULT
1518WINAPI
1521{
1522 CMINVOKECOMMANDINFOEX LocalInvokeInfo = {};
1524 UINT CmdId;
1525
1526 /* Take a local copy of the fixed members of the
1527 struct as we might need to modify the verb */
1528 memcpy(&LocalInvokeInfo, lpcmi, min(sizeof(LocalInvokeInfo), lpcmi->cbSize));
1529
1530 /* Check if this is a string verb */
1531 if (!IS_INTRESOURCE(LocalInvokeInfo.lpVerb))
1532 {
1533 /* Get the ID which corresponds to this verb, and update our local copy */
1534 if (MapVerbToCmdId((LPVOID)LocalInvokeInfo.lpVerb, &CmdId, FALSE))
1535 LocalInvokeInfo.lpVerb = MAKEINTRESOURCEA(CmdId);
1536 else
1537 return E_INVALIDARG;
1538 }
1539
1540 CmdId = LOWORD(LocalInvokeInfo.lpVerb);
1541
1542 if (!m_DynamicEntries.IsEmpty() && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast)
1543 {
1544 LocalInvokeInfo.lpVerb -= m_iIdSHEFirst;
1545 Result = InvokeShellExt(&LocalInvokeInfo);
1546 return Result;
1547 }
1548
1549 if (!m_StaticEntries.IsEmpty() && CmdId >= m_iIdSCMFirst && CmdId < m_iIdSCMLast)
1550 {
1551 LocalInvokeInfo.lpVerb -= m_iIdSCMFirst;
1552 Result = InvokeRegVerb(&LocalInvokeInfo);
1553 // TODO: if (FAILED(Result) && !(lpcmi->fMask & CMIC_MASK_FLAG_NO_UI)) SHELL_ErrorBox(m_pSite, Result);
1554 return Result;
1555 }
1556
1557 if (m_iIdCBFirst != m_iIdCBLast && CmdId >= m_iIdCBFirst && CmdId < m_iIdCBLast)
1558 {
1559 Result = _DoInvokeCommandCallback(&LocalInvokeInfo, CmdId - m_iIdCBFirst);
1560 return Result;
1561 }
1562
1563 if (m_iIdDfltFirst != m_iIdDfltLast && CmdId >= m_iIdDfltFirst && CmdId < m_iIdDfltLast)
1564 {
1565 CmdId -= m_iIdDfltFirst;
1566 /* See the definitions of IDM_CUT and co to see how this works */
1567 CmdId += DCM_FCIDM_SHVIEW_OFFSET;
1568 }
1569
1570 if (LocalInvokeInfo.cbSize >= sizeof(CMINVOKECOMMANDINFOEX) && (LocalInvokeInfo.fMask & CMIC_MASK_PTINVOKE))
1571 {
1572 if (m_pDataObj && FAILED_UNEXPECTEDLY(DataObject_SetOffset(m_pDataObj, &LocalInvokeInfo.ptInvoke)))
1573 {
1574 ERR("Unable to add OFFSET to DataObject!\n");
1575 }
1576 }
1577
1578 /* Check if this is a Id */
1579 switch (CmdId)
1580 {
1582 Result = DoPaste(&LocalInvokeInfo, FALSE);
1583 break;
1585 Result = DoPaste(&LocalInvokeInfo, TRUE);
1586 break;
1587 case FCIDM_SHVIEW_OPEN:
1589 Result = DoOpenOrExplore(&LocalInvokeInfo);
1590 break;
1591 case FCIDM_SHVIEW_COPY:
1592 case FCIDM_SHVIEW_CUT:
1593 Result = DoCopyOrCut(&LocalInvokeInfo, CmdId == FCIDM_SHVIEW_COPY);
1594 break;
1596 Result = DoCreateLink(&LocalInvokeInfo);
1597 break;
1599 Result = DoDelete(&LocalInvokeInfo);
1600 break;
1602 Result = DoRename(&LocalInvokeInfo);
1603 break;
1605 Result = DoProperties(&LocalInvokeInfo);
1606 break;
1608 Result = DoCreateNewFolder(&LocalInvokeInfo);
1609 break;
1611 Result = DoCopyToMoveToFolder(&LocalInvokeInfo, TRUE);
1612 break;
1614 Result = DoCopyToMoveToFolder(&LocalInvokeInfo, FALSE);
1615 break;
1616 case FCIDM_SHVIEW_UNDO:
1617 Result = DoUndo(&LocalInvokeInfo);
1618 break;
1619 default:
1621 ERR("Unhandled Verb %xl\n", LOWORD(LocalInvokeInfo.lpVerb));
1622 break;
1623 }
1624
1625 return Result;
1626}
1627
1628HRESULT
1629WINAPI
1631 UINT_PTR idCommand,
1632 UINT uFlags,
1634 LPSTR lpszName,
1635 UINT uMaxNameLen)
1636{
1637 /* We don't handle the help text yet */
1638 if (uFlags == GCS_HELPTEXTA ||
1639 uFlags == GCS_HELPTEXTW ||
1640 HIWORD(idCommand) != 0)
1641 {
1642 return E_NOTIMPL;
1643 }
1644
1645 UINT CmdId = LOWORD(idCommand);
1646
1647 if (!m_DynamicEntries.IsEmpty() && CmdId >= m_iIdSHEFirst && CmdId < m_iIdSHELast)
1648 {
1649 idCommand -= m_iIdSHEFirst;
1651 if (!pEntry)
1652 return E_FAIL;
1653
1654 idCommand -= pEntry->iIdCmdFirst;
1655 return pEntry->pCM->GetCommandString(idCommand,
1656 uFlags,
1657 lpReserved,
1658 lpszName,
1659 uMaxNameLen);
1660 }
1661
1662 if (!m_StaticEntries.IsEmpty() && CmdId >= m_iIdSCMFirst && CmdId < m_iIdSCMLast)
1663 {
1664 /* Validation just returns S_OK on a match. The id exists. */
1665 if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEW)
1666 return S_OK;
1667
1668 CmdId -= m_iIdSCMFirst;
1669
1670 POSITION it = m_StaticEntries.FindIndex(CmdId);
1671
1672 if (it == NULL)
1673 return E_INVALIDARG;
1674
1676
1677 if (uFlags == GCS_VERBW)
1678 return StringCchCopyW((LPWSTR)lpszName, uMaxNameLen, pEntry->Verb);
1679
1680 if (uFlags == GCS_VERBA)
1681 {
1682 if (SHUnicodeToAnsi(pEntry->Verb, lpszName, uMaxNameLen))
1683 return S_OK;
1684 }
1685
1686 return E_INVALIDARG;
1687 }
1688
1689 //FIXME: Should we handle callbacks here?
1690 if (m_iIdDfltFirst != m_iIdDfltLast && CmdId >= m_iIdDfltFirst && CmdId < m_iIdDfltLast)
1691 {
1692 CmdId -= m_iIdDfltFirst;
1693 /* See the definitions of IDM_CUT and co to see how this works */
1694 CmdId += DCM_FCIDM_SHVIEW_OFFSET;
1695 }
1696
1697 /* Loop looking for a matching Id */
1698 for (UINT i = 0; i < _countof(g_StaticInvokeCmdMap); i++)
1699 {
1700 if (g_StaticInvokeCmdMap[i].IntVerb == CmdId)
1701 {
1702 /* Validation just returns S_OK on a match */
1703 if (uFlags == GCS_VALIDATEA || uFlags == GCS_VALIDATEW)
1704 return S_OK;
1705
1706 /* Return a copy of the ANSI verb */
1707 if (uFlags == GCS_VERBA)
1708 return StringCchCopyA(lpszName, uMaxNameLen, g_StaticInvokeCmdMap[i].szStringVerb);
1709
1710 /* Convert the ANSI verb to unicode and return that */
1711 if (uFlags == GCS_VERBW)
1712 {
1713 if (SHAnsiToUnicode(g_StaticInvokeCmdMap[i].szStringVerb, (LPWSTR)lpszName, uMaxNameLen))
1714 return S_OK;
1715 }
1716 }
1717 }
1718
1719 return E_INVALIDARG;
1720}
1721
1722HRESULT
1723WINAPI
1725 UINT uMsg,
1726 WPARAM wParam,
1727 LPARAM lParam)
1728{
1729 /* FIXME: Should we implement this as well? */
1730 return S_OK;
1731}
1732
1734{
1735 if (uMsg == WM_DRAWITEM)
1736 {
1737 DRAWITEMSTRUCT* pDrawStruct = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
1738 *CmdId = pDrawStruct->itemID;
1739 return S_OK;
1740 }
1741 else if (uMsg == WM_MEASUREITEM)
1742 {
1743 MEASUREITEMSTRUCT* pMeasureStruct = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
1744 *CmdId = pMeasureStruct->itemID;
1745 return S_OK;
1746 }
1747
1748 return E_FAIL;
1749}
1750
1752{
1753 if (uMsg == WM_DRAWITEM)
1754 {
1755 DRAWITEMSTRUCT* pDrawStruct = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
1756 pDrawStruct->itemID = CmdId;
1757 return S_OK;
1758 }
1759 else if (uMsg == WM_MEASUREITEM)
1760 {
1761 MEASUREITEMSTRUCT* pMeasureStruct = reinterpret_cast<MEASUREITEMSTRUCT*>(lParam);
1762 pMeasureStruct->itemID = CmdId;
1763 return S_OK;
1764 }
1765
1766 return E_FAIL;
1767}
1768
1769HRESULT
1770WINAPI
1772 UINT uMsg,
1773 WPARAM wParam,
1774 LPARAM lParam,
1775 LRESULT *plResult)
1776{
1777 if (uMsg == WM_INITMENUPOPUP)
1778 {
1779 POSITION it = m_DynamicEntries.GetHeadPosition();
1780 while (it != NULL)
1781 {
1783 SHForwardContextMenuMsg(info.pCM, uMsg, wParam, lParam, plResult, TRUE);
1784 }
1785 return S_OK;
1786 }
1787
1788 UINT CmdId;
1789 HRESULT hr = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdId);
1790 if (FAILED(hr))
1791 return S_FALSE;
1792
1793 if (CmdId < m_iIdSHEFirst || CmdId >= m_iIdSHELast)
1794 return S_FALSE;
1795
1796 CmdId -= m_iIdSHEFirst;
1798 if (pEntry)
1799 {
1800 SHSetMenuIdInMenuMsg(uMsg, lParam, CmdId - pEntry->iIdCmdFirst);
1801 SHForwardContextMenuMsg(pEntry->pCM, uMsg, wParam, lParam, plResult, TRUE);
1802 }
1803
1804 return S_OK;
1805}
1806
1807HRESULT
1808WINAPI
1810{
1811 m_site = pUnkSite;
1812 return S_OK;
1813}
1814
1815HRESULT
1816WINAPI
1818{
1819 if (!m_site)
1820 return E_FAIL;
1821
1822 return m_site->QueryInterface(riid, ppvSite);
1823}
1824
1825static
1826HRESULT
1828{
1829 return ShellObjectCreatorInit<CDefaultContextMenu>(pdcm, lpfn, riid, ppv);
1830}
1831
1832/*************************************************************************
1833 * SHCreateDefaultContextMenu [SHELL32.325] Vista API
1834 *
1835 */
1836
1837HRESULT
1838WINAPI
1840{
1841 HRESULT hr;
1842
1843 if (!ppv)
1844 return E_INVALIDARG;
1845
1848 return hr;
1849
1850 return S_OK;
1851}
1852
1853/*************************************************************************
1854 * CDefFolderMenu_Create2 [SHELL32.701]
1855 *
1856 */
1857
1858HRESULT
1859WINAPI
1861 PCIDLIST_ABSOLUTE pidlFolder,
1862 HWND hwnd,
1863 UINT cidl,
1865 IShellFolder *psf,
1866 LPFNDFMCALLBACK lpfn,
1867 UINT nKeys,
1868 const HKEY *ahkeyClsKeys,
1869 IContextMenu **ppcm)
1870{
1871 DEFCONTEXTMENU dcm;
1872 dcm.hwnd = hwnd;
1873 dcm.pcmcb = NULL;
1874 dcm.pidlFolder = pidlFolder;
1875 dcm.psf = psf;
1876 dcm.cidl = cidl;
1877 dcm.apidl = apidl;
1879 dcm.cKeys = nKeys;
1880 dcm.aKeys = ahkeyClsKeys;
1881
1884 return hr;
1885
1886 return S_OK;
1887}
static const struct _StaticInvokeCommandMap_ g_StaticInvokeCmdMap[]
struct _DynamicShellEntry_ * PDynamicShellEntry
struct _DynamicShellEntry_ DynamicShellEntry
UINT MapVerbToDfmCmd(_In_ LPCSTR verba)
static int FindVerbInDefaultVerbList(LPCWSTR List, LPCWSTR Verb)
static BOOL HasClipboardData()
static HRESULT CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn, REFIID riid, void **ppv)
BOOL WINAPI _InsertMenuItemW(HMENU hMenu, UINT indexMenu, BOOL fByPosition, UINT wID, UINT fType, LPCWSTR dwTypeData, UINT fState)
HRESULT WINAPI SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
static HRESULT SHELL_GetRegCLSID(HKEY hKey, LPCWSTR SubKey, LPCWSTR Value, CLSID &clsid)
static BOOL InsertMenuItemAt(HMENU hMenu, UINT Pos, UINT Flags)
HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId)
#define DCM_FCIDM_SHVIEW_OFFSET
EXTERN_C HRESULT SHELL32_EnumDefaultVerbList(LPCWSTR List, UINT Index, LPWSTR Verb, SIZE_T cchMax)
static bool IsVerbListSeparator(WCHAR Ch)
static HRESULT MapVerbToCmdId(PVOID Verb, BOOL IsUnicode, IContextMenu *pCM, UINT idFirst, UINT idLast)
struct _StaticShellEntry_ StaticShellEntry
struct _StaticShellEntry_ * PStaticShellEntry
HRESULT WINAPI CDefFolderMenu_Create2(PCIDLIST_ABSOLUTE pidlFolder, HWND hwnd, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, IShellFolder *psf, LPFNDFMCALLBACK lpfn, UINT nKeys, const HKEY *ahkeyClsKeys, IContextMenu **ppcm)
#define MAX_VERB
HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId)
HRESULT CRecyclerDropTarget_CreateInstance(REFIID riid, LPVOID *ppvOut)
#define shell32_hInstance
UINT cchMax
static DWORD const LPVOID const lpReserved
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define IDM_PROPERTIES
Definition: resources.h:9
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define EXTERN_C
Definition: basetyps.h:12
#define STDMETHOD(m)
Definition: basetyps.h:62
#define UNIMPLEMENTED
Definition: ntoskrnl.c:15
HANDLE HKEY
Definition: registry.h:26
#define RegCloseKey(hKey)
Definition: registry.h:49
#define _stricmp
Definition: cat.c:22
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired=KEY_READ|KEY_WRITE) noexcept
Definition: atlbase.h:1173
HRESULT InvokeRegVerb(LPCMINVOKECOMMANDINFOEX lpcmi)
STDMETHOD() QueryService(REFGUID svc, REFIID riid, void **ppv) override
UINT AddShellExtensionsToMenu(HMENU hMenu, UINT *pIndexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
HRESULT DoRename(LPCMINVOKECOMMANDINFOEX lpcmi)
STDMETHOD() GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen) override
BOOL MapVerbToCmdId(PVOID Verb, PUINT idCmd, BOOL IsUnicode)
HRESULT DoCreateLink(LPCMINVOKECOMMANDINFOEX lpcmi)
CComPtr< IDataObject > m_pDataObj
UINT AddStaticContextMenusToMenu(HMENU hMenu, UINT *IndexMenu, UINT iIdCmdFirst, UINT iIdCmdLast, UINT uFlags)
CComPtr< IShellFolder > m_psf
HRESULT DoUndo(LPCMINVOKECOMMANDINFOEX lpcmi)
PCUITEMID_CHILD_ARRAY m_apidl
STDMETHOD() SetSite(IUnknown *pUnkSite) override
STDMETHOD() QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) override
CComPtr< IContextMenuCB > m_pmcb
PDynamicShellEntry GetDynamicEntry(UINT idCmd)
CAtlList< StaticShellEntry > m_StaticEntries
HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bCopy)
void AddStaticEntry(const HKEY hkeyClass, const WCHAR *szVerb, UINT uFlags)
HRESULT DoDelete(LPCMINVOKECOMMANDINFOEX lpcmi)
HRESULT DoCopyToMoveToFolder(LPCMINVOKECOMMANDINFOEX lpici, BOOL bCopy)
DWORD BrowserFlagsFromVerb(LPCMINVOKECOMMANDINFOEX lpcmi, PStaticShellEntry pEntry)
CAtlList< DynamicShellEntry > m_DynamicEntries
HRESULT WINAPI Initialize(const DEFCONTEXTMENU *pdcm, LPFNDFMCALLBACK lpfn)
HRESULT _DoInvokeCommandCallback(LPCMINVOKECOMMANDINFOEX lpcmi, WPARAM CmdId)
BOOL IsShellExtensionAlreadyLoaded(REFCLSID clsid)
STDMETHOD() HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) override
HRESULT TryToBrowse(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, DWORD wFlags)
HRESULT DoProperties(LPCMINVOKECOMMANDINFOEX lpcmi)
CComPtr< IUnknown > m_site
BOOL EnumerateDynamicContextHandlerForKey(HKEY hRootKey)
HRESULT DoCreateNewFolder(LPCMINVOKECOMMANDINFOEX lpici)
HRESULT DoPaste(LPCMINVOKECOMMANDINFOEX lpcmi, BOOL bLink)
STDMETHOD() GetSite(REFIID riid, void **ppvSite) override
HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFOEX lpcmi)
HRESULT LoadDynamicContextMenuHandler(HKEY hKey, REFCLSID clsid)
void TryPickDefault(HMENU hMenu, UINT idCmdFirst, UINT DfltOffset, UINT uFlags)
HRESULT InvokeShellExt(LPCMINVOKECOMMANDINFOEX lpcmi)
STDMETHOD() HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) override
HRESULT _DoCallback(UINT uMsg, WPARAM wParam, LPVOID lParam)
STDMETHOD() InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) override
PIDLIST_ABSOLUTE m_pidlFolder
HRESULT InvokePidl(LPCMINVOKECOMMANDINFOEX lpcmi, LPCITEMIDLIST pidl, PStaticShellEntry pEntry)
void AddStaticEntriesForKey(HKEY hKey, UINT uFlags)
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
static UINT RosGetProcessEffectiveVersion(VOID)
Definition: compat_undoc.h:39
wcscpy
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
ush Pos
Definition: deflate.h:92
#define ERROR_SUCCESS
Definition: deptool.c:10
LONG RegLoadMUIStringW(IN HKEY hKey, IN LPCWSTR pszValue OPTIONAL, OUT LPWSTR pszOutBuf, IN DWORD cbOutBuf, OUT LPDWORD pcbData OPTIONAL, IN DWORD Flags, IN LPCWSTR pszDirectory OPTIONAL)
Definition: muireg.c:53
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define DFM_GETDEFSTATICID
Definition: precomp.h:47
#define DFM_INVOKECOMMANDEX
Definition: precomp.h:46
#define DFM_MERGECONTEXTMENU
Definition: precomp.h:44
#define DFM_INVOKECOMMAND
Definition: precomp.h:45
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LSTATUS WINAPI RegGetValueW(HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue, DWORD dwFlags, LPDWORD pdwType, PVOID pvData, LPDWORD pcbData)
Definition: reg.c:1931
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2504
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
UINT uFlags
Definition: api.c:59
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define FAILED_UNEXPECTEDLY(hr)
Definition: precomp.h:121
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4224
HRESULT WINAPI OleSetClipboard(IDataObject *data)
Definition: clipboard.c:2199
HRESULT WINAPI OleGetClipboard(IDataObject **obj)
Definition: clipboard.c:2249
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
#define RRF_RT_REG_DWORD
Definition: driver.c:578
#define RRF_RT_REG_SZ
Definition: driver.c:575
#define CmicFlagsToSeeFlags(flags)
Definition: precomp.h:190
#define VERBKEY_CCHMAX
Definition: precomp.h:130
EXTERN_C HRESULT IUnknown_InitializeCommand(_In_ IUnknown *pUnk, _In_ PCWSTR pszCommandName, _In_opt_ IPropertyBag *pPB)
Definition: utils.cpp:1654
EXTERN_C HRESULT InvokeIExecuteCommandWithDataObject(_In_ IExecuteCommand *pEC, _In_ PCWSTR pszCommandName, _In_opt_ IPropertyBag *pPB, _In_ IDataObject *pDO, _In_opt_ LPCMINVOKECOMMANDINFOEX pICI, _In_opt_ IUnknown *pSite)
Definition: utils.cpp:1708
HRESULT SHELL32_ShowPropertiesDialog(IDataObject *pdtobj)
Definition: shlfolder.cpp:520
static BOOL RegValueExists(HKEY hKey, LPCWSTR Name)
Definition: utils.h:43
void WINAPI SHFree(LPVOID pv)
Definition: shellole.c:326
HRESULT WINAPI SHCoCreateInstance(LPCWSTR aclsid, const CLSID *clsid, LPUNKNOWN pUnkOuter, REFIID refiid, LPVOID *ppv)
Definition: shellole.c:105
BOOL WINAPI PathYetAnotherMakeUniqueName(LPWSTR buffer, LPCWSTR path, LPCWSTR shortname, LPCWSTR longname)
Definition: shellpath.c:848
BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj, DWORD grfKeyState, PPOINTL lpPt, DWORD *pdwEffect)
Definition: ordinal.c:1828
HRESULT WINAPI IUnknown_QueryService(IUnknown *, REFGUID, REFIID, LPVOID *)
Definition: ordinal.c:1501
HRESULT WINAPI SHCreatePropertyBagOnRegKey(HKEY hKey, LPCWSTR subkey, DWORD grfMode, REFIID riid, void **ppv)
Definition: ordinal.c:5214
HRESULT WINAPI IUnknown_SetSite(IUnknown *obj, IUnknown *site)
Definition: ordinal.c:1411
DWORD WINAPI SHAnsiToUnicode(LPCSTR lpSrcStr, LPWSTR lpDstStr, int iLen)
Definition: string.c:2673
INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen)
Definition: string.c:2797
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
static IShellFolder IShellItem **static IBindCtx LPITEMIDLIST SFGAOF
Definition: ebrowser.c:83
#define InitFormatEtc(fe, cf, med)
Definition: editor.h:33
#define IDS_NEWFOLDER
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
PWDFDEVICE_INIT pInit
FxAutoRegKey hKey
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
return pTarget Start()
GLuint res
Definition: glext.h:9613
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
const GLint * first
Definition: glext.h:5794
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
HRESULT GetCommandString([in] UINT_PTR idCmd, [in] UINT uType, [out] UINT *pwReserved, [out, size_is(cchMax)] LPSTR pszName, [in] UINT cchMax)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define C_ASSERT(e)
Definition: intsafe.h:73
uint32_t entry
Definition: isohybrid.c:63
#define LOBYTE(W)
Definition: jmemdos.c:487
#define debugstr_w
Definition: kernel32.h:32
#define BEGIN_COM_MAP(x)
Definition: atlcom.h:581
#define COM_INTERFACE_ENTRY_IID(iid, x)
Definition: atlcom.h:601
#define END_COM_MAP()
Definition: atlcom.h:592
if(dx< 0)
Definition: linetemp.h:194
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
const IID IID_IObjectWithSite
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
#define min(a, b)
Definition: monoChain.cc:55
REFCLSID clsid
Definition: msctf.c:82
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
unsigned int * PUINT
Definition: ndis.h:50
unsigned int UINT
Definition: ndis.h:50
#define _In_
Definition: no_sal2.h:158
#define KEY_READ
Definition: nt_native.h:1023
#define UNICODE_NULL
#define L(x)
Definition: ntvdm.h:50
#define STGM_READ
Definition: objbase.h:917
#define LOWORD(l)
Definition: pedump.c:82
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
PITEMID_CHILD * _ILCopyaPidl(PCUITEMID_CHILD_ARRAY apidlsrc, UINT cidl)
Definition: pidl.c:2589
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:237
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:1044
HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST *ppidl, DWORD *attributes)
Definition: pidl.c:403
LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
Definition: pidl.c:198
LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:816
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1454
void _ILFreeaPidl(LPITEMIDLIST *apidl, UINT cidl)
Definition: pidl.c:2572
#define REFIID
Definition: guiddef.h:118
#define REFCLSID
Definition: guiddef.h:117
#define err(...)
DWORD WINAPI GetVersion()
Definition: redirtest.c:5
HRESULT WINAPI SHForwardContextMenuMsg(IUnknown *pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult, BOOL useIContextMenu2)
Definition: rosordinal.c:11
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
static __inline const char * wine_dbgstr_guid(const GUID *id)
Definition: debug.h:197
#define _WIN32_WINNT_WIN7
Definition: sdkddkver.h:28
#define _WIN32_WINNT_VISTA
Definition: sdkddkver.h:25
#define Ch(x, y, z)
Definition: sha2.c:141
static __inline LPWSTR __SHCloneStrAtoW(WCHAR **target, const char *source)
Definition: shell32_main.h:184
#define SEE_MASK_CLASSKEY
Definition: shellapi.h:26
#define SEE_MASK_IDLIST
Definition: shellapi.h:27
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2452
int WINAPI SHCreateDirectory(HWND hWnd, LPCWSTR path)
Definition: shlfileop.cpp:948
HRESULT hr
Definition: shlfolder.c:183
#define SID_IShellBrowser
UINT WINAPI Shell_MergeMenus(HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags)
Definition: shlmenu.c:856
#define DFM_CMD_DELETE
Definition: shlobj.h:2616
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:558
#define CFSTR_PREFERREDDROPEFFECT
Definition: shlobj.h:568
#define SHCNE_MKDIR
Definition: shlobj.h:1901
#define DFM_CMD_NEWFOLDER
Definition: shlobj.h:2621
#define DFM_CMD_COPY
Definition: shlobj.h:2618
#define DFM_CMD_PASTE
Definition: shlobj.h:2622
#define SHCNF_FLUSH
Definition: shlobj.h:1936
#define SHCNF_PATHW
Definition: shlobj.h:1933
#define DFM_CMD_PROPERTIES
Definition: shlobj.h:2620
HRESULT(CALLBACK * LPFNDFMCALLBACK)(_In_opt_ IShellFolder *, _In_opt_ HWND, _In_opt_ IDataObject *, UINT, WPARAM, LPARAM)
Definition: shlobj.h:2576
#define DFM_CMD_RENAME
Definition: shlobj.h:2628
#define DFM_CMD_LINK
Definition: shlobj.h:2619
#define PathRemoveFileSpec
Definition: shlwapi.h:1070
#define FCIDM_SHVIEW_CUT
Definition: shresdef.h:854
#define FCIDM_SHVIEW_OPEN
Definition: shresdef.h:881
#define FCIDM_SHVIEW_UNDO
Definition: shresdef.h:857
#define IDM_DELETE
Definition: shresdef.h:894
#define FCIDM_SHVIEW_COPY
Definition: shresdef.h:855
#define IDS_OPEN_VERB
Definition: shresdef.h:212
#define IDM_INSERT
Definition: shresdef.h:892
#define FCIDM_SHVIEW_INSERTLINK
Definition: shresdef.h:858
#define IDS_FIND_VERB
Definition: shresdef.h:216
#define FCIDM_SHVIEW_NEWFOLDER
Definition: shresdef.h:877
#define IDM_RENAME
Definition: shresdef.h:895
#define IDM_COPY
Definition: shresdef.h:891
#define FCIDM_SHVIEW_EXPLORE
Definition: shresdef.h:880
#define FCIDM_SHVIEW_PROPERTIES
Definition: shresdef.h:853
#define IDS_EXPLORE_VERB
Definition: shresdef.h:213
#define IDM_CUT
Definition: shresdef.h:890
#define IDM_CREATELINK
Definition: shresdef.h:893
#define IDS_PRINT_VERB
Definition: shresdef.h:217
#define FCIDM_SHVIEW_COPYTO
Definition: shresdef.h:859
#define FCIDM_SHVIEW_MOVETO
Definition: shresdef.h:860
#define FCIDM_SHVIEW_DELETE
Definition: shresdef.h:852
#define FCIDM_SHVIEW_RENAME
Definition: shresdef.h:874
#define FCIDM_SHVIEW_CREATELINK
Definition: shresdef.h:875
#define IDS_RUNAS_VERB
Definition: shresdef.h:214
#define IDS_EDIT_VERB
Definition: shresdef.h:215
#define FCIDM_SHVIEW_INSERT
Definition: shresdef.h:856
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const PCUITEMID_CHILD * PCUITEMID_CHILD_ARRAY
Definition: shtypes.idl:71
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
#define TRACE(s)
Definition: solgame.cpp:4
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:557
STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, size_t cchToCopy)
Definition: strsafe.h:236
IContextMenuCB * pcmcb
Definition: shlobj.h:2558
IShellFolder * psf
Definition: shlobj.h:2560
IUnknown * punkAssociationInfo
Definition: shlobj.h:2563
PCUITEMID_CHILD_ARRAY apidl
Definition: shlobj.h:2562
const HKEY * aKeys
Definition: shlobj.h:2565
PCIDLIST_ABSOLUTE pidlFolder
Definition: shlobj.h:2559
CComPtr< IContextMenu > pCM
Definition: scsiwmi.h:51
UINT idCmdFirst
Definition: shlobj.h:1400
LPCWSTR lpDirectory
Definition: shellapi.h:335
LPCWSTR lpParameters
Definition: shellapi.h:334
LPWSTR dwTypeData
Definition: winuser.h:3280
int32_t INT_PTR
Definition: typedefs.h:64
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define HIWORD(l)
Definition: typedefs.h:247
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
#define ZeroMemory
Definition: winbase.h:1743
#define GHND
Definition: winbase.h:323
_In_ PSID _Out_writes_to_opt_ cchName LPSTR _Inout_ LPDWORD cchName
Definition: winbase.h:2798
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define HRESULT_CODE(hr)
Definition: winerror.h:76
#define ERROR_NOT_FOUND
Definition: winerror.h:690
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define MK_SHIFT
Definition: winuser.h:2380
UINT WINAPI GetMenuDefaultItem(_In_ HMENU hMenu, _In_ UINT fByPos, _In_ UINT gmdiFlags)
#define MF_BYCOMMAND
Definition: winuser.h:202
#define MIIM_ID
Definition: winuser.h:733
BOOL WINAPI SetMenuDefaultItem(_In_ HMENU, _In_ UINT, _In_ UINT)
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
BOOL WINAPI DeleteMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
#define MFT_SEPARATOR
Definition: winuser.h:755
#define WM_DRAWITEM
Definition: winuser.h:1656
#define MIIM_STATE
Definition: winuser.h:732
#define MFS_DEFAULT
Definition: winuser.h:759
HMENU WINAPI GetSubMenu(_In_ HMENU, _In_ int)
#define WM_INITMENUPOPUP
Definition: winuser.h:1757
#define MK_CONTROL
Definition: winuser.h:2381
#define MF_SEPARATOR
Definition: winuser.h:137
#define MF_BYPOSITION
Definition: winuser.h:203
#define WM_MEASUREITEM
Definition: winuser.h:1657
#define MFS_ENABLED
Definition: winuser.h:761
#define MAKEINTRESOURCEA(i)
Definition: winuser.h:581
BOOL WINAPI DestroyMenu(_In_ HMENU)
#define MFT_STRING
Definition: winuser.h:757
HMENU WINAPI LoadMenuW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
#define MIIM_DATA
Definition: winuser.h:737
#define MIIM_TYPE
Definition: winuser.h:736
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
static void Initialize()
Definition: xlate.c:212
#define IID_PPV_ARG(Itype, ppType)
#define IID_NULL_PPV_ARG(Itype, ppType)
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185