4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
12 #include "if_macros.h"
15 #include "shell32_main.h"
18 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
,REFIID
, LPVOID
*);
19 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
);
20 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
);
21 static HRESULT WINAPI
IContextMenu_QueryContextMenu(LPCONTEXTMENU
, HMENU32
,UINT32
,UINT32
,UINT32
,UINT32
);
22 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
, LPCMINVOKECOMMANDINFO32
);
23 static HRESULT WINAPI
IContextMenu_GetCommandString(LPCONTEXTMENU
, UINT32
,UINT32
,LPUINT32
,LPSTR
,UINT32
);
24 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
, UINT32
, WPARAM32
, LPARAM
);
26 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
, DWORD
);
27 void IContextMenu_FreePidlTable(LPCONTEXTMENU
);
28 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
);
29 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
, LPCITEMIDLIST
*, UINT32
);
31 static struct IContextMenu_VTable cmvt
=
32 { IContextMenu_QueryInterface
,
35 IContextMenu_QueryContextMenu
,
36 IContextMenu_InvokeCommand
,
37 IContextMenu_GetCommandString
,
38 IContextMenu_HandleMenuMsg
,
39 (void *) 0xdeadbabe /* just paranoia */
41 /**************************************************************************
42 * IContextMenu_QueryInterface
44 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
this,REFIID riid
, LPVOID
*ppvObj
)
46 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
47 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid
,ppvObj
);
51 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
52 { *ppvObj
= (LPUNKNOWN
)(LPCONTEXTMENU
)this;
54 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
55 { *ppvObj
= (LPCONTEXTMENU
)this;
57 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
58 { FIXME (shell
,"-- LPSHELLEXTINIT pointer requested\n");
62 { (*(LPCONTEXTMENU
*)ppvObj
)->lpvtbl
->fnAddRef(this);
63 TRACE(shell
,"-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
66 TRACE(shell
,"-- Interface: E_NOINTERFACE\n");
70 /**************************************************************************
73 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
this)
74 { TRACE(shell
,"(%p)->(count=%lu)\n",this,(this->ref
)+1);
78 /**************************************************************************
79 * IContextMenu_Release
81 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
this)
82 { TRACE(shell
,"(%p)->()\n",this);
87 { TRACE(shell
," destroying IContextMenu(%p)\n",this);
90 this->pSFParent
->lpvtbl
->fnRelease(this->pSFParent
);
92 /*make sure the pidl is freed*/
94 { IContextMenu_FreePidlTable(this);
97 HeapFree(GetProcessHeap(),0,this);
103 /**************************************************************************
104 * IContextMenu_Constructor()
106 LPCONTEXTMENU
IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
110 cm
= (LPCONTEXTMENU
)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu
));
114 cm
->pSFParent
= pSFParent
;
116 cm
->pSFParent
->lpvtbl
->fnAddRef(cm
->pSFParent
);
120 IContextMenu_AllocPidlTable(cm
, uItemCount
);
123 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
127 for(u
= 0; u
< uItemCount
; u
++)
128 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
130 TRACE(shell
,"(%p)->()\n",cm
);
134 /**************************************************************************
137 void WINAPI
_InsertMenuItem (HMENU32 hmenu
, UINT32 indexMenu
, BOOL32 fByPosition
,
138 UINT32 wID
, UINT32 fType
, LPSTR dwTypeData
, UINT32 fState
)
139 { MENUITEMINFO32A mii
;
141 ZeroMemory(&mii
, sizeof(mii
));
142 mii
.cbSize
= sizeof(mii
);
143 if (fType
== MFT_SEPARATOR
)
144 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
147 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
148 mii
.dwTypeData
= dwTypeData
;
149 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
153 InsertMenuItem32A( hmenu
, indexMenu
, fByPosition
, &mii
);
155 /**************************************************************************
156 * IContextMenu_QueryContextMenu()
159 static HRESULT WINAPI
IContextMenu_QueryContextMenu( LPCONTEXTMENU
this, HMENU32 hmenu
, UINT32 indexMenu
,
160 UINT32 idCmdFirst
,UINT32 idCmdLast
,UINT32 uFlags
)
163 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",this, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
165 if(!(CMF_DEFAULTONLY
& uFlags
))
166 { if(!this->bAllValues
)
168 fExplore
= uFlags
& CMF_EXPLORE
;
170 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
|MFS_DEFAULT
);
171 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
);
174 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
175 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, "&Explore", MFS_ENABLED
);
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
));
184 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_OPEN
, MFT_STRING
, "&Open", MFS_ENABLED
|MFS_DEFAULT
);
185 if(uFlags
& CMF_CANRENAME
)
186 { _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
187 _InsertMenuItem(hmenu
, indexMenu
++, TRUE
, idCmdFirst
+IDM_RENAME
, MFT_STRING
, "&Rename", (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
190 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
192 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
195 /**************************************************************************
196 * IContextMenu_InvokeCommand()
198 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
this, LPCMINVOKECOMMANDINFO32 lpcmi
)
199 { LPITEMIDLIST pidlTemp
,pidlFQ
;
203 SHELLEXECUTEINFO32A sei
;
206 TRACE(shell
,"(%p)->(invcom=%p verb=%p wnd=%x)\n",this,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
208 if(HIWORD(lpcmi
->lpVerb
))
209 { /* get the active IShellView */
210 lpSB
= (LPSHELLBROWSER
)SendMessage32A(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
,0,0);
211 IShellBrowser_QueryActiveShellView(lpSB
, &lpSV
); /* does AddRef() on lpSV */
212 lpSV
->lpvtbl
->fnGetWindow(lpSV
, &hWndSV
);
214 /* these verbs are used by the filedialogs*/
215 if (! strcmp(lpcmi
->lpVerb
,CMDSTR_NEWFOLDER
))
216 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
218 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWLIST
))
219 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
220 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
,0),0 );
222 else if (! strcmp(lpcmi
->lpVerb
,CMDSTR_VIEWDETAILS
))
223 { FIXME(shell
,"%s\n",lpcmi
->lpVerb
);
224 SendMessage32A(hWndSV
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
,0),0 );
227 { FIXME(shell
,"please report: unknown verb %s\n",lpcmi
->lpVerb
);
229 lpSV
->lpvtbl
->fnRelease(lpSV
);
233 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
236 switch(LOWORD(lpcmi
->lpVerb
))
239 /* Find the first item in the list that is not a value. These commands
240 should never be invoked if there isn't at least one folder item in the list.*/
242 for(i
= 0; this->aPidls
[i
]; i
++)
243 { if(!_ILIsValue(this->aPidls
[i
]))
247 pidlTemp
= ILCombine(this->pSFParent
->mpidl
, this->aPidls
[i
]);
248 pidlFQ
= ILCombine(this->pSFParent
->pMyPidl
, pidlTemp
);
251 ZeroMemory(&sei
, sizeof(sei
));
252 sei
.cbSize
= sizeof(sei
);
253 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
254 sei
.lpIDList
= pidlFQ
;
255 sei
.lpClass
= "folder";
256 sei
.hwnd
= lpcmi
->hwnd
;
257 sei
.nShow
= SW_SHOWNORMAL
;
259 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
260 { sei
.lpVerb
= "explore";
263 { sei
.lpVerb
= "open";
265 ShellExecuteEx32A(&sei
);
270 MessageBeep32(MB_OK
);
271 /*handle rename for the view here*/
277 /**************************************************************************
278 * IContextMenu_GetCommandString()
280 static HRESULT WINAPI
IContextMenu_GetCommandString( LPCONTEXTMENU
this, UINT32 idCommand
,
281 UINT32 uFlags
,LPUINT32 lpReserved
,LPSTR lpszName
,UINT32 uMaxNameLen
)
282 { HRESULT hr
= E_INVALIDARG
;
284 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
294 strcpy((LPSTR
)lpszName
, "rename");
300 /* NT 4.0 with IE 3.0x or no IE will always call this with GCS_VERBW. In this
301 case, you need to do the lstrcpyW to the pointer passed.*/
305 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
315 TRACE(shell
,"-- (%p)->(name=%s)\n",this, lpszName
);
318 /**************************************************************************
319 * IContextMenu_HandleMenuMsg()
321 * should be only in IContextMenu2 and IContextMenu3
322 * is nevertheless called from word95
324 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
this, UINT32 uMsg
,WPARAM32 wParam
,LPARAM lParam
)
325 { TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",this, uMsg
, wParam
, lParam
);
328 /**************************************************************************
329 * IContextMenu_AllocPidlTable()
331 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
this, DWORD dwEntries
)
332 { TRACE(shell
,"(%p)->(entrys=%lu)\n",this, dwEntries
);
334 /*add one for NULL terminator */
337 this->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
340 { ZeroMemory(this->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
342 return (this->aPidls
!= NULL
);
345 /**************************************************************************
346 * IContextMenu_FreePidlTable()
348 void IContextMenu_FreePidlTable(LPCONTEXTMENU
this)
351 TRACE(shell
,"(%p)->()\n",this);
354 { for(i
= 0; this->aPidls
[i
]; i
++)
355 { SHFree(this->aPidls
[i
]);
358 SHFree(this->aPidls
);
363 /**************************************************************************
364 * IContextMenu_FillPidlTable()
366 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
this, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
368 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",this, aPidls
, uItemCount
);
370 { for(i
= 0; i
< uItemCount
; i
++)
371 { this->aPidls
[i
] = ILClone(aPidls
[i
]);
378 /**************************************************************************
379 * IContextMenu_CanRenameItems()
381 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
this)
385 TRACE(shell
,"(%p)->()\n",this);
388 { for(i
= 0; this->aPidls
[i
]; i
++){} /*get the number of items assigned to this object*/
389 if(i
> 1) /*you can't rename more than one item at a time*/
392 dwAttributes
= SFGAO_CANRENAME
;
393 this->pSFParent
->lpvtbl
->fnGetAttributesOf(this->pSFParent
, i
,
394 (LPCITEMIDLIST
*)this->aPidls
, &dwAttributes
);
396 return dwAttributes
& SFGAO_CANRENAME
;