dbghelp: When unwinding i386 stacks, update CONTEXT with sp/bp/ip.
[wine] / dlls / shell32 / shv_item_cmenu.c
1 /*
2  *      IContextMenu for items in the shellview
3  *
4  * Copyright 1998, 2000 Juergen Schmied <juergen.schmied@debitel.net>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <string.h>
22
23 #define COBJMACROS
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26
27 #include "winerror.h"
28 #include "wine/debug.h"
29
30 #include "windef.h"
31 #include "wingdi.h"
32 #include "pidl.h"
33 #include "undocshell.h"
34 #include "shlobj.h"
35 #include "winreg.h"
36 #include "prsht.h"
37
38 #include "shell32_main.h"
39 #include "shellfolder.h"
40
41 #include "shresdef.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(shell);
44
45 /**************************************************************************
46 *  IContextMenu Implementation
47 */
48 typedef struct
49 {       const IContextMenu2Vtbl *lpVtbl;
50         LONG            ref;
51         IShellFolder*   pSFParent;
52         LPITEMIDLIST    pidl;           /* root pidl */
53         LPITEMIDLIST    *apidl;         /* array of child pidls */
54         UINT            cidl;
55         BOOL            bAllValues;
56 } ItemCmImpl;
57
58
59 static const IContextMenu2Vtbl cmvt;
60
61 /**************************************************************************
62 * ISvItemCm_CanRenameItems()
63 */
64 static BOOL ISvItemCm_CanRenameItems(ItemCmImpl *This)
65 {       UINT  i;
66         DWORD dwAttributes;
67
68         TRACE("(%p)->()\n",This);
69
70         if(This->apidl)
71         {
72           for(i = 0; i < This->cidl; i++){}
73           if(i > 1) return FALSE;               /* can't rename more than one item at a time*/
74           dwAttributes = SFGAO_CANRENAME;
75           IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)This->apidl, &dwAttributes);
76           return dwAttributes & SFGAO_CANRENAME;
77         }
78         return FALSE;
79 }
80
81 /**************************************************************************
82 *   ISvItemCm_Constructor()
83 */
84 IContextMenu2 *ISvItemCm_Constructor(LPSHELLFOLDER pSFParent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl)
85 {       ItemCmImpl* cm;
86         UINT  u;
87
88         cm = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ItemCmImpl));
89         cm->lpVtbl = &cmvt;
90         cm->ref = 1;
91         cm->pidl = ILClone(pidl);
92         cm->pSFParent = pSFParent;
93
94         if(pSFParent) IShellFolder_AddRef(pSFParent);
95
96         cm->apidl = _ILCopyaPidl(apidl, cidl);
97         cm->cidl = cidl;
98
99         cm->bAllValues = 1;
100         for(u = 0; u < cidl; u++)
101         {
102           cm->bAllValues &= (_ILIsValue(apidl[u]) ? 1 : 0);
103         }
104
105         TRACE("(%p)->()\n",cm);
106
107         return (IContextMenu2*)cm;
108 }
109
110 /**************************************************************************
111 *  ISvItemCm_fnQueryInterface
112 */
113 static HRESULT WINAPI ISvItemCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj)
114 {
115         ItemCmImpl *This = (ItemCmImpl *)iface;
116
117         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
118
119         *ppvObj = NULL;
120
121         if(IsEqualIID(riid, &IID_IUnknown) ||
122            IsEqualIID(riid, &IID_IContextMenu) ||
123            IsEqualIID(riid, &IID_IContextMenu2))
124         {
125           *ppvObj = This;
126         }
127         else if(IsEqualIID(riid, &IID_IShellExtInit))  /*IShellExtInit*/
128         {
129           FIXME("-- LPSHELLEXTINIT pointer requested\n");
130         }
131
132         if(*ppvObj)
133         {
134           IUnknown_AddRef((IUnknown*)*ppvObj);
135           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
136           return S_OK;
137         }
138         TRACE("-- Interface: E_NOINTERFACE\n");
139         return E_NOINTERFACE;
140 }
141
142 /**************************************************************************
143 *  ISvItemCm_fnAddRef
144 */
145 static ULONG WINAPI ISvItemCm_fnAddRef(IContextMenu2 *iface)
146 {
147         ItemCmImpl *This = (ItemCmImpl *)iface;
148         ULONG refCount = InterlockedIncrement(&This->ref);
149
150         TRACE("(%p)->(count=%u)\n", This, refCount - 1);
151
152         return refCount;
153 }
154
155 /**************************************************************************
156 *  ISvItemCm_fnRelease
157 */
158 static ULONG WINAPI ISvItemCm_fnRelease(IContextMenu2 *iface)
159 {
160         ItemCmImpl *This = (ItemCmImpl *)iface;
161         ULONG refCount = InterlockedDecrement(&This->ref);
162
163         TRACE("(%p)->(count=%i)\n", This, refCount + 1);
164
165         if (!refCount)
166         {
167           TRACE(" destroying IContextMenu(%p)\n",This);
168
169           if(This->pSFParent)
170             IShellFolder_Release(This->pSFParent);
171
172           SHFree(This->pidl);
173
174           /*make sure the pidl is freed*/
175           _ILFreeaPidl(This->apidl, This->cidl);
176
177           HeapFree(GetProcessHeap(),0,This);
178         }
179         return refCount;
180 }
181
182 static void _InsertMenuItemW (
183         HMENU hmenu,
184         UINT indexMenu,
185         BOOL fByPosition,
186         UINT wID,
187         UINT fType,
188         LPWSTR dwTypeData,
189         UINT fState)
190 {
191         MENUITEMINFOW   mii;
192
193         mii.cbSize = sizeof(mii);
194         if (fType == MFT_SEPARATOR)
195         {
196           mii.fMask = MIIM_ID | MIIM_TYPE;
197         }
198         else
199         {
200           mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
201           mii.dwTypeData = dwTypeData;
202           mii.fState = fState;
203         }
204         mii.wID = wID;
205         mii.fType = fType;
206         InsertMenuItemW( hmenu, indexMenu, fByPosition, &mii);
207 }
208
209 /**************************************************************************
210 * ISvItemCm_fnQueryContextMenu()
211 */
212 static HRESULT WINAPI ISvItemCm_fnQueryContextMenu(
213         IContextMenu2 *iface,
214         HMENU hmenu,
215         UINT indexMenu,
216         UINT idCmdFirst,
217         UINT idCmdLast,
218         UINT uFlags)
219 {
220         ItemCmImpl *This = (ItemCmImpl *)iface;
221
222         TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
223
224         if (idCmdFirst != 0)
225           FIXME("We should use idCmdFirst=%d and idCmdLast=%d for command ids\n", idCmdFirst, idCmdLast);
226
227         if(!(CMF_DEFAULTONLY & uFlags) && This->cidl>0)
228         {
229           HMENU hmenures = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(MENU_SHV_FILE));
230
231           if(uFlags & CMF_EXPLORE)
232             RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
233
234           Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
235
236           DestroyMenu(hmenures);
237
238           if(This->bAllValues)
239           {
240             MENUITEMINFOW mi;
241             WCHAR str[255];
242             mi.cbSize = sizeof(mi);
243             mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
244             mi.dwTypeData = str;
245             mi.cch = 255;
246             GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE, MF_BYCOMMAND, &mi);
247             RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE, MF_BYCOMMAND);
248             _InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, FCIDM_SHVIEW_EXPLORE, MFT_STRING, str, MFS_ENABLED);
249           }
250
251           SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
252
253           if(uFlags & ~CMF_CANRENAME)
254             RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND);
255           else
256             EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND | ISvItemCm_CanRenameItems(This) ? MFS_ENABLED : MFS_DISABLED);
257
258           return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (FCIDM_SHVIEWLAST));
259         }
260         return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
261 }
262
263 /**************************************************************************
264 * DoOpenExplore
265 *
266 *  for folders only
267 */
268
269 static void DoOpenExplore(
270         IContextMenu2 *iface,
271         HWND hwnd,
272         LPCSTR verb)
273 {
274         ItemCmImpl *This = (ItemCmImpl *)iface;
275
276         UINT i, bFolderFound = FALSE;
277         LPITEMIDLIST    pidlFQ;
278         SHELLEXECUTEINFOA       sei;
279
280         /* Find the first item in the list that is not a value. These commands
281             should never be invoked if there isn't at least one folder item in the list.*/
282
283         for(i = 0; i<This->cidl; i++)
284         {
285           if(!_ILIsValue(This->apidl[i]))
286           {
287             bFolderFound = TRUE;
288             break;
289           }
290         }
291
292         if (!bFolderFound) return;
293
294         pidlFQ = ILCombine(This->pidl, This->apidl[i]);
295
296         ZeroMemory(&sei, sizeof(sei));
297         sei.cbSize = sizeof(sei);
298         sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
299         sei.lpIDList = pidlFQ;
300         sei.lpClass = "Folder";
301         sei.hwnd = hwnd;
302         sei.nShow = SW_SHOWNORMAL;
303         sei.lpVerb = verb;
304         ShellExecuteExA(&sei);
305         SHFree(pidlFQ);
306 }
307
308 /**************************************************************************
309 * DoRename
310 */
311 static void DoRename(
312         IContextMenu2 *iface,
313         HWND hwnd)
314 {
315         ItemCmImpl *This = (ItemCmImpl *)iface;
316
317         LPSHELLBROWSER  lpSB;
318         LPSHELLVIEW     lpSV;
319
320         TRACE("(%p)->(wnd=%p)\n",This, hwnd);
321
322         /* get the active IShellView */
323         if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
324         {
325           if(SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
326           {
327             TRACE("(sv=%p)\n",lpSV);
328             IShellView_SelectItem(lpSV, This->apidl[0],
329               SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
330             IShellView_Release(lpSV);
331           }
332         }
333 }
334
335 /**************************************************************************
336  * DoDelete
337  *
338  * deletes the currently selected items
339  */
340 static void DoDelete(IContextMenu2 *iface)
341 {
342         ItemCmImpl *This = (ItemCmImpl *)iface;
343         ISFHelper * psfhlp;
344
345         IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlp);
346         if (psfhlp)
347         {
348           ISFHelper_DeleteItems(psfhlp, This->cidl, (LPCITEMIDLIST *)This->apidl);
349           ISFHelper_Release(psfhlp);
350         }
351 }
352
353 /**************************************************************************
354  * DoCopyOrCut
355  *
356  * copies the currently selected items into the clipboard
357  */
358 static BOOL DoCopyOrCut(
359         IContextMenu2 *iface,
360         HWND hwnd,
361         BOOL bCut)
362 {
363         ItemCmImpl *This = (ItemCmImpl *)iface;
364
365         LPSHELLBROWSER  lpSB;
366         LPSHELLVIEW     lpSV;
367         LPDATAOBJECT    lpDo;
368
369         TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut);
370
371         /* get the active IShellView */
372         if ((lpSB = (LPSHELLBROWSER)SendMessageA(hwnd, CWM_GETISHELLBROWSER,0,0)))
373         {
374           if (SUCCEEDED(IShellBrowser_QueryActiveShellView(lpSB, &lpSV)))
375           {
376             if (SUCCEEDED(IShellView_GetItemObject(lpSV, SVGIO_SELECTION, &IID_IDataObject, (LPVOID*)&lpDo)))
377             {
378               OleSetClipboard(lpDo);
379               IDataObject_Release(lpDo);
380             }
381             IShellView_Release(lpSV);
382           }
383         }
384         return TRUE;
385 }
386
387 /**************************************************************************
388  * Properties_AddPropSheetCallback
389  *
390  * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
391  * propertysheet pages from shell extensions.
392  */
393 static BOOL Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
394 {
395         LPPROPSHEETHEADERW psh = (LPPROPSHEETHEADERW) lparam;
396         psh->u3.phpage[psh->nPages++] = hpage;
397
398         return TRUE;
399 }
400
401 /**************************************************************************
402  * DoOpenProperties
403  */
404 static void DoOpenProperties(IContextMenu2 *iface, HWND hwnd)
405 {
406         ItemCmImpl *This = (ItemCmImpl *)iface;
407         static const UINT MAX_PROP_PAGES = 99;
408         static const WCHAR wszFolder[] = {'F','o','l','d','e','r', 0};
409         static const WCHAR wszFiletypeAll[] = {'*',0};
410         LPSHELLFOLDER lpDesktopSF;
411         LPSHELLFOLDER lpSF;
412         LPDATAOBJECT lpDo;
413         WCHAR wszFiletype[MAX_PATH];
414         WCHAR wszFilename[MAX_PATH];
415         PROPSHEETHEADERW psh;
416         HPROPSHEETPAGE hpages[MAX_PROP_PAGES];
417         HPSXA hpsxa;
418         UINT ret;
419
420         TRACE("(%p)->(wnd=%p)\n", This, hwnd);
421
422         ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
423         psh.dwSize = sizeof (PROPSHEETHEADERW);
424         psh.hwndParent = hwnd;
425         psh.dwFlags = PSH_PROPTITLE;
426         psh.nPages = 0;
427         psh.u3.phpage = hpages;
428         psh.u2.nStartPage = 0;
429
430         _ILSimpleGetTextW(This->apidl[0], (LPVOID)&wszFilename, MAX_PATH);
431         psh.pszCaption = (LPCWSTR)&wszFilename;
432
433         /* Find out where to look for the shell extensions */
434         if (_ILIsValue(This->apidl[0]))
435         {
436             char sTemp[64];
437             sTemp[0] = 0;
438             if (_ILGetExtension(This->apidl[0], sTemp, 64))
439             {
440                 HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE);
441                 MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wszFiletype, MAX_PATH);
442             }
443             else
444             {
445                 wszFiletype[0] = 0;
446             }
447         }
448         else if (_ILIsFolder(This->apidl[0]))
449         {
450             lstrcpynW(wszFiletype, wszFolder, 64);
451         }
452         else if (_ILIsSpecialFolder(This->apidl[0]))
453         {
454             LPGUID folderGUID;
455             static const WCHAR wszclsid[] = {'C','L','S','I','D','\\', 0};
456             folderGUID = _ILGetGUIDPointer(This->apidl[0]);
457             lstrcpyW(wszFiletype, wszclsid);
458             StringFromGUID2(folderGUID, &wszFiletype[6], MAX_PATH - 6);
459         }
460         else
461         {
462             FIXME("Requested properties for unknown type.\n");
463             return;
464         }
465
466         /* Get a suitable DataObject for accessing the files */
467         SHGetDesktopFolder(&lpDesktopSF);
468         if (_ILIsPidlSimple(This->pidl))
469         {
470             ret = IShellFolder_GetUIObjectOf(lpDesktopSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
471                                              &IID_IDataObject, NULL, (LPVOID *)&lpDo);
472             IShellFolder_Release(lpDesktopSF);
473         }
474         else
475         {
476             IShellFolder_BindToObject(lpDesktopSF, This->pidl, NULL, &IID_IShellFolder, (LPVOID*) &lpSF);
477             ret = IShellFolder_GetUIObjectOf(lpSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
478                                              &IID_IDataObject, NULL, (LPVOID *)&lpDo);
479             IShellFolder_Release(lpSF);
480             IShellFolder_Release(lpDesktopSF);
481         }
482
483         if (SUCCEEDED(ret))
484         {
485             hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
486             if (hpsxa != NULL)
487             {
488                 SHAddFromPropSheetExtArray((HPSXA)hpsxa,
489                                            (LPFNADDPROPSHEETPAGE)&Properties_AddPropSheetCallback,
490                                            (LPARAM)&psh);
491                 SHDestroyPropSheetExtArray(hpsxa);
492             }
493             hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletypeAll, MAX_PROP_PAGES - psh.nPages, lpDo);
494             if (hpsxa != NULL)
495             {
496                 SHAddFromPropSheetExtArray((HPSXA)hpsxa,
497                                            (LPFNADDPROPSHEETPAGE)&Properties_AddPropSheetCallback,
498                                            (LPARAM)&psh);
499                 SHDestroyPropSheetExtArray(hpsxa);
500             }
501             IDataObject_Release(lpDo);
502         }
503
504         if (psh.nPages)
505             PropertySheetW(&psh);
506         else
507             FIXME("No property pages found.\n");
508 }
509
510 /**************************************************************************
511 * ISvItemCm_fnInvokeCommand()
512 */
513 static HRESULT WINAPI ISvItemCm_fnInvokeCommand(
514         IContextMenu2 *iface,
515         LPCMINVOKECOMMANDINFO lpcmi)
516 {
517     ItemCmImpl *This = (ItemCmImpl *)iface;
518
519     if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
520         FIXME("Is an EX structure\n");
521
522     TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
523
524     if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
525     {
526         TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb));
527         return E_INVALIDARG;
528     }
529
530     if (HIWORD(lpcmi->lpVerb) == 0)
531     {
532         switch(LOWORD(lpcmi->lpVerb))
533         {
534         case FCIDM_SHVIEW_EXPLORE:
535             TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
536             DoOpenExplore(iface, lpcmi->hwnd, "explore");
537             break;
538         case FCIDM_SHVIEW_OPEN:
539             TRACE("Verb FCIDM_SHVIEW_OPEN\n");
540             DoOpenExplore(iface, lpcmi->hwnd, "open");
541             break;
542         case FCIDM_SHVIEW_RENAME:
543             TRACE("Verb FCIDM_SHVIEW_RENAME\n");
544             DoRename(iface, lpcmi->hwnd);
545             break;
546         case FCIDM_SHVIEW_DELETE:
547             TRACE("Verb FCIDM_SHVIEW_DELETE\n");
548             DoDelete(iface);
549             break;
550         case FCIDM_SHVIEW_COPY:
551             TRACE("Verb FCIDM_SHVIEW_COPY\n");
552             DoCopyOrCut(iface, lpcmi->hwnd, FALSE);
553             break;
554         case FCIDM_SHVIEW_CUT:
555             TRACE("Verb FCIDM_SHVIEW_CUT\n");
556             DoCopyOrCut(iface, lpcmi->hwnd, TRUE);
557             break;
558         case FCIDM_SHVIEW_PROPERTIES:
559             TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
560             DoOpenProperties(iface, lpcmi->hwnd);
561             break;
562         default:
563             FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
564         }
565     }
566     else
567     {
568         TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb));
569         if (strcmp(lpcmi->lpVerb,"delete")==0)
570             DoDelete(iface);
571         else if (strcmp(lpcmi->lpVerb,"properties")==0)
572             DoOpenProperties(iface, lpcmi->hwnd);
573         else
574             FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb));
575     }
576     return NOERROR;
577 }
578
579 /**************************************************************************
580 *  ISvItemCm_fnGetCommandString()
581 */
582 static HRESULT WINAPI ISvItemCm_fnGetCommandString(
583         IContextMenu2 *iface,
584         UINT_PTR idCommand,
585         UINT uFlags,
586         UINT* lpReserved,
587         LPSTR lpszName,
588         UINT uMaxNameLen)
589 {
590         ItemCmImpl *This = (ItemCmImpl *)iface;
591
592         HRESULT  hr = E_INVALIDARG;
593
594         TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
595
596         switch(uFlags)
597         {
598           case GCS_HELPTEXTA:
599           case GCS_HELPTEXTW:
600             hr = E_NOTIMPL;
601             break;
602
603           case GCS_VERBA:
604             switch(idCommand)
605             {
606               case FCIDM_SHVIEW_RENAME:
607                 strcpy(lpszName, "rename");
608                 hr = NOERROR;
609                 break;
610             }
611             break;
612
613              /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
614              case, you need to do the lstrcpyW to the pointer passed.*/
615           case GCS_VERBW:
616             switch(idCommand)
617             { case FCIDM_SHVIEW_RENAME:
618                 MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen );
619                 hr = NOERROR;
620                 break;
621             }
622             break;
623
624           case GCS_VALIDATEA:
625           case GCS_VALIDATEW:
626             hr = NOERROR;
627             break;
628         }
629         TRACE("-- (%p)->(name=%s)\n",This, lpszName);
630         return hr;
631 }
632
633 /**************************************************************************
634 * ISvItemCm_fnHandleMenuMsg()
635 * NOTES
636 *  should be only in IContextMenu2 and IContextMenu3
637 *  is nevertheless called from word95
638 */
639 static HRESULT WINAPI ISvItemCm_fnHandleMenuMsg(
640         IContextMenu2 *iface,
641         UINT uMsg,
642         WPARAM wParam,
643         LPARAM lParam)
644 {
645         ItemCmImpl *This = (ItemCmImpl *)iface;
646
647         TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n",This, uMsg, wParam, lParam);
648
649         return E_NOTIMPL;
650 }
651
652 static const IContextMenu2Vtbl cmvt =
653 {
654         ISvItemCm_fnQueryInterface,
655         ISvItemCm_fnAddRef,
656         ISvItemCm_fnRelease,
657         ISvItemCm_fnQueryContextMenu,
658         ISvItemCm_fnInvokeCommand,
659         ISvItemCm_fnGetCommandString,
660         ISvItemCm_fnHandleMenuMsg
661 };