source: trunk/src/shell32/new/contmenu.cpp@ 1036

Last change on this file since 1036 was 791, checked in by phaller, 26 years ago

Add: shell32/new - a direct port of WINE's Shell32 implmentation

File size: 11.9 KB
Line 
1/*
2 * IContextMenu
3 *
4 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
5 */
6#include <string.h>
7#include <odin.h>
8
9#define ICOM_CINTERFACE 1
10#define CINTERFACE 1
11
12
13#include "winerror.h"
14#include "debugtools.h"
15
16#include "pidl.h"
17#include "wine/obj_base.h"
18#include "wine/obj_contextmenu.h"
19#include "wine/obj_shellbrowser.h"
20#include "wine/obj_shellextinit.h"
21#include "wine/undocshell.h"
22
23#include "shell32_main.h"
24
25#include <heapstring.h>
26#include <misc.h>
27
28DEFAULT_DEBUG_CHANNEL(shell)
29
30/**************************************************************************
31* IContextMenu VTable
32*
33*/
34
35static HRESULT WINAPI IContextMenu_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj);
36static ULONG WINAPI IContextMenu_fnAddRef(IContextMenu *iface);
37static ULONG WINAPI IContextMenu_fnRelease(IContextMenu *iface);
38static HRESULT WINAPI IContextMenu_fnQueryContextMenu(IContextMenu *iface, HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
39static HRESULT WINAPI IContextMenu_fnInvokeCommand(IContextMenu *iface, LPCMINVOKECOMMANDINFO lpcmi);
40static HRESULT WINAPI IContextMenu_fnGetCommandString(IContextMenu *iface, UINT idCommand, UINT uFlags, LPUINT lpReserved, LPSTR lpszName, UINT uMaxNameLen);
41static HRESULT WINAPI IContextMenu_fnHandleMenuMsg(IContextMenu *iface, UINT uMsg, WPARAM wParam, LPARAM lParam);
42
43static struct ICOM_VTABLE(IContextMenu) cmvt =
44{
45 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
46 IContextMenu_fnQueryInterface,
47 IContextMenu_fnAddRef,
48 IContextMenu_fnRelease,
49 IContextMenu_fnQueryContextMenu,
50 IContextMenu_fnInvokeCommand,
51 IContextMenu_fnGetCommandString,
52 IContextMenu_fnHandleMenuMsg,
53 (void *) 0xdeadbabe /* just paranoia */
54};
55
56/**************************************************************************
57* IContextMenu Implementation
58*/
59typedef struct
60{ ICOM_VTABLE(IContextMenu)* lpvtbl;
61 DWORD ref;
62 IShellFolder* pSFParent;
63 LPITEMIDLIST pidl; /* root pidl */
64 LPITEMIDLIST *aPidls; /* array of child pidls */
65 BOOL bAllValues;
66} IContextMenuImpl;
67
68
69//static struct ICOM_VTABLE(IContextMenu) cmvt;
70
71/**************************************************************************
72* IContextMenu_AllocPidlTable()
73*/
74static BOOL IContextMenu_AllocPidlTable(IContextMenuImpl *This, DWORD dwEntries)
75{
76 TRACE("(%p)->(entrys=%lu)\n",This, dwEntries);
77
78 /*add one for NULL terminator */
79 dwEntries++;
80
81 This->aPidls = (LPITEMIDLIST*)SHAlloc(dwEntries * sizeof(LPITEMIDLIST));
82
83 if(This->aPidls)
84 { ZeroMemory(This->aPidls, dwEntries * sizeof(LPITEMIDLIST)); /*set all of the entries to NULL*/
85 }
86 return (This->aPidls != NULL);
87}
88
89/**************************************************************************
90* IContextMenu_FreePidlTable()
91*/
92static void IContextMenu_FreePidlTable(IContextMenuImpl *This)
93{
94 int i;
95
96 TRACE("(%p)->()\n",This);
97
98 if(This->aPidls)
99 { for(i = 0; This->aPidls[i]; i++)
100 { SHFree(This->aPidls[i]);
101 }
102
103 SHFree(This->aPidls);
104 This->aPidls = NULL;
105 }
106}
107
108/**************************************************************************
109* IContextMenu_FillPidlTable()
110*/
111static BOOL IContextMenu_FillPidlTable(IContextMenuImpl *This, LPCITEMIDLIST *aPidls, UINT uItemCount)
112{
113 UINT i;
114
115 TRACE("(%p)->(apidl=%p count=%u)\n",This, aPidls, uItemCount);
116
117 if(This->aPidls)
118 { for(i = 0; i < uItemCount; i++)
119 { This->aPidls[i] = ILClone(aPidls[i]);
120 }
121 return TRUE;
122 }
123 return FALSE;
124}
125
126/**************************************************************************
127* IContextMenu_CanRenameItems()
128*/
129static BOOL IContextMenu_CanRenameItems(IContextMenuImpl *This)
130{ UINT i;
131 DWORD dwAttributes;
132
133 TRACE("(%p)->()\n",This);
134
135 if(This->aPidls)
136 {
137 for(i = 0; This->aPidls[i]; i++){} /*get the number of items assigned to This object*/
138 { if(i > 1) /*you can't rename more than one item at a time*/
139 { return FALSE;
140 }
141 }
142 dwAttributes = SFGAO_CANRENAME;
143 IShellFolder_GetAttributesOf(This->pSFParent, i, (LPCITEMIDLIST*)This->aPidls, &dwAttributes);
144
145 return dwAttributes & SFGAO_CANRENAME;
146 }
147 return FALSE;
148}
149
150/**************************************************************************
151* IContextMenu_Constructor()
152*/
153IContextMenu *IContextMenu_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, LPCITEMIDLIST *aPidls, UINT uItemCount)
154{ IContextMenuImpl* cm;
155 UINT u;
156
157 cm = (IContextMenuImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenuImpl));
158 cm->lpvtbl=&cmvt;
159 cm->ref = 1;
160 cm->pidl = ILClone(pidl);
161
162 cm->pSFParent = pSFParent;
163
164 if(pSFParent)
165 IShellFolder_AddRef(pSFParent);
166
167 cm->aPidls = NULL;
168
169 IContextMenu_AllocPidlTable(cm, uItemCount);
170
171 if(cm->aPidls)
172 { IContextMenu_FillPidlTable(cm, aPidls, uItemCount);
173 }
174
175 cm->bAllValues = 1;
176 for(u = 0; u < uItemCount; u++)
177 { cm->bAllValues &= (_ILIsValue(aPidls[u]) ? 1 : 0);
178 }
179 TRACE("(%p)->()\n",cm);
180 shell32_ObjCount++;
181 return (IContextMenu*)cm;
182}
183
184/**************************************************************************
185* IContextMenu_fnQueryInterface
186*/
187static HRESULT WINAPI IContextMenu_fnQueryInterface(IContextMenu *iface, REFIID riid, LPVOID *ppvObj)
188{
189 ICOM_THIS(IContextMenuImpl, iface);
190
191 char xriid[50];
192 WINE_StringFromCLSID((LPCLSID)riid,xriid);
193
194 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
195
196 *ppvObj = NULL;
197
198 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
199 { *ppvObj = This;
200 }
201 else if(IsEqualIID(riid, &IID_IContextMenu)) /*IContextMenu*/
202 { *ppvObj = This;
203 }
204 else if(IsEqualIID(riid, &IID_IShellExtInit)) /*IShellExtInit*/
205 { FIXME("-- LPSHELLEXTINIT pointer requested\n");
206 }
207
208 if(*ppvObj)
209 {
210 IContextMenu_AddRef((IContextMenu*)*ppvObj);
211 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
212 return S_OK;
213 }
214 TRACE("-- Interface: E_NOINTERFACE\n");
215 return E_NOINTERFACE;
216}
217
218/**************************************************************************
219* IContextMenu_fnAddRef
220*/
221static ULONG WINAPI IContextMenu_fnAddRef(IContextMenu *iface)
222{
223 ICOM_THIS(IContextMenuImpl, iface);
224
225 TRACE("(%p)->(count=%lu)\n",This, This->ref);
226
227 shell32_ObjCount++;
228 return ++(This->ref);
229}
230
231/**************************************************************************
232* IContextMenu_fnRelease
233*/
234static ULONG WINAPI IContextMenu_fnRelease(IContextMenu *iface)
235{
236 ICOM_THIS(IContextMenuImpl, iface);
237
238 TRACE("(%p)->()\n",This);
239
240 shell32_ObjCount--;
241
242 if (!--(This->ref))
243 { TRACE(" destroying IContextMenu(%p)\n",This);
244
245 if(This->pSFParent)
246 IShellFolder_Release(This->pSFParent);
247
248 if(This->pidl)
249 SHFree(This->pidl);
250
251 /*make sure the pidl is freed*/
252 if(This->aPidls)
253 { IContextMenu_FreePidlTable(This);
254 }
255
256 HeapFree(GetProcessHeap(),0,This);
257 return 0;
258 }
259 return This->ref;
260}
261
262/**************************************************************************
263* ICM_InsertItem()
264*/
265void WINAPI _InsertMenuItem (
266 HMENU hmenu,
267 UINT indexMenu,
268 BOOL fByPosition,
269 UINT wID,
270 UINT fType,
271 LPSTR dwTypeData,
272 UINT fState)
273{
274 MENUITEMINFOA mii;
275
276 ZeroMemory(&mii, sizeof(mii));
277 mii.cbSize = sizeof(mii);
278 if (fType == MFT_SEPARATOR)
279 { mii.fMask = MIIM_ID | MIIM_TYPE;
280 }
281 else
282 { mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
283 mii.dwTypeData = dwTypeData;
284 mii.fState = fState;
285 }
286 mii.wID = wID;
287 mii.fType = fType;
288 InsertMenuItemA( hmenu, indexMenu, fByPosition, &mii);
289}
290/**************************************************************************
291* IContextMenu_fnQueryContextMenu()
292*/
293
294static HRESULT WINAPI IContextMenu_fnQueryContextMenu(
295 IContextMenu *iface,
296 HMENU hmenu,
297 UINT indexMenu,
298 UINT idCmdFirst,
299 UINT idCmdLast,
300 UINT uFlags)
301{
302 ICOM_THIS(IContextMenuImpl, iface);
303
304 BOOL fExplore ;
305
306 TRACE("(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
307
308 if(!(CMF_DEFAULTONLY & uFlags))
309 { if(!This->bAllValues)
310 { /* folder menu */
311 fExplore = uFlags & CMF_EXPLORE;
312 if(fExplore)
313 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED|MFS_DEFAULT);
314 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED);
315 }
316 else
317 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
318 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_EXPLORE, MFT_STRING, "&Explore", MFS_ENABLED);
319 }
320
321 if(uFlags & CMF_CANRENAME)
322 { _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
323 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
324 }
325 }
326 else /* file menu */
327 { _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_OPEN, MFT_STRING, "&Open", MFS_ENABLED|MFS_DEFAULT);
328 if(uFlags & CMF_CANRENAME)
329 { _InsertMenuItem(hmenu, indexMenu++, TRUE, 0, MFT_SEPARATOR, NULL, 0);
330 _InsertMenuItem(hmenu, indexMenu++, TRUE, idCmdFirst+IDM_RENAME, MFT_STRING, "&Rename", (IContextMenu_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED));
331 }
332 }
333 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (IDM_LAST + 1));
334 }
335 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
336}
337
338/**************************************************************************
339* IContextMenu_fnInvokeCommand()
340*/
341static HRESULT WINAPI IContextMenu_fnInvokeCommand(
342 IContextMenu *iface,
343 LPCMINVOKECOMMANDINFO lpcmi)
344{
345 ICOM_THIS(IContextMenuImpl, iface);
346
347 LPITEMIDLIST pidlFQ;
348 SHELLEXECUTEINFOA sei;
349 int i;
350
351 TRACE("(%p)->(invcom=%p verb=%p wnd=%x)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
352
353 if(LOWORD(lpcmi->lpVerb) > IDM_LAST)
354 return E_INVALIDARG;
355
356 switch(LOWORD(lpcmi->lpVerb))
357 { case IDM_EXPLORE:
358 case IDM_OPEN:
359 /* Find the first item in the list that is not a value. These commands
360 should never be invoked if there isn't at least one folder item in the list.*/
361
362 for(i = 0; This->aPidls[i]; i++)
363 { if(!_ILIsValue(This->aPidls[i]))
364 break;
365 }
366
367 pidlFQ = ILCombine(This->pidl, This->aPidls[i]);
368
369 ZeroMemory(&sei, sizeof(sei));
370 sei.cbSize = sizeof(sei);
371 sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
372 sei.lpIDList = pidlFQ;
373 sei.lpClass = "folder";
374 sei.hwnd = lpcmi->hwnd;
375 sei.nShow = SW_SHOWNORMAL;
376
377 if(LOWORD(lpcmi->lpVerb) == IDM_EXPLORE)
378 { sei.lpVerb = "explore";
379 }
380 else
381 { sei.lpVerb = "open";
382 }
383 ShellExecuteExA(&sei);
384 SHFree(pidlFQ);
385 break;
386
387 case IDM_RENAME:
388 MessageBeep(MB_OK);
389 /*handle rename for the view here*/
390 break;
391 }
392 return NOERROR;
393}
394
395/**************************************************************************
396* IContextMenu_fnGetCommandString()
397*/
398static HRESULT WINAPI IContextMenu_fnGetCommandString(
399 IContextMenu *iface,
400 UINT idCommand,
401 UINT uFlags,
402 LPUINT lpReserved,
403 LPSTR lpszName,
404 UINT uMaxNameLen)
405{
406 ICOM_THIS(IContextMenuImpl, iface);
407
408 HRESULT hr = E_INVALIDARG;
409
410 TRACE("(%p)->(idcom=%x flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
411
412 switch(uFlags)
413 { case GCS_HELPTEXT:
414 hr = E_NOTIMPL;
415 break;
416
417 case GCS_VERBA:
418 switch(idCommand)
419 { case IDM_RENAME:
420 strcpy((LPSTR)lpszName, "rename");
421 hr = NOERROR;
422 break;
423 }
424 break;
425
426 /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
427 case, you need to do the lstrcpyW to the pointer passed.*/
428 case GCS_VERBW:
429 switch(idCommand)
430 { case IDM_RENAME:
431 lstrcpyAtoW((LPWSTR)lpszName, "rename");
432 hr = NOERROR;
433 break;
434 }
435 break;
436
437 case GCS_VALIDATE:
438 hr = NOERROR;
439 break;
440 }
441 TRACE("-- (%p)->(name=%s)\n",This, lpszName);
442 return hr;
443}
444
445/**************************************************************************
446* IContextMenu_fnHandleMenuMsg()
447* NOTES
448* should be only in IContextMenu2 and IContextMenu3
449* is nevertheless called from word95
450*/
451static HRESULT WINAPI IContextMenu_fnHandleMenuMsg(
452 IContextMenu *iface,
453 UINT uMsg,
454 WPARAM wParam,
455 LPARAM lParam)
456{
457 ICOM_THIS(IContextMenuImpl, iface);
458
459 TRACE("(%p)->(msg=%x wp=%x lp=%lx)\n",This, uMsg, wParam, lParam);
460
461 return E_NOTIMPL;
462}
463
Note: See TracBrowser for help on using the repository browser.