4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
9 #include "debugtools.h"
12 #include "wine/obj_base.h"
13 #include "wine/obj_contextmenu.h"
14 #include "wine/obj_shellbrowser.h"
15 #include "wine/obj_shellextinit.h"
16 #include "wine/undocshell.h"
18 #include "shell32_main.h"
20 DEFAULT_DEBUG_CHANNEL(shell
)
22 /**************************************************************************
23 * IContextMenu Implementation
26 { ICOM_VTABLE(IContextMenu
)* lpvtbl
;
28 IShellFolder
* pSFParent
;
29 LPITEMIDLIST pidl
; /* root pidl */
30 LPITEMIDLIST
*aPidls
; /* array of child pidls */
35 static struct ICOM_VTABLE(IContextMenu
) cmvt
;
37 /**************************************************************************
38 * IContextMenu_AllocPidlTable()
40 BOOL
IContextMenu_AllocPidlTable(IContextMenuImpl
*This
, DWORD dwEntries
)
42 TRACE("(%p)->(entrys=%lu)\n",This
, dwEntries
);
44 /*add one for NULL terminator */
47 This
->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
50 { ZeroMemory(This
->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
52 return (This
->aPidls
!= NULL
);
55 /**************************************************************************
56 * IContextMenu_FreePidlTable()
58 void IContextMenu_FreePidlTable(IContextMenuImpl
*This
)
62 TRACE("(%p)->()\n",This
);
65 { for(i
= 0; This
->aPidls
[i
]; i
++)
66 { SHFree(This
->aPidls
[i
]);
74 /**************************************************************************
75 * IContextMenu_FillPidlTable()
77 BOOL
IContextMenu_FillPidlTable(IContextMenuImpl
*This
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
81 TRACE("(%p)->(apidl=%p count=%u)\n",This
, aPidls
, uItemCount
);
84 { for(i
= 0; i
< uItemCount
; i
++)
85 { This
->aPidls
[i
] = ILClone(aPidls
[i
]);
92 /**************************************************************************
93 * IContextMenu_CanRenameItems()
95 BOOL
IContextMenu_CanRenameItems(IContextMenuImpl
*This
)
99 TRACE("(%p)->()\n",This
);
103 for(i
= 0; This
->aPidls
[i
]; i
++){} /*get the number of items assigned to This object*/
104 { if(i
> 1) /*you can't rename more than one item at a time*/
108 dwAttributes
= SFGAO_CANRENAME
;
109 IShellFolder_GetAttributesOf(This
->pSFParent
, i
, (LPCITEMIDLIST
*)This
->aPidls
, &dwAttributes
);
111 return dwAttributes
& SFGAO_CANRENAME
;
116 /**************************************************************************
117 * IContextMenu_Constructor()
119 IContextMenu
*IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST pidl
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
120 { IContextMenuImpl
* cm
;
123 cm
= (IContextMenuImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl
));
126 cm
->pidl
= ILClone(pidl
);
128 cm
->pSFParent
= pSFParent
;
131 IShellFolder_AddRef(pSFParent
);
135 IContextMenu_AllocPidlTable(cm
, uItemCount
);
138 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
142 for(u
= 0; u
< uItemCount
; u
++)
143 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
145 TRACE("(%p)->()\n",cm
);
147 return (IContextMenu
*)cm
;
150 /**************************************************************************
151 * IContextMenu_fnQueryInterface
153 static HRESULT WINAPI
IContextMenu_fnQueryInterface(IContextMenu
*iface
, REFIID riid
, LPVOID
*ppvObj
)
155 ICOM_THIS(IContextMenuImpl
, iface
);
158 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
160 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,xriid
,ppvObj
);
164 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
167 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
170 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
171 { FIXME("-- LPSHELLEXTINIT pointer requested\n");
176 IContextMenu_AddRef((IContextMenu
*)*ppvObj
);
177 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
180 TRACE("-- Interface: E_NOINTERFACE\n");
181 return E_NOINTERFACE
;
184 /**************************************************************************
185 * IContextMenu_fnAddRef
187 static ULONG WINAPI
IContextMenu_fnAddRef(IContextMenu
*iface
)
189 ICOM_THIS(IContextMenuImpl
, iface
);
191 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
194 return ++(This
->ref
);
197 /**************************************************************************
198 * IContextMenu_fnRelease
200 static ULONG WINAPI
IContextMenu_fnRelease(IContextMenu
*iface
)
202 ICOM_THIS(IContextMenuImpl
, iface
);
204 TRACE("(%p)->()\n",This
);
209 { TRACE(" destroying IContextMenu(%p)\n",This
);
212 IShellFolder_Release(This
->pSFParent
);
217 /*make sure the pidl is freed*/
219 { IContextMenu_FreePidlTable(This
);
222 HeapFree(GetProcessHeap(),0,This
);
228 /**************************************************************************
231 void WINAPI
_InsertMenuItem (
242 ZeroMemory(&mii
, sizeof(mii
));
243 mii
.cbSize
= sizeof(mii
);
244 if (fType
== MFT_SEPARATOR
)
245 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
248 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
249 mii
.dwTypeData
= dwTypeData
;
254 InsertMenuItemA( hmenu
, indexMenu
, fByPosition
, &mii
);
256 /**************************************************************************
257 * IContextMenu_fnQueryContextMenu()
260 static HRESULT WINAPI
IContextMenu_fnQueryContextMenu(
268 ICOM_THIS(IContextMenuImpl
, iface
);
272 TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This
, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
274 if(!(CMF_DEFAULTONLY
& uFlags
))
275 { if(!This
->bAllValues
)
277 fExplore
= uFlags
& CMF_EXPLORE
;
279 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
|MFS_DEFAULT
);
280 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
);
283 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
284 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
);
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
));
293 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
294 if(uFlags
& CMF_CANRENAME
)
295 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
296 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
));
299 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
301 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
304 /**************************************************************************
305 * IContextMenu_fnInvokeCommand()
307 static HRESULT WINAPI
IContextMenu_fnInvokeCommand(
309 LPCMINVOKECOMMANDINFO lpcmi
)
311 ICOM_THIS(IContextMenuImpl
, iface
);
314 SHELLEXECUTEINFOA sei
;
317 TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
319 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
322 switch(LOWORD(lpcmi
->lpVerb
))
325 /* Find the first item in the list that is not a value. These commands
326 should never be invoked if there isn't at least one folder item in the list.*/
328 for(i
= 0; This
->aPidls
[i
]; i
++)
329 { if(!_ILIsValue(This
->aPidls
[i
]))
333 pidlFQ
= ILCombine(This
->pidl
, This
->aPidls
[i
]);
335 ZeroMemory(&sei
, sizeof(sei
));
336 sei
.cbSize
= sizeof(sei
);
337 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
338 sei
.lpIDList
= pidlFQ
;
339 sei
.lpClass
= "folder";
340 sei
.hwnd
= lpcmi
->hwnd
;
341 sei
.nShow
= SW_SHOWNORMAL
;
343 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
344 { sei
.lpVerb
= "explore";
347 { sei
.lpVerb
= "open";
349 ShellExecuteExA(&sei
);
355 /*handle rename for the view here*/
361 /**************************************************************************
362 * IContextMenu_fnGetCommandString()
364 static HRESULT WINAPI
IContextMenu_fnGetCommandString(
372 ICOM_THIS(IContextMenuImpl
, iface
);
374 HRESULT hr
= E_INVALIDARG
;
376 TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
386 strcpy((LPSTR
)lpszName
, "rename");
392 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
393 case, you need to do the lstrcpyW to the pointer passed.*/
397 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
407 TRACE("-- (%p)->(name=%s)\n",This
, lpszName
);
411 /**************************************************************************
412 * IContextMenu_fnHandleMenuMsg()
414 * should be only in IContextMenu2 and IContextMenu3
415 * is nevertheless called from word95
417 static HRESULT WINAPI
IContextMenu_fnHandleMenuMsg(
423 ICOM_THIS(IContextMenuImpl
, iface
);
425 TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
430 /**************************************************************************
431 * IContextMenu VTable
434 static struct ICOM_VTABLE(IContextMenu
) cmvt
=
436 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
437 IContextMenu_fnQueryInterface
,
438 IContextMenu_fnAddRef
,
439 IContextMenu_fnRelease
,
440 IContextMenu_fnQueryContextMenu
,
441 IContextMenu_fnInvokeCommand
,
442 IContextMenu_fnGetCommandString
,
443 IContextMenu_fnHandleMenuMsg
,
444 (void *) 0xdeadbabe /* just paranoia */