source: trunk/src/shell32/contmenu.cpp@ 1330

Last change on this file since 1330 was 1214, checked in by sandervl, 26 years ago

Moved new shell32 to current dir

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