4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
11 #include "shell32_main.h"
17 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
,REFIID
, LPVOID
*);
18 static ULONG WINAPI
IContextMenu_AddRef(LPCONTEXTMENU
);
19 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
);
20 static HRESULT WINAPI
IContextMenu_QueryContextMenu(LPCONTEXTMENU
, HMENU32
,UINT32
,UINT32
,UINT32
,UINT32
);
21 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
, LPCMINVOKECOMMANDINFO32
);
22 static HRESULT WINAPI
IContextMenu_GetCommandString(LPCONTEXTMENU
, UINT32
,UINT32
,LPUINT32
,LPSTR
,UINT32
);
23 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
, UINT32
, WPARAM32
, LPARAM
);
25 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
, DWORD
);
26 void IContextMenu_FreePidlTable(LPCONTEXTMENU
);
27 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
);
28 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
, LPCITEMIDLIST
*, UINT32
);
30 static struct IContextMenu_VTable cmvt
=
31 { IContextMenu_QueryInterface
,
34 IContextMenu_QueryContextMenu
,
35 IContextMenu_InvokeCommand
,
36 IContextMenu_GetCommandString
,
37 IContextMenu_HandleMenuMsg
,
38 (void *) 0xdeadbabe /* just paranoia */
40 /**************************************************************************
41 * IContextMenu_QueryInterface
43 static HRESULT WINAPI
IContextMenu_QueryInterface(LPCONTEXTMENU
this,REFIID riid
, LPVOID
*ppvObj
)
45 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
46 TRACE(shell
,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid
,ppvObj
);
50 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
51 { *ppvObj
= (LPUNKNOWN
)(LPCONTEXTMENU
)this;
53 else if(IsEqualIID(riid
, &IID_IContextMenu
)) /*IContextMenu*/
54 { *ppvObj
= (LPCONTEXTMENU
)this;
56 else if(IsEqualIID(riid
, &IID_IShellExtInit
)) /*IShellExtInit*/
57 { *ppvObj
= (LPSHELLEXTINIT
)this;
58 WARN(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);
77 /**************************************************************************
78 * IContextMenu_Release
80 static ULONG WINAPI
IContextMenu_Release(LPCONTEXTMENU
this)
81 { TRACE(shell
,"(%p)->()\n",this);
83 { TRACE(shell
," destroying IContextMenu(%p)\n",this);
86 this->pSFParent
->lpvtbl
->fnRelease(this->pSFParent
);
88 /*make sure the pidl is freed*/
90 { IContextMenu_FreePidlTable(this);
94 HeapFree(GetProcessHeap(),0,this);
100 /**************************************************************************
101 * IContextMenu_Constructor()
103 LPCONTEXTMENU
IContextMenu_Constructor(LPSHELLFOLDER pSFParent
, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
107 cm
= (LPCONTEXTMENU
)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu
));
111 cm
->pSFParent
= pSFParent
;
113 cm
->pSFParent
->lpvtbl
->fnAddRef(cm
->pSFParent
);
117 IContextMenu_AllocPidlTable(cm
, uItemCount
);
120 { IContextMenu_FillPidlTable(cm
, aPidls
, uItemCount
);
124 for(u
= 0; u
< uItemCount
; u
++)
125 { cm
->bAllValues
&= (_ILIsValue(aPidls
[u
]) ? 1 : 0);
127 TRACE(shell
,"(%p)->()\n",cm
);
130 /**************************************************************************
133 static void ICM_InsertItem (HMENU32 hmenu
, UINT32 indexMenu
, UINT32 wID
, UINT32 fType
, LPSTR dwTypeData
, UINT32 fState
)
134 { MENUITEMINFO32A mii
;
136 ZeroMemory(&mii
, sizeof(mii
));
137 mii
.cbSize
= sizeof(mii
);
138 if (fType
== MFT_SEPARATOR
)
139 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
142 { mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
143 mii
.dwTypeData
= dwTypeData
;
144 mii
.fState
= MFS_ENABLED
| MFS_DEFAULT
;
148 InsertMenuItem32A( hmenu
, indexMenu
, TRUE
, &mii
);
150 /**************************************************************************
151 * IContextMenu_QueryContextMenu()
154 static HRESULT WINAPI
IContextMenu_QueryContextMenu( LPCONTEXTMENU
this, HMENU32 hmenu
,
155 UINT32 indexMenu
,UINT32 idCmdFirst
,UINT32 idCmdLast
,UINT32 uFlags
)
158 TRACE(shell
,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",this, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
160 if(!(CMF_DEFAULTONLY
& uFlags
))
161 { if(!this->bAllValues
)
162 { fExplore
= uFlags
& CMF_EXPLORE
;
164 { ICM_InsertItem(hmenu
, indexMenu
++, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, TEXT("&Explore"), MFS_ENABLED
|MFS_DEFAULT
);
165 ICM_InsertItem(hmenu
, indexMenu
++, idCmdFirst
+IDM_OPEN
, MFT_STRING
, TEXT("&Open"), MFS_ENABLED
);
168 { ICM_InsertItem(hmenu
, indexMenu
++, idCmdFirst
+IDM_OPEN
, MFT_STRING
, TEXT("&Open"), MFS_ENABLED
|MFS_DEFAULT
);
169 ICM_InsertItem(hmenu
, indexMenu
++, idCmdFirst
+IDM_EXPLORE
, MFT_STRING
, TEXT("&Explore"), MFS_ENABLED
);
172 if(uFlags
& CMF_CANRENAME
)
173 { ICM_InsertItem(hmenu
, indexMenu
++, 0, MFT_SEPARATOR
, NULL
, 0);
174 ICM_InsertItem(hmenu
, indexMenu
++, idCmdFirst
+IDM_RENAME
, MFT_STRING
, TEXT("&Rename"), (IContextMenu_CanRenameItems(this) ? MFS_ENABLED
: MFS_DISABLED
));
177 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, (IDM_LAST
+ 1));
179 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
182 /**************************************************************************
183 * IContextMenu_InvokeCommand()
185 static HRESULT WINAPI
IContextMenu_InvokeCommand(LPCONTEXTMENU
this, LPCMINVOKECOMMANDINFO32 lpcmi
)
186 { LPITEMIDLIST pidlTemp
,pidlFQ
;
187 SHELLEXECUTEINFO32A sei
;
190 TRACE(shell
,"(%p)->(invcom=%p verb=%p)\n",this,lpcmi
,lpcmi
->lpVerb
);
192 if(HIWORD(lpcmi
->lpVerb
))
193 { //the command is being sent via a verb
197 if(LOWORD(lpcmi
->lpVerb
) > IDM_LAST
)
200 switch(LOWORD(lpcmi
->lpVerb
))
203 /* Find the first item in the list that is not a value. These commands
204 should never be invoked if there isn't at least one folder item in the list.*/
206 for(i
= 0; this->aPidls
[i
]; i
++)
207 { if(!_ILIsValue(this->aPidls
[i
]))
211 pidlTemp
= ILCombine(this->pSFParent
->mpidl
, this->aPidls
[i
]);
212 pidlFQ
= ILCombine(this->pSFParent
->mpidlNSRoot
, pidlTemp
);
215 ZeroMemory(&sei
, sizeof(sei
));
216 sei
.cbSize
= sizeof(sei
);
217 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
218 sei
.lpIDList
= pidlFQ
;
219 sei
.lpClass
= TEXT("folder");
220 sei
.hwnd
= lpcmi
->hwnd
;
221 sei
.nShow
= SW_SHOWNORMAL
;
223 if(LOWORD(lpcmi
->lpVerb
) == IDM_EXPLORE
)
224 { sei
.lpVerb
= TEXT("explore");
227 { sei
.lpVerb
= TEXT("open");
229 ShellExecuteEx32A(&sei
);
234 MessageBeep32(MB_OK
);
235 /*handle rename for the view here*/
241 /**************************************************************************
242 * IContextMenu_GetCommandString()
244 static HRESULT WINAPI
IContextMenu_GetCommandString( LPCONTEXTMENU
this, UINT32 idCommand
,
245 UINT32 uFlags
,LPUINT32 lpReserved
,LPSTR lpszName
,UINT32 uMaxNameLen
)
246 { HRESULT hr
= E_INVALIDARG
;
248 TRACE(shell
,"(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",this, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
258 strcpy((LPSTR
)lpszName
, "rename");
264 /* NT 4.0 with IE 3.0x or no IE will always call this with GCS_VERBW. In this
265 case, you need to do the lstrcpyW to the pointer passed.*/
269 lstrcpyAtoW((LPWSTR
)lpszName
, "rename");
279 TRACE(shell
,"-- (%p)->(name=%s)\n",this, lpszName
);
282 /**************************************************************************
283 * IContextMenu_HandleMenuMsg()
285 * should be only in IContextMenu2 and IContextMenu3
286 * is nevertheless called from word95
288 static HRESULT WINAPI
IContextMenu_HandleMenuMsg(LPCONTEXTMENU
this, UINT32 uMsg
,WPARAM32 wParam
,LPARAM lParam
)
289 { TRACE(shell
,"(%p)->(msg=%x wp=%x lp=%lx)\n",this, uMsg
, wParam
, lParam
);
292 /**************************************************************************
293 * IContextMenu_AllocPidlTable()
295 BOOL32
IContextMenu_AllocPidlTable(LPCONTEXTMENU
this, DWORD dwEntries
)
296 { //add one for NULL terminator
297 TRACE(shell
,"(%p)->(entrys=%lu)\n",this, dwEntries
);
300 this->aPidls
= (LPITEMIDLIST
*)SHAlloc(dwEntries
* sizeof(LPITEMIDLIST
));
303 { ZeroMemory(this->aPidls
, dwEntries
* sizeof(LPITEMIDLIST
)); /*set all of the entries to NULL*/
305 return (this->aPidls
!= NULL
);
308 /**************************************************************************
309 * IContextMenu_FreePidlTable()
311 void IContextMenu_FreePidlTable(LPCONTEXTMENU
this)
314 TRACE(shell
,"(%p)->()\n",this);
317 { for(i
= 0; this->aPidls
[i
]; i
++)
318 { SHFree(this->aPidls
[i
]);
321 SHFree(this->aPidls
);
326 /**************************************************************************
327 * IContextMenu_FillPidlTable()
329 BOOL32
IContextMenu_FillPidlTable(LPCONTEXTMENU
this, LPCITEMIDLIST
*aPidls
, UINT32 uItemCount
)
331 TRACE(shell
,"(%p)->(apidl=%p count=%u)\n",this, aPidls
, uItemCount
);
333 { for(i
= 0; i
< uItemCount
; i
++)
334 { this->aPidls
[i
] = ILClone(aPidls
[i
]);
341 /**************************************************************************
342 * IContextMenu_CanRenameItems()
344 BOOL32
IContextMenu_CanRenameItems(LPCONTEXTMENU
this)
348 TRACE(shell
,"(%p)->()\n",this);
351 { for(i
= 0; this->aPidls
[i
]; i
++){} /*get the number of items assigned to this object*/
352 if(i
> 1) /*you can't rename more than one item at a time*/
355 dwAttributes
= SFGAO_CANRENAME
;
356 this->pSFParent
->lpvtbl
->fnGetAttributesOf(this->pSFParent
, i
,
357 (LPCITEMIDLIST
*)this->aPidls
, &dwAttributes
);
359 return dwAttributes
& SFGAO_CANRENAME
;