4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
11 #include "shell32_main.h"
13 #include "if_macros.h"
15 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
,REFIID
, LPVOID
*);
16 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
);
17 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
);
18 static HRESULT WINAPI
IContextMenu_QueryContextMenu(LPCONTEXTMENU
, HMENU32
,UINT32
,UINT32
,UINT32
,UINT32
);
19 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
, LPCMINVOKECOMMANDINFO32
);
20 static HRESULT WINAPI
IContextMenu_GetCommandString(LPCONTEXTMENU
, UINT32
,UINT32
,LPUINT32
,LPSTR
,UINT32
);
21 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
, UINT32
, WPARAM32
, LPARAM
);
23 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
, DWORD
);
24 void IContextMenu_FreePidlTable(LPCONTEXTMENU
);
25 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
);
26 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
, LPCITEMIDLIST
*, UINT32
);
28 static struct IContextMenu_VTable cmvt
=
29 { IContextMenu_QueryInterface
,
32 IContextMenu_QueryContextMenu
,
33 IContextMenu_InvokeCommand
,
34 IContextMenu_GetCommandString
,
35 IContextMenu_HandleMenuMsg
,
36 (void *) 0xdeadbabe /* just paranoia */
38 /**************************************************************************
39 * IContextMenu_QueryInterface
41 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
this,REFIID riid
, LPVOID
*ppvObj
)
43 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
44 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid
,ppvObj
);
48 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
49 { *ppvObj
= (LPUNKNOWN
)(LPCONTEXTMENU
)this;
51 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
52 { *ppvObj
= (LPCONTEXTMENU
)this;
54 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
55 { *ppvObj
= (LPSHELLEXTINIT
)this;
56 WARN(shell
,"-- LPSHELLEXTINIT pointer requested\n");
60 { (*(LPCONTEXTMENU
*)ppvObj
)->lpvtbl
->fnAddRef(this);
61 TRACE(shell
,"-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
64 TRACE(shell
,"-- Interface: E_NOINTERFACE\n");
68 /**************************************************************************
71 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
this)
72 { TRACE(shell
,"(%p)->(count=%lu)\n",this,(this->ref
)+1);
75 /**************************************************************************
76 * IContextMenu_Release
78 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
this)
79 { TRACE(shell
,"(%p)->()\n",this);
81 { TRACE(shell
," destroying IContextMenu(%p)\n",this);
84 this->pSFParent
->lpvtbl
->fnRelease(this->pSFParent
);
86 /*make sure the pidl is freed*/
88 { IContextMenu_FreePidlTable(this);
91 HeapFree(GetProcessHeap(),0,this);
97 /**************************************************************************
98 * IContextMenu_Constructor()
100 LPCONTEXTMENU
IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
104 cm
= (LPCONTEXTMENU
)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu
));
108 cm
->pSFParent
= pSFParent
;
110 cm
->pSFParent
->lpvtbl
->fnAddRef(cm
->pSFParent
);
114 IContextMenu_AllocPidlTable(cm
, uItemCount
);
117 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
121 for(u
= 0; u
< uItemCount
; u
++)
122 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
124 TRACE(shell
,"(%p)->()\n",cm
);
127 /**************************************************************************
130 void WINAPI
_InsertMenuItem (HMENU32 hmenu
, UINT32 indexMenu
, BOOL32 fByPosition
,
131 UINT32 wID
, UINT32 fType
, LPSTR dwTypeData
, UINT32 fState
)
132 { MENUITEMINFO32A mii
;
134 ZeroMemory(&mii
, sizeof(mii
));
135 mii
.cbSize
= sizeof(mii
);
136 if (fType
== MFT_SEPARATOR
)
137 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
140 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
141 mii
.dwTypeData
= dwTypeData
;
142 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
146 InsertMenuItem32A( hmenu
, indexMenu
, fByPosition
, &mii
);
148 /**************************************************************************
149 * IContextMenu_QueryContextMenu()
152 static HRESULT WINAPI
IContextMenu_QueryContextMenu( LPCONTEXTMENU
this, HMENU32 hmenu
, UINT32 indexMenu
,
153 UINT32 idCmdFirst
,UINT32 idCmdLast
,UINT32 uFlags
)
156 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",this, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
158 if(!(CMF_DEFAULTONLY
& uFlags
))
159 { if(!this->bAllValues
)
161 fExplore
= uFlags
& CMF_EXPLORE
;
163 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
|MFS_DEFAULT
);
164 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
);
167 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
168 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
);
171 if(uFlags
& CMF_CANRENAME
)
172 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
173 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
177 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
178 if(uFlags
& CMF_CANRENAME
)
179 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
180 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
183 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
185 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
188 /**************************************************************************
189 * IContextMenu_InvokeCommand()
191 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
this, LPCMINVOKECOMMANDINFO32 lpcmi
)
192 { LPITEMIDLIST pidlTemp
,pidlFQ
;
196 SHELLEXECUTEINFO32A sei
;
199 TRACE(shell
,"(%p)->(invcom=%p verb=%p wnd=%x)\n",this,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
201 if(HIWORD(lpcmi
->lpVerb
))
202 { /* get the active IShellView */
203 lpSB
= (LPSHELLBROWSER
)SendMessage32A(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
204 IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
);
205 lpSV
->lpvtbl
->fnGetWindow(lpSV
, &hWndSV
);
207 /* these verbs are used by the filedialogs*/
208 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDER
))
209 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
211 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLIST
))
212 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
213 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
215 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILS
))
216 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
217 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
220 { FIXME(shell
,"please report: unknown verb %s\n",lpcmi
->lpVerb
);
225 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
228 switch(LOWORD(lpcmi
->lpVerb
))
231 /* Find the first item in the list that is not a value. These commands
232 should never be invoked if there isn't at least one folder item in the list.*/
234 for(i
= 0; this->aPidls
[i
]; i
++)
235 { if(!_ILIsValue(this->aPidls
[i
]))
239 pidlTemp
= ILCombine(this->pSFParent
->mpidl
, this->aPidls
[i
]);
240 pidlFQ
= ILCombine(this->pSFParent
->pMyPidl
, pidlTemp
);
243 ZeroMemory(&sei
, sizeof(sei
));
244 sei
.cbSize
= sizeof(sei
);
245 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
246 sei
.lpIDList
= pidlFQ
;
247 sei
.lpClass
= "folder";
248 sei
.hwnd
= lpcmi
->hwnd
;
249 sei
.nShow
= SW_SHOWNORMAL
;
251 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
252 { sei
.lpVerb
= "explore";
255 { sei
.lpVerb
= "open";
257 ShellExecuteEx32A(&sei
);
262 MessageBeep32(MB_OK
);
263 /*handle rename for the view here*/
269 /**************************************************************************
270 * IContextMenu_GetCommandString()
272 static HRESULT WINAPI
IContextMenu_GetCommandString( LPCONTEXTMENU
this, UINT32 idCommand
,
273 UINT32 uFlags
,LPUINT32 lpReserved
,LPSTR lpszName
,UINT32 uMaxNameLen
)
274 { HRESULT hr
= E_INVALIDARG
;
276 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
286 strcpy((LPSTR
)lpszName
, "rename");
292 /* NT 4.0 with IE 3.0x or no IE will always call this with GCS_VERBW. In this
293 case, you need to do the lstrcpyW to the pointer passed.*/
297 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
307 TRACE(shell
,"-- (%p)->(name=%s)\n",this, lpszName
);
310 /**************************************************************************
311 * IContextMenu_HandleMenuMsg()
313 * should be only in IContextMenu2 and IContextMenu3
314 * is nevertheless called from word95
316 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
this, UINT32 uMsg
,WPARAM32 wParam
,LPARAM lParam
)
317 { TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",this, uMsg
, wParam
, lParam
);
320 /**************************************************************************
321 * IContextMenu_AllocPidlTable()
323 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
this, DWORD dwEntries
)
324 { //add one for NULL terminator
325 TRACE(shell
,"(%p)->(entrys=%lu)\n",this, dwEntries
);
328 this->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
331 { ZeroMemory(this->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
333 return (this->aPidls
!= NULL
);
336 /**************************************************************************
337 * IContextMenu_FreePidlTable()
339 void IContextMenu_FreePidlTable(LPCONTEXTMENU
this)
342 TRACE(shell
,"(%p)->()\n",this);
345 { for(i
= 0; this->aPidls
[i
]; i
++)
346 { SHFree(this->aPidls
[i
]);
349 SHFree(this->aPidls
);
354 /**************************************************************************
355 * IContextMenu_FillPidlTable()
357 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
this, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
359 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",this, aPidls
, uItemCount
);
361 { for(i
= 0; i
< uItemCount
; i
++)
362 { this->aPidls
[i
] = ILClone(aPidls
[i
]);
369 /**************************************************************************
370 * IContextMenu_CanRenameItems()
372 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
this)
376 TRACE(shell
,"(%p)->()\n",this);
379 { for(i
= 0; this->aPidls
[i
]; i
++){} /*get the number of items assigned to this object*/
380 if(i
> 1) /*you can't rename more than one item at a time*/
383 dwAttributes
= SFGAO_CANRENAME
;
384 this->pSFParent
->lpvtbl
->fnGetAttributesOf(this->pSFParent
, i
,
385 (LPCITEMIDLIST
*)this->aPidls
, &dwAttributes
);
387 return dwAttributes
& SFGAO_CANRENAME
;