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 (janderwald@reactos.org)
11 WINE_DEFAULT_DEBUG_CHANNEL(dmenu
);
13 typedef struct _DynamicShellEntry_
19 struct _DynamicShellEntry_
* Next
;
20 }DynamicShellEntry
, *PDynamicShellEntry
;
22 typedef struct _StaticShellEntry_
26 struct _StaticShellEntry_
* Next
;
27 }StaticShellEntry
, *PStaticShellEntry
;
32 const IContextMenu2Vtbl
*lpVtbl
;
35 IDataObject
* pDataObj
;
36 DWORD bGroupPolicyActive
;
37 PDynamicShellEntry dhead
; /* first dynamic shell extension entry */
38 UINT iIdSHEFirst
; /* first used id */
39 UINT iIdSHELast
; /* last used id */
40 PStaticShellEntry shead
; /* first static shell extension entry */
41 UINT iIdSCMFirst
; /* first static used id */
42 UINT iIdSCMLast
; /* last static used id */
43 }IDefaultContextMenuImpl
, *LPIDefaultContextMenuImpl
;
45 static LPIDefaultContextMenuImpl __inline
impl_from_IContextMenu( IContextMenu2
*iface
)
47 return (LPIDefaultContextMenuImpl
)((char*)iface
- FIELD_OFFSET(IDefaultContextMenuImpl
, lpVtbl
));
50 VOID
INewItem_SetCurrentShellFolder(IShellFolder
* psfParent
); // HACK
56 IDefaultContextMenu_fnQueryInterface(
61 IDefaultContextMenuImpl
*This
= (IDefaultContextMenuImpl
*)iface
;
63 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
67 if(IsEqualIID(riid
, &IID_IUnknown
) ||
68 IsEqualIID(riid
, &IID_IContextMenu
) ||
69 IsEqualIID(riid
, &IID_IContextMenu2
))
76 IUnknown_AddRef((IUnknown
*)*ppvObj
);
77 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
80 TRACE("-- Interface: E_NOINTERFACE\n");
88 IDefaultContextMenu_fnAddRef(
91 IDefaultContextMenuImpl
*This
= (IDefaultContextMenuImpl
*)iface
;
92 ULONG refCount
= InterlockedIncrement(&This
->ref
);
94 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
102 IDefaultContextMenu_fnRelease(
103 IContextMenu2
*iface
)
105 PDynamicShellEntry dEntry
, dNext
;
106 PStaticShellEntry sEntry
, sNext
;
107 IDefaultContextMenuImpl
*This
= (IDefaultContextMenuImpl
*)iface
;
108 ULONG refCount
= InterlockedDecrement(&This
->ref
);
110 TRACE("(%p)->(count=%u)\n", This
, refCount
+ 1);
113 /* free dynamic shell extension entries */
114 dEntry
= This
->dhead
;
117 dNext
= dEntry
->Next
;
118 IContextMenu_Release(dEntry
->CMenu
);
119 HeapFree(GetProcessHeap(), 0, dEntry
);
122 /* free static shell extension entries */
123 sEntry
= This
->shead
;
126 sNext
= sEntry
->Next
;
127 HeapFree(GetProcessHeap(), 0, sEntry
->szClass
);
128 HeapFree(GetProcessHeap(), 0, sEntry
->szVerb
);
129 HeapFree(GetProcessHeap(), 0, sEntry
);
132 HeapFree(GetProcessHeap(),0,This
);
140 SH_AddStaticEntry(IDefaultContextMenuImpl
* This
, WCHAR
*szVerb
, WCHAR
* szClass
)
142 PStaticShellEntry curEntry
;
143 PStaticShellEntry lastEntry
= NULL
;
145 curEntry
= This
->shead
;
148 if (!wcsicmp(curEntry
->szVerb
, szVerb
))
150 /* entry already exists */
153 lastEntry
= curEntry
;
154 curEntry
= curEntry
->Next
;
157 TRACE("adding verb %s szClass %s\n", debugstr_w(szVerb
), debugstr_w(szClass
));
159 curEntry
= HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry
));
162 curEntry
->Next
= NULL
;
163 curEntry
->szVerb
= HeapAlloc(GetProcessHeap(), 0, (wcslen(szVerb
)+1) * sizeof(WCHAR
));
164 if (curEntry
->szVerb
)
165 wcscpy(curEntry
->szVerb
, szVerb
);
166 curEntry
->szClass
= HeapAlloc(GetProcessHeap(), 0, (wcslen(szClass
)+1) * sizeof(WCHAR
));
167 if (curEntry
->szClass
)
168 wcscpy(curEntry
->szClass
, szClass
);
173 lastEntry
->Next
= curEntry
;
177 This
->shead
= curEntry
;
183 SH_AddStaticEntryForKey(IDefaultContextMenuImpl
* This
, HKEY hKey
, WCHAR
* szClass
)
194 dwName
= sizeof(szName
) / sizeof(WCHAR
);
195 result
= RegEnumKeyExW(hKey
, dwIndex
, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
);
196 szName
[(sizeof(szName
)/sizeof(WCHAR
))-1] = 0;
197 if (result
== ERROR_SUCCESS
)
199 SH_AddStaticEntry(This
, szName
, szClass
);
202 }while(result
== ERROR_SUCCESS
);
207 SH_AddStaticEntryForFileClass(IDefaultContextMenuImpl
* This
, WCHAR
* szExt
)
214 static WCHAR szShell
[] = L
"\\shell";
215 static WCHAR szShellAssoc
[] = L
"SystemFileAssociations\\";
217 TRACE("SH_AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt
));
219 Length
= wcslen(szExt
);
220 if (Length
+ (sizeof(szShell
)/sizeof(WCHAR
)) + 1 < sizeof(szBuffer
)/sizeof(WCHAR
))
222 wcscpy(szBuffer
, szExt
);
223 wcscpy(&szBuffer
[Length
], szShell
);
224 result
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szBuffer
, 0, KEY_READ
| KEY_QUERY_VALUE
, &hKey
);
225 if (result
== ERROR_SUCCESS
)
227 szBuffer
[Length
] = 0;
228 SH_AddStaticEntryForKey(This
, hKey
, szExt
);
233 dwBuffer
= sizeof(szBuffer
);
234 result
= RegGetValueW(HKEY_CLASSES_ROOT
, szExt
, NULL
, RRF_RT_REG_SZ
, NULL
, (LPBYTE
)szBuffer
, &dwBuffer
);
235 if (result
== ERROR_SUCCESS
)
237 Length
= wcslen(szBuffer
);
238 if (Length
+ (sizeof(szShell
)/sizeof(WCHAR
)) + 1 < sizeof(szBuffer
)/sizeof(WCHAR
))
240 wcscpy(&szBuffer
[Length
], szShell
);
241 TRACE("szBuffer %s\n", debugstr_w(szBuffer
));
243 result
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szBuffer
, 0, KEY_READ
| KEY_QUERY_VALUE
, &hKey
);
244 if (result
== ERROR_SUCCESS
)
246 szBuffer
[Length
] = 0;
247 SH_AddStaticEntryForKey(This
, hKey
, szBuffer
);
253 wcscpy(szBuffer
, szShellAssoc
);
254 dwBuffer
= sizeof(szBuffer
) - sizeof(szShellAssoc
) - sizeof(WCHAR
);
255 result
= RegGetValueW(HKEY_CLASSES_ROOT
, szExt
, L
"PerceivedType", RRF_RT_REG_SZ
, NULL
, (LPBYTE
)&szBuffer
[(sizeof(szShellAssoc
)/sizeof(WCHAR
))], &dwBuffer
);
256 if (result
== ERROR_SUCCESS
)
258 Length
= wcslen(&szBuffer
[(sizeof(szShellAssoc
)/sizeof(WCHAR
))]) + (sizeof(szShellAssoc
)/sizeof(WCHAR
));
259 wcscat(&szBuffer
[(sizeof(szShellAssoc
)/sizeof(WCHAR
))], szShell
);
260 TRACE("szBuffer %s\n", debugstr_w(szBuffer
));
262 result
= RegOpenKeyExW(HKEY_CLASSES_ROOT
, szBuffer
, 0, KEY_READ
| KEY_QUERY_VALUE
, &hKey
);
263 if (result
== ERROR_SUCCESS
)
265 szBuffer
[Length
] = 0;
266 SH_AddStaticEntryForKey(This
, hKey
, szBuffer
);
280 if(SUCCEEDED(OleGetClipboard(&pda
)))
285 TRACE("pda=%p\n", pda
);
287 /* Set the FORMATETC structure*/
288 InitFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
289 if(SUCCEEDED(IDataObject_GetData(pda
,&formatetc
,&medium
)))
294 IDataObject_Release(pda
);
295 ReleaseStgMedium(&medium
);
302 DisablePasteOptions(HMENU hMenu
)
306 mii
.cbSize
= sizeof(mii
);
307 mii
.fMask
= MIIM_STATE
;
308 mii
.fState
= MFS_DISABLED
;
310 TRACE("result %d\n", SetMenuItemInfoW(hMenu
, FCIDM_SHVIEW_INSERT
, FALSE
, &mii
));
311 TRACE("result %d\n", SetMenuItemInfoW(hMenu
, FCIDM_SHVIEW_INSERTLINK
, FALSE
, &mii
));
315 IsShellExtensionAlreadyLoaded(IDefaultContextMenuImpl
* This
, const CLSID
* szClass
)
317 PDynamicShellEntry curEntry
= This
->dhead
;
321 if (!memcmp(&curEntry
->ClassID
, szClass
, sizeof(CLSID
)))
323 curEntry
= curEntry
->Next
;
331 SH_LoadDynamicContextMenuHandler(IDefaultContextMenuImpl
* This
, HKEY hKey
, const CLSID
* szClass
, BOOL bExternalInit
)
334 IContextMenu
* cmobj
;
335 IShellExtInit
*shext
;
336 PDynamicShellEntry curEntry
;
340 StringFromCLSID(szClass
, &pstr
);
342 TRACE("SH_LoadDynamicContextMenuHandler entered with This %p hKey %p szClass %s bExternalInit %u\n",This
, hKey
, wine_dbgstr_guid(szClass
), bExternalInit
);
343 //swprintf(szTemp, L"This %p hKey %p szClass %s bExternalInit %u", This, hKey, pstr, bExternalInit);
344 //MessageBoxW(NULL, szTemp, NULL, MB_OK);
346 if (IsShellExtensionAlreadyLoaded(This
, szClass
))
349 hr
= SHCoCreateInstance(NULL
, szClass
, NULL
, &IID_IContextMenu
, (void**)&cmobj
);
352 TRACE("SHCoCreateInstance failed %x\n", GetLastError());
358 hr
= IContextMenu_QueryInterface(cmobj
, &IID_IShellExtInit
, (void**)&shext
);
361 TRACE("Failed to query for interface IID_IShellExtInit\n");
362 IContextMenu_Release(cmobj
);
365 hr
= IShellExtInit_Initialize(shext
, NULL
, This
->pDataObj
, hKey
);
366 IShellExtInit_Release(shext
);
369 TRACE("Failed to initialize shell extension error %x\n", hr
);
370 IContextMenu_Release(cmobj
);
375 curEntry
= HeapAlloc(GetProcessHeap(), 0, sizeof(DynamicShellEntry
));
378 IContextMenu_Release(cmobj
);
379 return E_OUTOFMEMORY
;
382 curEntry
->iIdCmdFirst
= 0;
383 curEntry
->Next
= NULL
;
384 curEntry
->NumIds
= 0;
385 curEntry
->CMenu
= cmobj
;
386 memcpy(&curEntry
->ClassID
, szClass
, sizeof(CLSID
));
390 PDynamicShellEntry pEntry
= This
->dhead
;
394 pEntry
= pEntry
->Next
;
397 pEntry
->Next
= curEntry
;
401 This
->dhead
= curEntry
;
405 if (!memcmp(szClass
, &CLSID_NewMenu
, sizeof(CLSID
)))
407 /* A REAL UGLY HACK */
408 INewItem_SetCurrentShellFolder(This
->dcm
.psf
);
417 EnumerateDynamicContextHandlerForKey(IDefaultContextMenuImpl
*This
, HKEY hRootKey
)
419 WCHAR szKey
[MAX_PATH
] = {0};
420 WCHAR szName
[MAX_PATH
] = {0};
421 DWORD dwIndex
, dwName
;
428 static const WCHAR szShellEx
[] = { 's','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0 };
430 if (RegOpenKeyExW(hRootKey
, szShellEx
, 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
432 TRACE("RegOpenKeyExW failed for key %s\n", debugstr_w(szKey
));
441 res
= RegEnumKeyExW(hKey
, dwIndex
, szName
, &dwName
, NULL
, NULL
, NULL
, NULL
);
442 if (res
== ERROR_SUCCESS
)
444 hResult
= CLSIDFromString(szName
, &clsid
);
448 if (RegGetValueW(hKey
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, szKey
, &dwName
) == ERROR_SUCCESS
)
450 hResult
= CLSIDFromString(szKey
, &clsid
);
453 if (SUCCEEDED(hResult
))
455 if (This
->bGroupPolicyActive
)
457 if (RegGetValueW(HKEY_LOCAL_MACHINE
,
458 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
463 &dwName
) == ERROR_SUCCESS
)
465 SH_LoadDynamicContextMenuHandler(This
, hKey
, &clsid
, TRUE
);
470 SH_LoadDynamicContextMenuHandler(This
, hKey
, &clsid
, TRUE
);
475 }while(res
== ERROR_SUCCESS
);
484 InsertMenuItemsOfDynamicContextMenuExtension(IDefaultContextMenuImpl
* This
, HMENU hMenu
, UINT indexMenu
, UINT idCmdFirst
, UINT idCmdLast
)
486 PDynamicShellEntry curEntry
;
491 This
->iIdSHEFirst
= 0;
492 This
->iIdSHELast
= 0;
496 curEntry
= This
->dhead
;
499 This
->iIdSHEFirst
= idCmdFirst
;
502 hResult
= IContextMenu_QueryContextMenu(curEntry
->CMenu
, hMenu
, indexMenu
++, idCmdFirst
, idCmdLast
, CMF_NORMAL
);
503 if (SUCCEEDED(hResult
))
505 curEntry
->iIdCmdFirst
= idCmdFirst
;
506 curEntry
->NumIds
= LOWORD(hResult
);
507 indexMenu
+= curEntry
->NumIds
;
508 idCmdFirst
+= curEntry
->NumIds
+ 0x10;
510 TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n", curEntry
, hResult
, curEntry
->CMenu
, curEntry
->iIdCmdFirst
, curEntry
->NumIds
);
511 curEntry
= curEntry
->Next
;
514 This
->iIdSHELast
= idCmdFirst
;
515 TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This
->iIdSHEFirst
, This
->iIdSHELast
);
520 BuildBackgroundContextMenu(
521 IDefaultContextMenuImpl
* This
,
528 WCHAR szBuffer
[MAX_PATH
];
533 ZeroMemory(&mii
, sizeof(mii
));
535 TRACE("BuildBackgroundContextMenu entered\n");
537 if (!_ILIsDesktop(This
->dcm
.pidlFolder
))
539 /* view option is only available in browsing mode */
540 hSubMenu
= LoadMenuA(shell32_hInstance
, "MENU_001");
544 LoadStringW(shell32_hInstance
, FCIDM_SHVIEW_VIEW
, szBuffer
, MAX_PATH
);
545 szBuffer
[MAX_PATH
-1] = 0;
547 TRACE("szBuffer %s\n", debugstr_w(szBuffer
));
549 mii
.cbSize
= sizeof(mii
);
550 mii
.fMask
= MIIM_TYPE
| MIIM_STATE
| MIIM_SUBMENU
| MIIM_ID
;
551 mii
.fType
= MFT_STRING
;
552 mii
.wID
= iIdCmdFirst
++;
553 mii
.dwTypeData
= szBuffer
;
554 mii
.cch
= wcslen( mii
.dwTypeData
);
555 mii
.fState
= MFS_ENABLED
;
556 mii
.hSubMenu
= hSubMenu
;
557 InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, &mii
);
558 DestroyMenu(hSubMenu
);
561 hSubMenu
= LoadMenuW(shell32_hInstance
, L
"MENU_002");
564 /* merge general background context menu in */
565 iIdCmdFirst
= Shell_MergeMenus(hMenu
, GetSubMenu(hSubMenu
, 0), indexMenu
, 0, 0xFFFF, MM_DONTREMOVESEPS
| MM_SUBMENUSHAVEIDS
) + 1;
566 DestroyMenu(hSubMenu
);
569 if (!HasClipboardData())
571 TRACE("disabling paste options\n");
572 DisablePasteOptions(hMenu
);
574 /* load extensions from HKCR\* key */
575 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
,
579 &hKey
) == ERROR_SUCCESS
)
581 EnumerateDynamicContextHandlerForKey(This
, hKey
);
585 /* load create new shell extension */
586 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
,
587 L
"CLSID\\{D969A300-E7FF-11d0-A93B-00A0C90F2719}",
590 &hKey
) == ERROR_SUCCESS
)
592 SH_LoadDynamicContextMenuHandler(This
, hKey
, &CLSID_NewMenu
, TRUE
);
596 if (InsertMenuItemsOfDynamicContextMenuExtension(This
, hMenu
, GetMenuItemCount(hMenu
)-1, iIdCmdFirst
, iIdCmdLast
))
598 /* seperate dynamic context menu items */
599 _InsertMenuItemW(hMenu
, GetMenuItemCount(hMenu
)-1, TRUE
, -1, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
607 AddStaticContextMenusToMenu(
610 IDefaultContextMenuImpl
* This
)
614 PStaticShellEntry curEntry
;
621 mii
.cbSize
= sizeof(mii
);
622 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
| MIIM_DATA
;
623 mii
.fType
= MFT_STRING
;
624 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
626 This
->iIdSCMFirst
= mii
.wID
;
628 curEntry
= This
->shead
;
632 fState
= MFS_ENABLED
;
633 if (!wcsicmp(curEntry
->szVerb
, L
"open"))
635 fState
|= MFS_DEFAULT
;
636 idResource
= IDS_OPEN_VERB
;
638 else if (!wcsicmp(curEntry
->szVerb
, L
"runas"))
639 idResource
= IDS_RUNAS_VERB
;
640 else if (!wcsicmp(curEntry
->szVerb
, L
"edit"))
641 idResource
= IDS_EDIT_VERB
;
642 else if (!wcsicmp(curEntry
->szVerb
, L
"find"))
643 idResource
= IDS_FIND_VERB
;
644 else if (!wcsicmp(curEntry
->szVerb
, L
"print"))
645 idResource
= IDS_PRINT_VERB
;
646 else if (!wcsicmp(curEntry
->szVerb
, L
"play"))
647 idResource
= IDS_PLAY_VERB
;
648 else if (!wcsicmp(curEntry
->szVerb
, L
"preview"))
649 idResource
= IDS_PREVIEW_VERB
;
655 if (LoadStringW(shell32_hInstance
, idResource
, szVerb
, sizeof(szVerb
)/sizeof(WCHAR
)))
657 /* use translated verb */
658 szVerb
[(sizeof(szVerb
)/sizeof(WCHAR
))-1] = L
'\0';
659 mii
.dwTypeData
= szVerb
;
664 Length
= wcslen(curEntry
->szClass
) + wcslen(curEntry
->szVerb
) + 8;
665 if (Length
< sizeof(szTemp
)/sizeof(WCHAR
))
667 wcscpy(szTemp
, curEntry
->szClass
);
668 wcscat(szTemp
, L
"\\shell\\");
669 wcscat(szTemp
, curEntry
->szVerb
);
670 dwSize
= sizeof(szVerb
);
672 if (RegGetValueW(HKEY_CLASSES_ROOT
, szTemp
, NULL
, RRF_RT_REG_SZ
, NULL
, szVerb
, &dwSize
) == ERROR_SUCCESS
)
674 /* use description for the menu entry */
675 mii
.dwTypeData
= szVerb
;
679 /* use verb for the menu entry */
680 mii
.dwTypeData
= curEntry
->szVerb
;
686 mii
.cch
= wcslen(mii
.dwTypeData
);
687 InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, &mii
);
690 curEntry
= curEntry
->Next
;
692 This
->iIdSCMLast
= mii
.wID
- 1;
696 void WINAPI
_InsertMenuItemW (
708 ZeroMemory(&mii
, sizeof(mii
));
709 mii
.cbSize
= sizeof(mii
);
710 if (fType
== MFT_SEPARATOR
)
712 mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
714 else if (fType
== MFT_STRING
)
716 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
717 if ((ULONG_PTR
)HIWORD((ULONG_PTR
)dwTypeData
) == 0)
719 if (LoadStringW(shell32_hInstance
, LOWORD((ULONG_PTR
)dwTypeData
), szText
, sizeof(szText
)/sizeof(WCHAR
)))
721 szText
[(sizeof(szText
)/sizeof(WCHAR
))-1] = 0;
722 mii
.dwTypeData
= szText
;
726 TRACE("failed to load string %p\n", dwTypeData
);
732 mii
.dwTypeData
= (LPWSTR
) dwTypeData
;
739 InsertMenuItemW( hmenu
, indexMenu
, fByPosition
, &mii
);
743 BuildShellItemContextMenu(
744 IDefaultContextMenuImpl
* This
,
750 WCHAR szPath
[MAX_PATH
];
763 TRACE("BuildShellItemContextMenu entered\n");
765 if (IShellFolder2_GetDisplayNameOf(This
->dcm
.psf
, This
->dcm
.apidl
[0], SHGDN_FORPARSING
, &strFile
) == S_OK
)
767 if (StrRetToBufW(&strFile
, This
->dcm
.apidl
[0], szPath
, MAX_PATH
) == S_OK
)
769 pOffset
= wcsrchr(szPath
, L
'.');
772 /* enumerate dynamic/static for a given file class */
773 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, pOffset
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
775 /* add static verbs */
776 SH_AddStaticEntryForFileClass(This
, pOffset
);
777 /* load dynamic extensions from file extension key */
778 EnumerateDynamicContextHandlerForKey(This
, hKey
);
781 dwSize
= sizeof(szTemp
);
782 if (RegGetValueW(HKEY_CLASSES_ROOT
, pOffset
, NULL
, RRF_RT_REG_SZ
, NULL
, szTemp
, &dwSize
) == ERROR_SUCCESS
)
784 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
786 /* add static verbs from progid key */
787 SH_AddStaticEntryForFileClass(This
, szTemp
);
788 /* load dynamic extensions from progid key */
789 EnumerateDynamicContextHandlerForKey(This
, hKey
);
794 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"*", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
796 /* load default extensions */
797 EnumerateDynamicContextHandlerForKey(This
, hKey
);
803 guid
= _ILGetGUIDPointer(This
->dcm
.apidl
[0]);
809 wcscpy(buffer
, L
"CLSID\\");
810 hr
= StringFromCLSID(guid
, &pwszCLSID
);
813 wcscpy(&buffer
[6], pwszCLSID
);
814 TRACE("buffer %s\n", debugstr_w(buffer
));
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
817 EnumerateDynamicContextHandlerForKey(This
, hKey
);
818 SH_AddStaticEntryForFileClass(This
, buffer
);
821 CoTaskMemFree(pwszCLSID
);
826 if (_ILIsDrive(This
->dcm
.apidl
[0]))
828 SH_AddStaticEntryForFileClass(This
, L
"Drive");
829 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Drive", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
831 EnumerateDynamicContextHandlerForKey(This
, hKey
);
837 /* add static actions */
838 rfg
= SFGAO_BROWSABLE
| SFGAO_CANCOPY
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANDELETE
| SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
;
839 hr
= IShellFolder_GetAttributesOf(This
->dcm
.psf
, This
->dcm
.cidl
, This
->dcm
.apidl
, &rfg
);
843 if (rfg
& SFGAO_FOLDER
)
845 /* add the default verbs open / explore */
846 SH_AddStaticEntryForFileClass(This
, L
"Folder");
847 SH_AddStaticEntryForFileClass(This
, L
"Directory");
848 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Folder", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
850 EnumerateDynamicContextHandlerForKey(This
, hKey
);
853 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"Directory", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
855 EnumerateDynamicContextHandlerForKey(This
, hKey
);
861 if (rfg
& SFGAO_FILESYSTEM
)
863 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, L
"AllFilesystemObjects", 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
865 /* sendto service is registered here */
866 EnumerateDynamicContextHandlerForKey(This
, hKey
);
871 /* add static context menu handlers */
872 indexMenu
= AddStaticContextMenusToMenu(hMenu
, 0, This
);
873 /* now process dynamic context menu handlers */
874 indexMenu
= InsertMenuItemsOfDynamicContextMenuExtension(This
, hMenu
, indexMenu
, iIdCmdFirst
, iIdCmdLast
);
875 TRACE("indexMenu %d\n", indexMenu
);
877 if (_ILIsDrive(This
->dcm
.apidl
[0]))
879 /* The 'Format' option must be always available,
880 * thus it is not registered as a static shell extension
882 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
883 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0x7ABC, MFT_STRING
, MAKEINTRESOURCEW(IDS_FORMATDRIVE
), MFS_ENABLED
);
887 bClipboardData
= (HasClipboardData() && (rfg
& SFGAO_FILESYSTEM
));
888 if (rfg
& (SFGAO_CANCOPY
| SFGAO_CANMOVE
) || bClipboardData
)
890 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
891 if (rfg
& SFGAO_CANMOVE
)
892 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_CUT
, MFT_STRING
, MAKEINTRESOURCEW(IDS_CUT
), MFS_ENABLED
);
893 if (rfg
& SFGAO_CANCOPY
)
894 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_COPY
, MFT_STRING
, MAKEINTRESOURCEW(IDS_COPY
), MFS_ENABLED
);
896 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_INSERT
, MFT_STRING
, MAKEINTRESOURCEW(IDS_INSERT
), MFS_ENABLED
);
902 if (rfg
& SFGAO_CANLINK
)
905 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
906 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_CREATELINK
, MFT_STRING
, MAKEINTRESOURCEW(IDS_CREATELINK
), MFS_ENABLED
);
910 if (rfg
& SFGAO_CANDELETE
)
915 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
917 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_DELETE
, MFT_STRING
, MAKEINTRESOURCEW(IDS_DELETE
), MFS_ENABLED
);
920 if (rfg
& SFGAO_CANRENAME
)
924 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
926 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_RENAME
, MFT_STRING
, MAKEINTRESOURCEW(IDS_RENAME
), MFS_ENABLED
);
930 if (rfg
& SFGAO_HASPROPSHEET
)
932 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
933 _InsertMenuItemW(hMenu
, indexMenu
++, TRUE
, FCIDM_SHVIEW_PROPERTIES
, MFT_STRING
, MAKEINTRESOURCEW(IDS_PROPERTIES
), MFS_ENABLED
);
942 IDefaultContextMenu_fnQueryContextMenu(
943 IContextMenu2
*iface
,
950 IDefaultContextMenuImpl
* This
= impl_from_IContextMenu(iface
);
953 idCmdFirst
= BuildShellItemContextMenu(This
, hmenu
, idCmdFirst
, idCmdLast
, uFlags
);
957 idCmdFirst
= BuildBackgroundContextMenu(This
, hmenu
, idCmdFirst
, idCmdLast
, uFlags
);
965 NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi
, BOOL bRefresh
)
968 LPSHELLVIEW lpSV
= NULL
;
971 if((lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0)))
973 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
)))
975 IShellView_GetWindow(lpSV
, &hwndSV
);
979 if (LOWORD(lpcmi
->lpVerb
) == FCIDM_SHVIEW_REFRESH
|| bRefresh
)
982 IShellView_Refresh(lpSV
);
987 SendMessageW(hwndSV
, WM_COMMAND
, MAKEWPARAM(LOWORD(lpcmi
->lpVerb
), 0), 0);
995 IDefaultContextMenuImpl
*This
,
996 LPCMINVOKECOMMANDINFO lpcmi
)
1000 FORMATETC formatetc
;
1001 LPITEMIDLIST
* apidl
;
1003 IShellFolder
*psfFrom
= NULL
, *psfDesktop
, *psfTarget
= NULL
;
1005 ISFHelper
*psfhlpdst
, *psfhlpsrc
;
1008 if (OleGetClipboard(&pda
) != S_OK
)
1011 InitFormatEtc(formatetc
, RegisterClipboardFormatA(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1012 hr
= IDataObject_GetData(pda
,&formatetc
,&medium
);
1016 IDataObject_Release(pda
);
1020 /* lock the handle */
1021 lpcida
= GlobalLock(medium
.u
.hGlobal
);
1024 ReleaseStgMedium(&medium
);
1025 IDataObject_Release(pda
);
1029 /* convert the data into pidl */
1030 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1035 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
1038 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1039 ReleaseStgMedium(&medium
);
1040 IDataObject_Release(pda
);
1044 if (FAILED(IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfFrom
)))
1046 ERR("no IShellFolder\n");
1048 IShellFolder_Release(psfDesktop
);
1050 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1051 ReleaseStgMedium(&medium
);
1052 IDataObject_Release(pda
);
1057 IShellFolder_Release(psfDesktop
);
1059 if (FAILED(IShellFolder_BindToObject(This
->dcm
.psf
, This
->dcm
.apidl
[0], NULL
, &IID_IShellFolder
, (LPVOID
*)&psfTarget
)))
1061 ERR("no IShellFolder\n");
1063 IShellFolder_Release(psfFrom
);
1065 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1066 ReleaseStgMedium(&medium
);
1067 IDataObject_Release(pda
);
1073 /* get source and destination shellfolder */
1074 if (FAILED(IShellFolder_QueryInterface(psfTarget
, &IID_ISFHelper
, (LPVOID
*)&psfhlpdst
)))
1076 ERR("no IID_ISFHelper for destination\n");
1078 IShellFolder_Release(psfFrom
);
1079 IShellFolder_Release(psfTarget
);
1081 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1082 ReleaseStgMedium(&medium
);
1083 IDataObject_Release(pda
);
1088 if (FAILED(IShellFolder_QueryInterface(psfFrom
, &IID_ISFHelper
, (LPVOID
*)&psfhlpsrc
)))
1090 ERR("no IID_ISFHelper for source\n");
1092 ISFHelper_Release(psfhlpdst
);
1093 IShellFolder_Release(psfFrom
);
1094 IShellFolder_Release(psfTarget
);
1096 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1097 ReleaseStgMedium(&medium
);
1098 IDataObject_Release(pda
);
1103 * do we want to perform a copy or move ???
1105 hr
= ISFHelper_CopyItems(psfhlpdst
, psfFrom
, lpcida
->cidl
, (LPCITEMIDLIST
*)apidl
);
1107 ISFHelper_Release(psfhlpdst
);
1108 ISFHelper_Release(psfhlpsrc
);
1109 IShellFolder_Release(psfFrom
);
1110 IShellFolder_Release(psfTarget
);
1112 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1113 ReleaseStgMedium(&medium
);
1114 IDataObject_Release(pda
);
1121 IDefaultContextMenuImpl
*iface
,
1122 LPCMINVOKECOMMANDINFO lpcmi
)
1130 GetUniqueFileName(LPWSTR szBasePath
, LPWSTR szExt
, LPWSTR szTarget
, BOOL bShortcut
)
1132 UINT RetryCount
= 0, Length
;
1138 Length
= LoadStringW(shell32_hInstance
, IDS_LNK_FILE
, szLnk
, sizeof(szLnk
)/sizeof(WCHAR
));
1146 swprintf(szTarget
, L
"%s%s(%u).%s", szLnk
, szBasePath
, RetryCount
, szExt
);
1148 swprintf(szTarget
, L
"%s%s.%s", szLnk
, szBasePath
, szExt
);
1153 swprintf(szTarget
, L
"%s(%u).%s", szBasePath
, RetryCount
, szExt
);
1155 swprintf(szTarget
, L
"%s.%s", szBasePath
, szExt
);
1158 hFile
= CreateFileW(szTarget
, GENERIC_WRITE
, 0, NULL
, CREATE_NEW
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1159 if (hFile
!= INVALID_HANDLE_VALUE
)
1165 }while(RetryCount
++ < 100);
1174 IDefaultContextMenuImpl
*This
,
1175 LPCMINVOKECOMMANDINFO lpcmi
)
1177 WCHAR szPath
[MAX_PATH
];
1178 WCHAR szTarget
[MAX_PATH
] = {0};
1182 IShellLinkW
* nLink
;
1184 static WCHAR szLnk
[] = L
"lnk";
1186 if (IShellFolder2_GetDisplayNameOf(This
->dcm
.psf
, This
->dcm
.apidl
[0], SHGDN_FORPARSING
, &strFile
) != S_OK
)
1188 ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
1192 if (StrRetToBufW(&strFile
, This
->dcm
.apidl
[0], szPath
, MAX_PATH
) != S_OK
)
1196 pszExt
= wcsrchr(szPath
, L
'.');
1199 if (!wcsicmp(pszExt
+ 1, szLnk
))
1201 if (!GetUniqueFileName(szPath
, pszExt
+ 1, szTarget
, TRUE
))
1204 hr
= IShellLink_ConstructFromFile(NULL
, &IID_IPersistFile
, This
->dcm
.apidl
[0], (LPVOID
*)&ipf
);
1209 hr
= IPersistFile_Save(ipf
, szTarget
, FALSE
);
1210 IPersistFile_Release(ipf
);
1211 NotifyShellViewWindow(lpcmi
, TRUE
);
1216 if (!GetUniqueFileName(szPath
, szLnk
, szTarget
, TRUE
))
1219 hr
= IShellLink_Constructor(NULL
, &IID_IShellLinkW
, (LPVOID
*)&nLink
);
1225 if (SUCCEEDED(IShellLinkW_SetPath(nLink
, szPath
)))
1227 if (SUCCEEDED(IShellLinkW_QueryInterface(nLink
, &IID_IPersistFile
, (LPVOID
*)&ipf
)))
1229 hr
= IPersistFile_Save(ipf
, szTarget
, TRUE
);
1230 IPersistFile_Release(ipf
);
1233 IShellLinkW_Release(nLink
);
1234 NotifyShellViewWindow(lpcmi
, TRUE
);
1242 IDefaultContextMenuImpl
*This
,
1243 LPCMINVOKECOMMANDINFO lpcmi
)
1247 WCHAR szPath
[MAX_PATH
];
1250 LPSHELLBROWSER lpSB
;
1254 hr
= IShellFolder2_GetDisplayNameOf(This
->dcm
.psf
, This
->dcm
.apidl
[0], SHGDN_FORPARSING
, &strTemp
);
1257 ERR("IShellFolder_GetDisplayNameOf failed with %x\n", hr
);
1260 ZeroMemory(szPath
, sizeof(szPath
));
1261 hr
= StrRetToBufW(&strTemp
, This
->dcm
.apidl
[0], szPath
, MAX_PATH
);
1264 ERR("StrRetToBufW failed with %x\n", hr
);
1268 * implement deletion with multiple files
1271 ZeroMemory(&op
, sizeof(op
));
1272 op
.hwnd
= GetActiveWindow();
1273 op
.wFunc
= FO_DELETE
;
1275 op
.fFlags
= FOF_ALLOWUNDO
;
1276 ret
= SHFileOperationW(&op
);
1280 TRACE("SHFileOperation failed with %0x%x", GetLastError());
1284 /* get the active IShellView */
1285 if ((lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0)))
1287 /* is the treeview focused */
1288 if (SUCCEEDED(IShellBrowser_GetControlWindow(lpSB
, FCW_TREE
, &hwnd
)))
1290 HTREEITEM hItem
= TreeView_GetSelection(hwnd
);
1293 (void)TreeView_DeleteItem(hwnd
, hItem
);
1297 NotifyShellViewWindow(lpcmi
, TRUE
);
1306 IDefaultContextMenuImpl
*iface
,
1307 LPCMINVOKECOMMANDINFO lpcmi
,
1310 LPSHELLBROWSER lpSB
;
1315 lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
1318 TRACE("failed to get shellbrowser\n");
1322 hr
= IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
);
1325 TRACE("failed to query the active shellview\n");
1329 hr
= IShellView_GetItemObject(lpSV
, SVGIO_SELECTION
, &IID_IDataObject
, (LPVOID
*)&lpDo
);
1332 TRACE("failed to get item object\n");
1336 hr
= OleSetClipboard(lpDo
);
1339 WARN("OleSetClipboard failed");
1341 IDataObject_Release(lpDo
);
1342 IShellView_Release(lpSV
);
1349 IDefaultContextMenuImpl
*This
,
1350 LPCMINVOKECOMMANDINFO lpcmi
)
1352 LPSHELLBROWSER lpSB
;
1356 /* get the active IShellView */
1357 if ((lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0)))
1359 /* is the treeview focused */
1360 if (SUCCEEDED(IShellBrowser_GetControlWindow(lpSB
, FCW_TREE
, &hwnd
)))
1362 HTREEITEM hItem
= TreeView_GetSelection(hwnd
);
1365 (void)TreeView_EditLabel(hwnd
, hItem
);
1369 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
)))
1371 IShellView_SelectItem(lpSV
, This
->dcm
.apidl
[0],
1372 SVSI_DESELECTOTHERS
|SVSI_EDIT
|SVSI_ENSUREVISIBLE
|SVSI_FOCUSED
|SVSI_SELECT
);
1373 IShellView_Release(lpSV
);
1383 IDefaultContextMenuImpl
*This
,
1384 LPCMINVOKECOMMANDINFO lpcmi
)
1386 WCHAR szDrive
[MAX_PATH
];
1389 if (This
->dcm
.cidl
&&_ILIsMyComputer(This
->dcm
.apidl
[0]))
1391 ShellExecuteW(lpcmi
->hwnd
, L
"open", L
"rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
1394 else if (This
->dcm
.cidl
== 0 && _ILIsDesktop(This
->dcm
.pidlFolder
))
1396 ShellExecuteW(lpcmi
->hwnd
, L
"open", L
"rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
1399 else if (_ILIsDrive(This
->dcm
.apidl
[0]))
1401 ILGetDisplayName(This
->dcm
.apidl
[0], szDrive
);
1402 SH_ShowDriveProperties(szDrive
, This
->dcm
.pidlFolder
, This
->dcm
.apidl
);
1405 else if (_ILIsNetHood(This
->dcm
.apidl
[0]))
1408 * implement nethood properties
1410 FIXME("implement network connection shell folder\n");
1413 else if (_ILIsBitBucket(This
->dcm
.apidl
[0]))
1416 * detect the drive path of bitbucket if appropiate
1419 SH_ShowRecycleBinProperties(L
'C');
1423 if (This
->dcm
.cidl
> 1)
1424 WARN("SHMultiFileProperties is not yet implemented\n");
1426 if (IShellFolder2_GetDisplayNameOf(This
->dcm
.psf
, This
->dcm
.apidl
[0], SHGDN_FORPARSING
, &strFile
) != S_OK
)
1428 ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
1432 if (StrRetToBufW(&strFile
, This
->dcm
.apidl
[0], szDrive
, MAX_PATH
) != S_OK
)
1435 return SH_ShowPropertiesDialog(szDrive
, This
->dcm
.pidlFolder
, This
->dcm
.apidl
);
1441 IDefaultContextMenuImpl
*This
,
1442 LPCMINVOKECOMMANDINFO lpcmi
)
1444 char sDrive
[5] = {0};
1446 if (!_ILGetDrive(This
->dcm
.apidl
[0], sDrive
, sizeof(sDrive
)))
1448 ERR("pidl is not a drive\n");
1452 SHFormatDrive(lpcmi
->hwnd
, sDrive
[0] - 'A', SHFMT_ID_DEFAULT
, 0);
1458 DoDynamicShellExtensions(
1459 IDefaultContextMenuImpl
*This
,
1460 LPCMINVOKECOMMANDINFO lpcmi
)
1462 UINT verb
= LOWORD(lpcmi
->lpVerb
);
1463 PDynamicShellEntry pCurrent
= This
->dhead
;
1465 TRACE("verb %p first %x last %x", lpcmi
->lpVerb
, This
->iIdSHEFirst
, This
->iIdSHELast
);
1467 while(pCurrent
&& verb
> pCurrent
->iIdCmdFirst
+ pCurrent
->NumIds
)
1468 pCurrent
= pCurrent
->Next
;
1473 if (verb
>= pCurrent
->iIdCmdFirst
&& verb
<= pCurrent
->iIdCmdFirst
+ pCurrent
->NumIds
)
1475 /* invoke the dynamic context menu */
1476 lpcmi
->lpVerb
= MAKEINTRESOURCEA(verb
- pCurrent
->iIdCmdFirst
);
1477 return IContextMenu_InvokeCommand(pCurrent
->CMenu
, lpcmi
);
1486 DoStaticShellExtensions(
1487 IDefaultContextMenuImpl
*This
,
1488 LPCMINVOKECOMMANDINFO lpcmi
)
1491 WCHAR szPath
[MAX_PATH
];
1492 SHELLEXECUTEINFOW sei
;
1493 PStaticShellEntry pCurrent
= This
->shead
;
1494 int verb
= LOWORD(lpcmi
->lpVerb
) - This
->iIdSCMFirst
;
1497 while(pCurrent
&& verb
-- > 0)
1498 pCurrent
= pCurrent
->Next
;
1504 if (IShellFolder2_GetDisplayNameOf(This
->dcm
.psf
, This
->dcm
.apidl
[0], SHGDN_FORPARSING
, &strFile
) != S_OK
)
1506 ERR("IShellFolder_GetDisplayNameOf failed for apidl\n");
1510 if (StrRetToBufW(&strFile
, This
->dcm
.apidl
[0], szPath
, MAX_PATH
) != S_OK
)
1514 ZeroMemory(&sei
, sizeof(sei
));
1515 sei
.cbSize
= sizeof(sei
);
1516 sei
.fMask
= SEE_MASK_CLASSNAME
;
1517 sei
.lpClass
= pCurrent
->szClass
;
1518 sei
.hwnd
= lpcmi
->hwnd
;
1519 sei
.nShow
= SW_SHOWNORMAL
;
1520 sei
.lpVerb
= pCurrent
->szVerb
;
1521 sei
.lpFile
= szPath
;
1522 ShellExecuteExW(&sei
);
1530 IDefaultContextMenu_fnInvokeCommand(
1531 IContextMenu2
*iface
,
1532 LPCMINVOKECOMMANDINFO lpcmi
)
1534 IDefaultContextMenuImpl
* This
= impl_from_IContextMenu(iface
);
1536 switch(LOWORD(lpcmi
->lpVerb
))
1538 case FCIDM_SHVIEW_BIGICON
:
1539 case FCIDM_SHVIEW_SMALLICON
:
1540 case FCIDM_SHVIEW_LISTVIEW
:
1541 case FCIDM_SHVIEW_REPORTVIEW
:
1542 case 0x30: /* FIX IDS in resource files */
1546 case FCIDM_SHVIEW_AUTOARRANGE
:
1547 case FCIDM_SHVIEW_SNAPTOGRID
:
1548 case FCIDM_SHVIEW_REFRESH
:
1549 return NotifyShellViewWindow(lpcmi
, FALSE
);
1550 case FCIDM_SHVIEW_INSERT
:
1551 case FCIDM_SHVIEW_INSERTLINK
:
1552 return DoPaste(This
, lpcmi
);
1553 case FCIDM_SHVIEW_OPEN
:
1554 case FCIDM_SHVIEW_EXPLORE
:
1555 return DoOpenOrExplore(This
, lpcmi
);
1556 case FCIDM_SHVIEW_COPY
:
1557 case FCIDM_SHVIEW_CUT
:
1558 return DoCopyOrCut(This
, lpcmi
, LOWORD(lpcmi
->lpVerb
) == FCIDM_SHVIEW_COPY
);
1559 case FCIDM_SHVIEW_CREATELINK
:
1560 return DoCreateLink(This
, lpcmi
);
1561 case FCIDM_SHVIEW_DELETE
:
1562 return DoDelete(This
, lpcmi
);
1563 case FCIDM_SHVIEW_RENAME
:
1564 return DoRename(This
, lpcmi
);
1565 case FCIDM_SHVIEW_PROPERTIES
:
1566 return DoProperties(This
, lpcmi
);
1568 return DoFormat(This
, lpcmi
);
1571 if (This
->iIdSHEFirst
&& This
->iIdSHELast
)
1573 if (LOWORD(lpcmi
->lpVerb
) >= This
->iIdSHEFirst
&& LOWORD(lpcmi
->lpVerb
) <= This
->iIdSHELast
)
1575 return DoDynamicShellExtensions(This
, lpcmi
);
1579 if (This
->iIdSCMFirst
&& This
->iIdSCMLast
)
1581 if (LOWORD(lpcmi
->lpVerb
) >= This
->iIdSCMFirst
&& LOWORD(lpcmi
->lpVerb
) <= This
->iIdSCMLast
)
1583 return DoStaticShellExtensions(This
, lpcmi
);
1587 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi
->lpVerb
));
1588 return E_UNEXPECTED
;
1594 IDefaultContextMenu_fnGetCommandString(
1595 IContextMenu2
*iface
,
1609 IDefaultContextMenu_fnHandleMenuMsg(
1610 IContextMenu2
*iface
,
1619 static const IContextMenu2Vtbl cmvt
=
1621 IDefaultContextMenu_fnQueryInterface
,
1622 IDefaultContextMenu_fnAddRef
,
1623 IDefaultContextMenu_fnRelease
,
1624 IDefaultContextMenu_fnQueryContextMenu
,
1625 IDefaultContextMenu_fnInvokeCommand
,
1626 IDefaultContextMenu_fnGetCommandString
,
1627 IDefaultContextMenu_fnHandleMenuMsg
1631 IDefaultContextMenu_Constructor(
1632 const DEFCONTEXTMENU
*pdcm
,
1636 IDefaultContextMenuImpl
* This
;
1637 HRESULT hr
= E_FAIL
;
1638 IDataObject
* pDataObj
;
1640 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDefaultContextMenuImpl
));
1643 This
->lpVtbl
= &cmvt
;
1645 TRACE("cidl %u\n", This
->dcm
.cidl
);
1646 if (SUCCEEDED(SHCreateDataObject(pdcm
->pidlFolder
, pdcm
->cidl
, pdcm
->apidl
, NULL
, &IID_IDataObject
, (void**)&pDataObj
)))
1648 This
->pDataObj
= pDataObj
;
1650 CopyMemory(&This
->dcm
, pdcm
, sizeof(DEFCONTEXTMENU
));
1651 hr
= IDefaultContextMenu_fnQueryInterface((IContextMenu2
*)This
, riid
, ppv
);
1653 IContextMenu_Release((IContextMenu2
*)This
);
1656 TRACE("This(%p)(%x) cidl %u\n",This
, hr
, This
->dcm
.cidl
);
1660 /*************************************************************************
1661 * SHCreateDefaultContextMenu [SHELL32.325] Vista API
1667 SHCreateDefaultContextMenu(
1668 const DEFCONTEXTMENU
*pdcm
,
1672 HRESULT hr
= E_FAIL
;
1675 hr
= IDefaultContextMenu_Constructor( pdcm
, riid
, ppv
);
1677 TRACE("pcm %p hr %x\n", pdcm
, hr
);
1681 /*************************************************************************
1682 * CDefFolderMenu_Create2 [SHELL32.701]
1688 CDefFolderMenu_Create2(
1689 LPCITEMIDLIST pidlFolder
,
1692 LPCITEMIDLIST
*apidl
,
1694 LPFNDFMCALLBACK lpfn
,
1696 const HKEY
*ahkeyClsKeys
,
1697 IContextMenu
**ppcm
)
1699 DEFCONTEXTMENU pdcm
;
1704 pdcm
.pidlFolder
= pidlFolder
;
1708 pdcm
.punkAssociationInfo
= NULL
;
1710 pdcm
.aKeys
= ahkeyClsKeys
;
1712 hr
= SHCreateDefaultContextMenu(&pdcm
, &IID_IContextMenu
, (void**)ppcm
);