4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
12 #include "wine/obj_base.h"
13 #include "if_macros.h"
15 #include "shell32_main.h"
18 /**************************************************************************
19 * IContextMenu Implementation
22 { ICOM_VTABLE(IContextMenu
)* lpvtbl
;
24 LPSHELLFOLDER pSFParent
;
29 static HRESULT WINAPI
IContextMenu_fnQueryInterface(IContextMenu
*,REFIID
, LPVOID
*);
30 static ULONG WINAPI
IContextMenu_fnAddRef(IContextMenu
*);
31 static ULONG WINAPI
IContextMenu_fnRelease(IContextMenu
*);
32 static HRESULT WINAPI
IContextMenu_fnQueryContextMenu(IContextMenu
*, HMENU
,UINT
,UINT
,UINT
,UINT
);
33 static HRESULT WINAPI
IContextMenu_fnInvokeCommand(IContextMenu
*, LPCMINVOKECOMMANDINFO
);
34 static HRESULT WINAPI
IContextMenu_fnGetCommandString(IContextMenu
*, UINT
,UINT
,LPUINT
,LPSTR
,UINT
);
35 static HRESULT WINAPI
IContextMenu_fnHandleMenuMsg(IContextMenu
*, UINT
, WPARAM
, LPARAM
);
38 BOOL
IContextMenu_AllocPidlTable(IContextMenuImpl
*, DWORD
);
39 void IContextMenu_FreePidlTable(IContextMenuImpl
*);
40 BOOL
IContextMenu_CanRenameItems(IContextMenuImpl
*);
41 BOOL
IContextMenu_FillPidlTable(IContextMenuImpl
*, LPCITEMIDLIST
*, UINT
);
43 /**************************************************************************
47 static struct ICOM_VTABLE(IContextMenu
) cmvt
= {
48 IContextMenu_fnQueryInterface
,
49 IContextMenu_fnAddRef
,
50 IContextMenu_fnRelease
,
51 IContextMenu_fnQueryContextMenu
,
52 IContextMenu_fnInvokeCommand
,
53 IContextMenu_fnGetCommandString
,
54 IContextMenu_fnHandleMenuMsg
,
55 (void *) 0xdeadbabe /* just paranoia */
58 /**************************************************************************
59 * IContextMenu_fnQueryInterface
61 static HRESULT WINAPI
IContextMenu_fnQueryInterface(IContextMenu
*iface
, REFIID riid
, LPVOID
*ppvObj
)
62 { ICOM_THIS(IContextMenuImpl
, iface
);
64 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
65 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",This
,xriid
,ppvObj
);
69 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
72 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
75 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
76 { FIXME (shell
,"-- LPSHELLEXTINIT pointer requested\n");
81 (*(IContextMenuImpl
**)ppvObj
)->lpvtbl
->fnAddRef(iface
);
82 TRACE(shell
,"-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
85 TRACE(shell
,"-- Interface: E_NOINTERFACE\n");
89 /**************************************************************************
90 * IContextMenu_fnAddRef
92 static ULONG WINAPI
IContextMenu_fnAddRef(IContextMenu
*iface
)
93 { ICOM_THIS(IContextMenuImpl
, iface
);
94 TRACE(shell
,"(%p)->(count=%lu)\n",This
,(This
->ref
)+1);
98 /**************************************************************************
99 * IContextMenu_fnRelease
101 static ULONG WINAPI
IContextMenu_fnRelease(IContextMenu
*iface
)
102 { ICOM_THIS(IContextMenuImpl
, iface
);
103 TRACE(shell
,"(%p)->()\n",This
);
108 { TRACE(shell
," destroying IContextMenu(%p)\n",This
);
111 This
->pSFParent
->lpvtbl
->fnRelease(This
->pSFParent
);
113 /*make sure the pidl is freed*/
115 { IContextMenu_FreePidlTable(This
);
118 HeapFree(GetProcessHeap(),0,This
);
124 /**************************************************************************
125 * IContextMenu_Constructor()
127 IContextMenu
*IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
128 { IContextMenuImpl
* cm
;
130 FIXME(shell
, "HELLO age\n") ;
131 cm
= (IContextMenuImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl
));
135 cm
->pSFParent
= pSFParent
;
137 cm
->pSFParent
->lpvtbl
->fnAddRef(cm
->pSFParent
);
141 IContextMenu_AllocPidlTable(cm
, uItemCount
);
144 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
148 for(u
= 0; u
< uItemCount
; u
++)
149 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
151 TRACE(shell
,"(%p)->()\n",cm
);
153 return (IContextMenu
*)cm
;
155 /**************************************************************************
158 void WINAPI
_InsertMenuItem (HMENU hmenu
, UINT indexMenu
, BOOL fByPosition
,
159 UINT wID
, UINT fType
, LPSTR dwTypeData
, UINT fState
)
162 ZeroMemory(&mii
, sizeof(mii
));
163 mii
.cbSize
= sizeof(mii
);
164 if (fType
== MFT_SEPARATOR
)
165 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
168 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
169 mii
.dwTypeData
= dwTypeData
;
170 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
174 InsertMenuItemA( hmenu
, indexMenu
, fByPosition
, &mii
);
176 /**************************************************************************
177 * IContextMenu_fnQueryContextMenu()
180 static HRESULT WINAPI
IContextMenu_fnQueryContextMenu(IContextMenu
*iface
, HMENU hmenu
, UINT indexMenu
,
181 UINT idCmdFirst
,UINT idCmdLast
,UINT uFlags
)
182 { ICOM_THIS(IContextMenuImpl
, iface
);
185 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This
, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
187 if(!(CMF_DEFAULTONLY
& uFlags
))
188 { if(!This
->bAllValues
)
190 fExplore
= uFlags
& CMF_EXPLORE
;
192 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
|MFS_DEFAULT
);
193 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
);
196 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
197 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
);
200 if(uFlags
& CMF_CANRENAME
)
201 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
202 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
));
206 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
207 if(uFlags
& CMF_CANRENAME
)
208 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
209 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(This
) ? MFS_ENABLED
: MFS_DISABLED
));
212 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
214 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
217 /**************************************************************************
218 * IContextMenu_fnInvokeCommand()
220 static HRESULT WINAPI
IContextMenu_fnInvokeCommand(IContextMenu
*iface
, LPCMINVOKECOMMANDINFO lpcmi
)
221 { ICOM_THIS(IContextMenuImpl
, iface
);
222 LPITEMIDLIST pidlTemp
,pidlFQ
;
226 SHELLEXECUTEINFOA sei
;
229 TRACE(shell
,"(%p)->(invcom=%p verb=%p wnd=%x)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
231 if(HIWORD(lpcmi
->lpVerb
))
232 { /* get the active IShellView */
233 lpSB
= (LPSHELLBROWSER
)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
234 IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
); /* does AddRef() on lpSV */
235 lpSV
->lpvtbl
->fnGetWindow(lpSV
, &hWndSV
);
237 /* these verbs are used by the filedialogs*/
238 TRACE(shell
,"%s\n",lpcmi
->lpVerb
);
239 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDER
))
240 { FIXME(shell
,"%s not implemented\n",lpcmi
->lpVerb
);
242 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLIST
))
243 { SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
245 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILS
))
246 { SendMessageA(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
249 { FIXME(shell
,"please report: unknown verb %s\n",lpcmi
->lpVerb
);
251 lpSV
->lpvtbl
->fnRelease(lpSV
);
255 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
258 switch(LOWORD(lpcmi
->lpVerb
))
261 /* Find the first item in the list that is not a value. These commands
262 should never be invoked if there isn't at least one folder item in the list.*/
264 for(i
= 0; This
->aPidls
[i
]; i
++)
265 { if(!_ILIsValue(This
->aPidls
[i
]))
269 pidlTemp
= ILCombine(This
->pSFParent
->mpidl
, This
->aPidls
[i
]);
270 pidlFQ
= ILCombine(This
->pSFParent
->pMyPidl
, pidlTemp
);
273 ZeroMemory(&sei
, sizeof(sei
));
274 sei
.cbSize
= sizeof(sei
);
275 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
276 sei
.lpIDList
= pidlFQ
;
277 sei
.lpClass
= "folder";
278 sei
.hwnd
= lpcmi
->hwnd
;
279 sei
.nShow
= SW_SHOWNORMAL
;
281 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
282 { sei
.lpVerb
= "explore";
285 { sei
.lpVerb
= "open";
287 ShellExecuteExA(&sei
);
293 /*handle rename for the view here*/
299 /**************************************************************************
300 * IContextMenu_fnGetCommandString()
302 static HRESULT WINAPI
IContextMenu_fnGetCommandString(IContextMenu
*iface
, UINT idCommand
,
303 UINT uFlags
,LPUINT lpReserved
,LPSTR lpszName
,UINT uMaxNameLen
)
304 { ICOM_THIS(IContextMenuImpl
, iface
);
305 HRESULT hr
= E_INVALIDARG
;
307 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
317 strcpy((LPSTR
)lpszName
, "rename");
323 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
324 case, you need to do the lstrcpyW to the pointer passed.*/
328 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
338 TRACE(shell
,"-- (%p)->(name=%s)\n",This
, lpszName
);
342 /**************************************************************************
343 * IContextMenu_fnHandleMenuMsg()
345 * should be only in IContextMenu2 and IContextMenu3
346 * is nevertheless called from word95
348 static HRESULT WINAPI
IContextMenu_fnHandleMenuMsg(IContextMenu
*iface
, UINT uMsg
,WPARAM wParam
,LPARAM lParam
)
349 { ICOM_THIS(IContextMenuImpl
, iface
);
350 TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",This
, uMsg
, wParam
, lParam
);
356 /**************************************************************************
357 * IContextMenu_AllocPidlTable()
359 BOOL
IContextMenu_AllocPidlTable(IContextMenuImpl
*This
, DWORD dwEntries
)
360 { TRACE(shell
,"(%p)->(entrys=%lu)\n",This
, dwEntries
);
362 /*add one for NULL terminator */
365 This
->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
368 { ZeroMemory(This
->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
370 return (This
->aPidls
!= NULL
);
373 /**************************************************************************
374 * IContextMenu_FreePidlTable()
376 void IContextMenu_FreePidlTable(IContextMenuImpl
*This
)
379 TRACE(shell
,"(%p)->()\n",This
);
382 { for(i
= 0; This
->aPidls
[i
]; i
++)
383 { SHFree(This
->aPidls
[i
]);
386 SHFree(This
->aPidls
);
391 /**************************************************************************
392 * IContextMenu_FillPidlTable()
394 BOOL
IContextMenu_FillPidlTable(IContextMenuImpl
*This
, LPCITEMIDLIST
*aPidls
, UINT uItemCount
)
396 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",This
, aPidls
, uItemCount
);
398 { for(i
= 0; i
< uItemCount
; i
++)
399 { This
->aPidls
[i
] = ILClone(aPidls
[i
]);
406 /**************************************************************************
407 * IContextMenu_CanRenameItems()
409 BOOL
IContextMenu_CanRenameItems(IContextMenuImpl
*This
)
413 TRACE(shell
,"(%p)->()\n",This
);
416 { for(i
= 0; This
->aPidls
[i
]; i
++){} /*get the number of items assigned to This object*/
417 if(i
> 1) /*you can't rename more than one item at a time*/
420 dwAttributes
= SFGAO_CANRENAME
;
421 This
->pSFParent
->lpvtbl
->fnGetAttributesOf(This
->pSFParent
, i
,
422 (LPCITEMIDLIST
*)This
->aPidls
, &dwAttributes
);
424 return dwAttributes
& SFGAO_CANRENAME
;