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;