Added window text to the output generated by walk wnd debugger
[wine.git] / dlls / shell32 / contmenu.c
blob9bca626b69e85bafdcde60ffa37fdffd8081c443
1 /*
2 * IContextMenu
4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
5 */
6 #include "windows.h"
7 #include "winerror.h"
8 #include "debug.h"
9 #include "pidl.h"
10 #include "shlobj.h"
11 #include "shell32_main.h"
13 #define __T(x) x
14 #define _T(x) __T(x)
15 #define TEXT _T
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,
32 IContextMenu_AddRef,
33 IContextMenu_Release,
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)
44 { char xriid[50];
45 WINE_StringFromCLSID((LPCLSID)riid,xriid);
46 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
48 *ppvObj = NULL;
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");
61 if(*ppvObj)
62 { (*(LPCONTEXTMENU *)ppvObj)->lpvtbl->fnAddRef(this);
63 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
64 return S_OK;
66 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
67 return E_NOINTERFACE;
70 /**************************************************************************
71 * IContextMenu_AddRef
73 static ULONG WINAPI IContextMenu_AddRef(LPCONTEXTMENU this)
74 { TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
75 return ++(this->ref);
77 /**************************************************************************
78 * IContextMenu_Release
80 static ULONG WINAPI IContextMenu_Release(LPCONTEXTMENU this)
81 { TRACE(shell,"(%p)->()\n",this);
82 if (!--(this->ref))
83 { TRACE(shell," destroying IContextMenu(%p)\n",this);
85 if(this->pSFParent)
86 this->pSFParent->lpvtbl->fnRelease(this->pSFParent);
88 /*make sure the pidl is freed*/
89 if(this->aPidls)
90 { IContextMenu_FreePidlTable(this);
94 HeapFree(GetProcessHeap(),0,this);
95 return 0;
97 return this->ref;
100 /**************************************************************************
101 * IContextMenu_Constructor()
103 LPCONTEXTMENU IContextMenu_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST *aPidls, UINT32 uItemCount)
104 { LPCONTEXTMENU cm;
105 UINT32 u;
107 cm = (LPCONTEXTMENU)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu));
108 cm->lpvtbl=&cmvt;
109 cm->ref = 1;
111 cm->pSFParent = pSFParent;
112 if(cm->pSFParent)
113 cm->pSFParent->lpvtbl->fnAddRef(cm->pSFParent);
115 cm->aPidls = NULL;
117 IContextMenu_AllocPidlTable(cm, uItemCount);
119 if(cm->aPidls)
120 { IContextMenu_FillPidlTable(cm, aPidls, uItemCount);
123 cm->bAllValues = 1;
124 for(u = 0; u < uItemCount; u++)
125 { cm->bAllValues &= (_ILIsValue(aPidls[u]) ? 1 : 0);
127 TRACE(shell,"(%p)->()\n",cm);
128 return cm;
130 /**************************************************************************
131 * ICM_InsertItem()
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;
141 else
142 { mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
143 mii.dwTypeData = dwTypeData;
144 mii.fState = MFS_ENABLED | MFS_DEFAULT;
146 mii.wID = wID;
147 mii.fType = fType;
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)
156 { BOOL32 fExplore ;
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;
163 if(fExplore)
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);
167 else
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;
188 int i;
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
194 return NOERROR;
197 if(LOWORD(lpcmi->lpVerb) > IDM_LAST)
198 return E_INVALIDARG;
200 switch(LOWORD(lpcmi->lpVerb))
201 { case IDM_EXPLORE:
202 case IDM_OPEN:
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]))
208 break;
211 pidlTemp = ILCombine(this->pSFParent->mpidl, this->aPidls[i]);
212 pidlFQ = ILCombine(this->pSFParent->mpidlNSRoot, pidlTemp);
213 SHFree(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");
226 else
227 { sei.lpVerb = TEXT("open");
229 ShellExecuteEx32A(&sei);
230 SHFree(pidlFQ);
231 break;
233 case IDM_RENAME:
234 MessageBeep32(MB_OK);
235 /*handle rename for the view here*/
236 break;
238 return NOERROR;
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);
250 switch(uFlags)
251 { case GCS_HELPTEXT:
252 hr = E_NOTIMPL;
253 break;
255 case GCS_VERBA:
256 switch(idCommand)
257 { case IDM_RENAME:
258 strcpy((LPSTR)lpszName, "rename");
259 hr = NOERROR;
260 break;
262 break;
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.*/
266 case GCS_VERBW:
267 switch(idCommand)
268 { case IDM_RENAME:
269 lstrcpyAtoW((LPWSTR)lpszName, "rename");
270 hr = NOERROR;
271 break;
273 break;
275 case GCS_VALIDATE:
276 hr = NOERROR;
277 break;
279 TRACE(shell,"-- (%p)->(name=%s)\n",this, lpszName);
280 return hr;
282 /**************************************************************************
283 * IContextMenu_HandleMenuMsg()
284 * NOTES
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);
290 return E_NOTIMPL;
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);
298 dwEntries++;
300 this->aPidls = (LPITEMIDLIST*)SHAlloc(dwEntries * sizeof(LPITEMIDLIST));
302 if(this->aPidls)
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)
312 { int i;
314 TRACE(shell,"(%p)->()\n",this);
316 if(this->aPidls)
317 { for(i = 0; this->aPidls[i]; i++)
318 { SHFree(this->aPidls[i]);
321 SHFree(this->aPidls);
322 this->aPidls = NULL;
326 /**************************************************************************
327 * IContextMenu_FillPidlTable()
329 BOOL32 IContextMenu_FillPidlTable(LPCONTEXTMENU this, LPCITEMIDLIST *aPidls, UINT32 uItemCount)
330 { UINT32 i;
331 TRACE(shell,"(%p)->(apidl=%p count=%u)\n",this, aPidls, uItemCount);
332 if(this->aPidls)
333 { for(i = 0; i < uItemCount; i++)
334 { this->aPidls[i] = ILClone(aPidls[i]);
336 return TRUE;
338 return FALSE;
341 /**************************************************************************
342 * IContextMenu_CanRenameItems()
344 BOOL32 IContextMenu_CanRenameItems(LPCONTEXTMENU this)
345 { UINT32 i;
346 DWORD dwAttributes;
348 TRACE(shell,"(%p)->()\n",this);
350 if(this->aPidls)
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*/
353 { return FALSE;
355 dwAttributes = SFGAO_CANRENAME;
356 this->pSFParent->lpvtbl->fnGetAttributesOf(this->pSFParent, i,
357 (LPCITEMIDLIST*)this->aPidls, &dwAttributes);
359 return dwAttributes & SFGAO_CANRENAME;
361 return FALSE;