4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
12 #include "wine/obj_base.h"
13 #include "wine/obj_contextmenu.h"
14 #include "wine/obj_shellbrowser.h"
15 #include "wine/obj_shellextinit.h"
17 #include "shell32_main.h"
19 DEFAULT_DEBUG_CHANNEL(shell
)
21 /**************************************************************************
22 * IContextMenu Implementation
25 { ICOM_VTABLE(IContextMenu
)* lpvtbl
;
27 IShellFolder
* pSFParent
;
33 static struct ICOM_VTABLE(IContextMenu
) cmvt
;
35 /**************************************************************************
36 * IContextMenu_AllocPidlTable()
38 BOOL
IContextMenu_AllocPidlTable(IContextMenuImpl
*This
, DWORD dwEntries
)
40 TRACE(shell
,"(%p)->(entrys=%lu)\n",This
, dwEntries
);
42 /*add one for NULL terminator */
45 This
->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
48 { ZeroMemory(This
->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
50 return (This
->aPidls
!= NULL
);
53 /**************************************************************************
54 * IContextMenu_FreePidlTable()
56 void IContextMenu_FreePidlTable(IContextMenuImpl
*This
)
60 TRACE(shell
,"(%p)->()\n",This
);
63 { for(i
= 0; This
->aPidls
[i
]; i
++)
64 { SHFree(This
->aPidls
[i
]);
72 /**************************************************************************
73 * IContextMenu_FillPidlTable()
75 BOOL
IContextMenu_FillPidlTable(IContextMenuImpl
*This
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
79 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",This
, aPidls
, uItemCount
);
82 { for(i
= 0; i
< uItemCount
; i
++)
83 { This
->aPidls
[i
] = ILClone(aPidls
[i
]);
90 /**************************************************************************
91 * IContextMenu_CanRenameItems()
93 BOOL
IContextMenu_CanRenameItems(IContextMenuImpl
*This
)
97 TRACE(shell
,"(%p)->()\n",This
);
101 for(i
= 0; This
->aPidls
[i
]; i
++){} /*get the number of items assigned to This object*/
102 { if(i
> 1) /*you can't rename more than one item at a time*/
106 dwAttributes
= SFGAO_CANRENAME
;
107 IShellFolder_GetAttributesOf(This
->pSFParent
, i
, (LPCITEMIDLIST
*)This
->aPidls
, &dwAttributes
);
109 return dwAttributes
& SFGAO_CANRENAME
;
114 /**************************************************************************
115 * IContextMenu_Constructor()
117 IContextMenu
*IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
118 { IContextMenuImpl
* cm
;
121 cm
= (IContextMenuImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl
));
125 cm
->pSFParent
= pSFParent
;
127 IShellFolder_AddRef(pSFParent
);
131 IContextMenu_AllocPidlTable(cm
, uItemCount
);
134 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
138 for(u
= 0; u
< uItemCount
; u
++)
139 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
141 TRACE(shell
,"(%p)->()\n",cm
);
143 return (IContextMenu
*)cm
;
146 /**************************************************************************
147 * IContextMenu_fnQueryInterface
149 static HRESULT WINAPI
IContextMenu_fnQueryInterface(IContextMenu
*iface
, REFIID riid
, LPVOID
*ppvObj
)
151 ICOM_THIS(IContextMenuImpl
, iface
);
154 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
156 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",This
,xriid
,ppvObj
);
160 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
163 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
166 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
167 { FIXME (shell
,"-- LPSHELLEXTINIT pointer requested\n");
172 IContextMenu_AddRef((IContextMenu
*)*ppvObj
);
173 TRACE(shell
,"-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
176 TRACE(shell
,"-- Interface: E_NOINTERFACE\n");
177 return E_NOINTERFACE
;
180 /**************************************************************************
181 * IContextMenu_fnAddRef
183 static ULONG WINAPI
IContextMenu_fnAddRef(IContextMenu
*iface
)
185 ICOM_THIS(IContextMenuImpl
, iface
);
187 TRACE(shell
,"(%p)->(count=%lu)\n",This
, This
->ref
);
190 return ++(This
->ref
);
193 /**************************************************************************
194 * IContextMenu_fnRelease
196 static ULONG WINAPI
IContextMenu_fnRelease(IContextMenu
*iface
)
198 ICOM_THIS(IContextMenuImpl
, iface
);
200 TRACE(shell
,"(%p)->()\n",This
);
205 { TRACE(shell
," destroying IContextMenu(%p)\n",This
);
208 IShellFolder_Release(This
->pSFParent
);
210 /*make sure the pidl is freed*/
212 { IContextMenu_FreePidlTable(This
);
215 HeapFree(GetProcessHeap(),0,This
);
221 /**************************************************************************
224 void WINAPI
_InsertMenuItem (
235 ZeroMemory(&mii
, sizeof(mii
));
236 mii
.cbSize
= sizeof(mii
);
237 if (fType
== MFT_SEPARATOR
)
238 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
241 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
242 mii
.dwTypeData
= dwTypeData
;
243 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
247 InsertMenuItemA( hmenu
, indexMenu
, fByPosition
, &mii
);
249 /**************************************************************************
250 * IContextMenu_fnQueryContextMenu()
253 static HRESULT WINAPI
IContextMenu_fnQueryContextMenu(
261 ICOM_THIS(IContextMenuImpl
, iface
);
265 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This
, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
267 if(!(CMF_DEFAULTONLY
& uFlags
))
268 { if(!This
->bAllValues
)
270 fExplore
= uFlags
& CMF_EXPLORE
;
272 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
|MFS_DEFAULT
);
273 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
);
276 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
277 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
);
280 if(uFlags
& CMF_CANRENAME
)
281 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
282 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
));
286 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
287 if(uFlags
& CMF_CANRENAME
)
288 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
289 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
));
292 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
294 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
297 /**************************************************************************
298 * IContextMenu_fnInvokeCommand()
300 static HRESULT WINAPI
IContextMenu_fnInvokeCommand(
302 LPCMINVOKECOMMANDINFO lpcmi
)
304 ICOM_THIS(IContextMenuImpl
, iface
);
306 LPITEMIDLIST pidlTemp
,pidlFQ
;
310 SHELLEXECUTEINFOA sei
;
313 TRACE(shell
,"(%p)->(invcom=%p verb=%p wnd=%x)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
315 if(HIWORD(lpcmi
->lpVerb
))
316 { /* get the active IShellView */
317 lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
318 IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
); /* does AddRef() on lpSV */
319 IShellView_GetWindow(lpSV
, &hWndSV
);
321 /* these verbs are used by the filedialogs*/
322 TRACE(shell
,"%s\n",lpcmi
->lpVerb
);
323 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDER
))
324 { FIXME(shell
,"%s not implemented\n",lpcmi
->lpVerb
);
326 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLIST
))
327 { SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
329 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILS
))
330 { SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
333 { FIXME(shell
,"please report: unknown verb %s\n",lpcmi
->lpVerb
);
335 IShellView_Release(lpSV
);
339 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
342 switch(LOWORD(lpcmi
->lpVerb
))
345 /* Find the first item in the list that is not a value. These commands
346 should never be invoked if there isn't at least one folder item in the list.*/
348 for(i
= 0; This
->aPidls
[i
]; i
++)
349 { if(!_ILIsValue(This
->aPidls
[i
]))
353 pidlTemp
= ILCombine(((IGenericSFImpl
*)(This
->pSFParent
))->mpidl
, This
->aPidls
[i
]);
354 pidlFQ
= ILCombine(((IGenericSFImpl
*)(This
->pSFParent
))->pMyPidl
, pidlTemp
);
357 ZeroMemory(&sei
, sizeof(sei
));
358 sei
.cbSize
= sizeof(sei
);
359 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
360 sei
.lpIDList
= pidlFQ
;
361 sei
.lpClass
= "folder";
362 sei
.hwnd
= lpcmi
->hwnd
;
363 sei
.nShow
= SW_SHOWNORMAL
;
365 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
366 { sei
.lpVerb
= "explore";
369 { sei
.lpVerb
= "open";
371 ShellExecuteExA(&sei
);
377 /*handle rename for the view here*/
383 /**************************************************************************
384 * IContextMenu_fnGetCommandString()
386 static HRESULT WINAPI
IContextMenu_fnGetCommandString(
394 ICOM_THIS(IContextMenuImpl
, iface
);
396 HRESULT hr
= E_INVALIDARG
;
398 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
408 strcpy((LPSTR
)lpszName
, "rename");
414 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
415 case, you need to do the lstrcpyW to the pointer passed.*/
419 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
429 TRACE(shell
,"-- (%p)->(name=%s)\n",This
, lpszName
);
433 /**************************************************************************
434 * IContextMenu_fnHandleMenuMsg()
436 * should be only in IContextMenu2 and IContextMenu3
437 * is nevertheless called from word95
439 static HRESULT WINAPI
IContextMenu_fnHandleMenuMsg(
445 ICOM_THIS(IContextMenuImpl
, iface
);
447 TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
452 /**************************************************************************
453 * IContextMenu VTable
456 static struct ICOM_VTABLE(IContextMenu
) cmvt
=
458 IContextMenu_fnQueryInterface
,
459 IContextMenu_fnAddRef
,
460 IContextMenu_fnRelease
,
461 IContextMenu_fnQueryContextMenu
,
462 IContextMenu_fnInvokeCommand
,
463 IContextMenu_fnGetCommandString
,
464 IContextMenu_fnHandleMenuMsg
,
465 (void *) 0xdeadbabe /* just paranoia */