4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
11 #include "shell32_main.h"
13 #include "if_macros.h"
19 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
,REFIID
, LPVOID
*);
20 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
);
21 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
);
22 static HRESULT WINAPI
IContextMenu_QueryContextMenu(LPCONTEXTMENU
, HMENU32
,UINT32
,UINT32
,UINT32
,UINT32
);
23 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
, LPCMINVOKECOMMANDINFO32
);
24 static HRESULT WINAPI
IContextMenu_GetCommandString(LPCONTEXTMENU
, UINT32
,UINT32
,LPUINT32
,LPSTR
,UINT32
);
25 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
, UINT32
, WPARAM32
, LPARAM
);
27 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
, DWORD
);
28 void IContextMenu_FreePidlTable(LPCONTEXTMENU
);
29 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
);
30 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
, LPCITEMIDLIST
*, UINT32
);
32 static struct IContextMenu_VTable cmvt
=
33 { IContextMenu_QueryInterface
,
36 IContextMenu_QueryContextMenu
,
37 IContextMenu_InvokeCommand
,
38 IContextMenu_GetCommandString
,
39 IContextMenu_HandleMenuMsg
,
40 (void *) 0xdeadbabe /* just paranoia */
42 /**************************************************************************
43 * IContextMenu_QueryInterface
45 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
this,REFIID riid
, LPVOID
*ppvObj
)
47 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
48 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid
,ppvObj
);
52 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
53 { *ppvObj
= (LPUNKNOWN
)(LPCONTEXTMENU
)this;
55 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
56 { *ppvObj
= (LPCONTEXTMENU
)this;
58 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
59 { *ppvObj
= (LPSHELLEXTINIT
)this;
60 WARN(shell
,"-- LPSHELLEXTINIT pointer requested\n");
64 { (*(LPCONTEXTMENU
*)ppvObj
)->lpvtbl
->fnAddRef(this);
65 TRACE(shell
,"-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
68 TRACE(shell
,"-- Interface: E_NOINTERFACE\n");
72 /**************************************************************************
75 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
this)
76 { TRACE(shell
,"(%p)->(count=%lu)\n",this,(this->ref
)+1);
79 /**************************************************************************
80 * IContextMenu_Release
82 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
this)
83 { TRACE(shell
,"(%p)->()\n",this);
85 { TRACE(shell
," destroying IContextMenu(%p)\n",this);
88 this->pSFParent
->lpvtbl
->fnRelease(this->pSFParent
);
90 /*make sure the pidl is freed*/
92 { IContextMenu_FreePidlTable(this);
95 HeapFree(GetProcessHeap(),0,this);
101 /**************************************************************************
102 * IContextMenu_Constructor()
104 LPCONTEXTMENU
IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
108 cm
= (LPCONTEXTMENU
)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu
));
112 cm
->pSFParent
= pSFParent
;
114 cm
->pSFParent
->lpvtbl
->fnAddRef(cm
->pSFParent
);
118 IContextMenu_AllocPidlTable(cm
, uItemCount
);
121 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
125 for(u
= 0; u
< uItemCount
; u
++)
126 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
128 TRACE(shell
,"(%p)->()\n",cm
);
131 /**************************************************************************
134 void WINAPI
_InsertMenuItem (HMENU32 hmenu
, UINT32 indexMenu
, BOOL32 fByPosition
,
135 UINT32 wID
, UINT32 fType
, LPSTR dwTypeData
, UINT32 fState
)
136 { MENUITEMINFO32A mii
;
138 ZeroMemory(&mii
, sizeof(mii
));
139 mii
.cbSize
= sizeof(mii
);
140 if (fType
== MFT_SEPARATOR
)
141 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
144 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
145 mii
.dwTypeData
= dwTypeData
;
146 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
150 InsertMenuItem32A( hmenu
, indexMenu
, fByPosition
, &mii
);
152 /**************************************************************************
153 * IContextMenu_QueryContextMenu()
156 static HRESULT WINAPI
IContextMenu_QueryContextMenu( LPCONTEXTMENU
this, HMENU32 hmenu
, UINT32 indexMenu
,
157 UINT32 idCmdFirst
,UINT32 idCmdLast
,UINT32 uFlags
)
160 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",this, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
162 if(!(CMF_DEFAULTONLY
& uFlags
))
163 { if(!this->bAllValues
)
165 fExplore
= uFlags
& CMF_EXPLORE
;
167 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, TEXT("&Explore"), MFS_ENABLED
|MFS_DEFAULT
);
168 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, TEXT("&Open"), MFS_ENABLED
);
171 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, TEXT("&Open"), MFS_ENABLED
|MFS_DEFAULT
);
172 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, TEXT("&Explore"), MFS_ENABLED
);
175 if(uFlags
& CMF_CANRENAME
)
176 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
177 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, TEXT("&Rename"), (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
181 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, TEXT("&Open"), MFS_ENABLED
|MFS_DEFAULT
);
182 if(uFlags
& CMF_CANRENAME
)
183 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
184 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, TEXT("&Rename"), (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
187 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
189 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
192 /**************************************************************************
193 * IContextMenu_InvokeCommand()
195 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
this, LPCMINVOKECOMMANDINFO32 lpcmi
)
196 { LPITEMIDLIST pidlTemp
,pidlFQ
;
200 SHELLEXECUTEINFO32A sei
;
203 TRACE(shell
,"(%p)->(invcom=%p verb=%p wnd=%x)\n",this,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
205 if(HIWORD(lpcmi
->lpVerb
))
206 { /* get the active IShellView */
207 lpSB
= (LPSHELLBROWSER
)SendMessage32A(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
208 IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
);
209 lpSV
->lpvtbl
->fnGetWindow(lpSV
, &hWndSV
);
211 /* these verbs are used by the filedialogs*/
212 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDER
))
213 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
215 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLIST
))
216 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
217 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
219 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILS
))
220 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
221 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
224 { FIXME(shell
,"please report: unknown verb %s\n",lpcmi
->lpVerb
);
229 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
232 switch(LOWORD(lpcmi
->lpVerb
))
235 /* Find the first item in the list that is not a value. These commands
236 should never be invoked if there isn't at least one folder item in the list.*/
238 for(i
= 0; this->aPidls
[i
]; i
++)
239 { if(!_ILIsValue(this->aPidls
[i
]))
243 pidlTemp
= ILCombine(this->pSFParent
->mpidl
, this->aPidls
[i
]);
244 pidlFQ
= ILCombine(this->pSFParent
->pMyPidl
, pidlTemp
);
247 ZeroMemory(&sei
, sizeof(sei
));
248 sei
.cbSize
= sizeof(sei
);
249 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
250 sei
.lpIDList
= pidlFQ
;
251 sei
.lpClass
= TEXT("folder");
252 sei
.hwnd
= lpcmi
->hwnd
;
253 sei
.nShow
= SW_SHOWNORMAL
;
255 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
256 { sei
.lpVerb
= TEXT("explore");
259 { sei
.lpVerb
= TEXT("open");
261 ShellExecuteEx32A(&sei
);
266 MessageBeep32(MB_OK
);
267 /*handle rename for the view here*/
273 /**************************************************************************
274 * IContextMenu_GetCommandString()
276 static HRESULT WINAPI
IContextMenu_GetCommandString( LPCONTEXTMENU
this, UINT32 idCommand
,
277 UINT32 uFlags
,LPUINT32 lpReserved
,LPSTR lpszName
,UINT32 uMaxNameLen
)
278 { HRESULT hr
= E_INVALIDARG
;
280 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
290 strcpy((LPSTR
)lpszName
, "rename");
296 /* NT 4.0 with IE 3.0x or no IE will always call this with GCS_VERBW. In this
297 case, you need to do the lstrcpyW to the pointer passed.*/
301 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
311 TRACE(shell
,"-- (%p)->(name=%s)\n",this, lpszName
);
314 /**************************************************************************
315 * IContextMenu_HandleMenuMsg()
317 * should be only in IContextMenu2 and IContextMenu3
318 * is nevertheless called from word95
320 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
this, UINT32 uMsg
,WPARAM32 wParam
,LPARAM lParam
)
321 { TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",this, uMsg
, wParam
, lParam
);
324 /**************************************************************************
325 * IContextMenu_AllocPidlTable()
327 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
this, DWORD dwEntries
)
328 { //add one for NULL terminator
329 TRACE(shell
,"(%p)->(entrys=%lu)\n",this, dwEntries
);
332 this->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
335 { ZeroMemory(this->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
337 return (this->aPidls
!= NULL
);
340 /**************************************************************************
341 * IContextMenu_FreePidlTable()
343 void IContextMenu_FreePidlTable(LPCONTEXTMENU
this)
346 TRACE(shell
,"(%p)->()\n",this);
349 { for(i
= 0; this->aPidls
[i
]; i
++)
350 { SHFree(this->aPidls
[i
]);
353 SHFree(this->aPidls
);
358 /**************************************************************************
359 * IContextMenu_FillPidlTable()
361 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
this, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
363 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",this, aPidls
, uItemCount
);
365 { for(i
= 0; i
< uItemCount
; i
++)
366 { this->aPidls
[i
] = ILClone(aPidls
[i
]);
373 /**************************************************************************
374 * IContextMenu_CanRenameItems()
376 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
this)
380 TRACE(shell
,"(%p)->()\n",this);
383 { for(i
= 0; this->aPidls
[i
]; i
++){} /*get the number of items assigned to this object*/
384 if(i
> 1) /*you can't rename more than one item at a time*/
387 dwAttributes
= SFGAO_CANRENAME
;
388 this->pSFParent
->lpvtbl
->fnGetAttributesOf(this->pSFParent
, i
,
389 (LPCITEMIDLIST
*)this->aPidls
, &dwAttributes
);
391 return dwAttributes
& SFGAO_CANRENAME
;