~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/shell32/shlview_cmenu.c

Version: ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *      IContextMenu for items in the shellview
  3  *
  4  * Copyright 1998-2000 Juergen Schmied <juergen.schmied@debitel.net>,
  5  *                                     <juergen.schmied@metronet.de>
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 20  */
 21 
 22 #include <string.h>
 23 
 24 #define COBJMACROS
 25 #define NONAMELESSUNION
 26 #define NONAMELESSSTRUCT
 27 
 28 #include "winerror.h"
 29 #include "wine/debug.h"
 30 
 31 #include "windef.h"
 32 #include "wingdi.h"
 33 #include "pidl.h"
 34 #include "undocshell.h"
 35 #include "shlobj.h"
 36 #include "winreg.h"
 37 #include "prsht.h"
 38 
 39 #include "shell32_main.h"
 40 #include "shellfolder.h"
 41 
 42 #include "shresdef.h"
 43 
 44 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 45 
 46 typedef struct
 47 {
 48     IContextMenu3 IContextMenu3_iface;
 49     LONG ref;
 50 
 51     IShellFolder* parent;
 52     UINT verb_offset;
 53 
 54     /* item menu data */
 55     LPITEMIDLIST  pidl;  /* root pidl */
 56     LPITEMIDLIST *apidl; /* array of child pidls */
 57     UINT cidl;
 58     BOOL allvalues;
 59 
 60     /* background menu data */
 61     BOOL desktop;
 62 } ContextMenu;
 63 
 64 static inline ContextMenu *impl_from_IContextMenu3(IContextMenu3 *iface)
 65 {
 66     return CONTAINING_RECORD(iface, ContextMenu, IContextMenu3_iface);
 67 }
 68 
 69 static HRESULT WINAPI ContextMenu_QueryInterface(IContextMenu3 *iface, REFIID riid, LPVOID *ppvObj)
 70 {
 71     ContextMenu *This = impl_from_IContextMenu3(iface);
 72 
 73     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObj);
 74 
 75     *ppvObj = NULL;
 76 
 77     if (IsEqualIID(riid, &IID_IUnknown)      ||
 78         IsEqualIID(riid, &IID_IContextMenu)  ||
 79         IsEqualIID(riid, &IID_IContextMenu2) ||
 80         IsEqualIID(riid, &IID_IContextMenu3))
 81     {
 82         *ppvObj = This;
 83     }
 84     else if (IsEqualIID(riid, &IID_IShellExtInit))  /*IShellExtInit*/
 85     {
 86         FIXME("-- LPSHELLEXTINIT pointer requested\n");
 87     }
 88 
 89     if(*ppvObj)
 90     {
 91         IContextMenu3_AddRef(iface);
 92         return S_OK;
 93     }
 94 
 95     TRACE("-- Interface: E_NOINTERFACE\n");
 96     return E_NOINTERFACE;
 97 }
 98 
 99 static ULONG WINAPI ContextMenu_AddRef(IContextMenu3 *iface)
100 {
101     ContextMenu *This = impl_from_IContextMenu3(iface);
102     ULONG ref = InterlockedIncrement(&This->ref);
103     TRACE("(%p)->(%u)\n", This, ref);
104     return ref;
105 }
106 
107 static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface)
108 {
109     ContextMenu *This = impl_from_IContextMenu3(iface);
110     ULONG ref = InterlockedDecrement(&This->ref);
111 
112     TRACE("(%p)->(%u)\n", This, ref);
113 
114     if (!ref)
115     {
116         if(This->parent)
117             IShellFolder_Release(This->parent);
118 
119         SHFree(This->pidl);
120         _ILFreeaPidl(This->apidl, This->cidl);
121 
122         HeapFree(GetProcessHeap(), 0, This);
123     }
124 
125     return ref;
126 }
127 
128 static HRESULT WINAPI ItemMenu_QueryContextMenu(
129         IContextMenu3 *iface,
130         HMENU hmenu,
131         UINT indexMenu,
132         UINT idCmdFirst,
133         UINT idCmdLast,
134         UINT uFlags)
135 {
136     ContextMenu *This = impl_from_IContextMenu3(iface);
137     INT uIDMax;
138 
139     TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
140 
141     This->verb_offset = idCmdFirst;
142 
143     if(!(CMF_DEFAULTONLY & uFlags) && This->cidl > 0)
144     {
145         HMENU hmenures = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(MENU_SHV_FILE));
146 
147         if(uFlags & CMF_EXPLORE)
148             RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
149 
150         uIDMax = Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
151 
152         DestroyMenu(hmenures);
153 
154         if(This->allvalues)
155         {
156             MENUITEMINFOW mi;
157             WCHAR str[255];
158             mi.cbSize = sizeof(mi);
159             mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
160             mi.dwTypeData = str;
161             mi.cch = 255;
162             GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE, MF_BYCOMMAND, &mi);
163             RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE, MF_BYCOMMAND);
164 
165             mi.cbSize = sizeof(mi);
166             mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
167             mi.dwTypeData = str;
168             mi.fState = MFS_ENABLED;
169             mi.wID = FCIDM_SHVIEW_EXPLORE;
170             mi.fType = MFT_STRING;
171             InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi);
172         }
173 
174         SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
175 
176         if(uFlags & ~CMF_CANRENAME)
177             RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME, MF_BYCOMMAND);
178         else
179         {
180             UINT enable = MF_BYCOMMAND;
181 
182             /* can't rename more than one item at a time*/
183             if (!This->apidl || This->cidl > 1)
184                 enable |= MFS_DISABLED;
185             else
186             {
187                 DWORD attr = SFGAO_CANRENAME;
188 
189                 IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr);
190                 enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED;
191             }
192 
193             EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, enable);
194         }
195 
196         return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst);
197     }
198     return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
199 }
200 
201 /**************************************************************************
202 * DoOpenExplore
203 *
204 *  for folders only
205 */
206 
207 static void DoOpenExplore(ContextMenu *This, HWND hwnd, LPCSTR verb)
208 {
209         UINT i, bFolderFound = FALSE;
210         LPITEMIDLIST    pidlFQ;
211         SHELLEXECUTEINFOA       sei;
212 
213         /* Find the first item in the list that is not a value. These commands
214             should never be invoked if there isn't at least one folder item in the list.*/
215 
216         for(i = 0; i<This->cidl; i++)
217         {
218           if(!_ILIsValue(This->apidl[i]))
219           {
220             bFolderFound = TRUE;
221             break;
222           }
223         }
224 
225         if (!bFolderFound) return;
226 
227         pidlFQ = ILCombine(This->pidl, This->apidl[i]);
228 
229         ZeroMemory(&sei, sizeof(sei));
230         sei.cbSize = sizeof(sei);
231         sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
232         sei.lpIDList = pidlFQ;
233         sei.lpClass = "Folder";
234         sei.hwnd = hwnd;
235         sei.nShow = SW_SHOWNORMAL;
236         sei.lpVerb = verb;
237         ShellExecuteExA(&sei);
238         SHFree(pidlFQ);
239 }
240 
241 /**************************************************************************
242  * DoDelete
243  *
244  * deletes the currently selected items
245  */
246 static void DoDelete(ContextMenu *This)
247 {
248     ISFHelper *helper;
249 
250     IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
251     if (helper)
252     {
253         ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST*)This->apidl);
254         ISFHelper_Release(helper);
255     }
256 }
257 
258 /**************************************************************************
259  * DoCopyOrCut
260  *
261  * copies the currently selected items into the clipboard
262  */
263 static BOOL DoCopyOrCut(ContextMenu *This, HWND hwnd, BOOL cut)
264 {
265     IDataObject *dataobject;
266     IShellBrowser *browser;
267     IShellView *view;
268 
269     TRACE("(%p)->(wnd=%p, cut=%d)\n", This, hwnd, cut);
270 
271     /* get the active IShellView */
272     if ((browser = (IShellBrowser*)SendMessageA(hwnd, CWM_GETISHELLBROWSER, 0, 0)))
273     {
274         if (SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
275         {
276             if (SUCCEEDED(IShellView_GetItemObject(view, SVGIO_SELECTION, &IID_IDataObject, (void**)&dataobject)))
277             {
278                 OleSetClipboard(dataobject);
279                 IDataObject_Release(dataobject);
280             }
281             IShellView_Release(view);
282         }
283     }
284 
285     return TRUE;
286 }
287 
288 /**************************************************************************
289  * Properties_AddPropSheetCallback
290  *
291  * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
292  * propertysheet pages from shell extensions.
293  */
294 static BOOL CALLBACK Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
295 {
296         LPPROPSHEETHEADERW psh = (LPPROPSHEETHEADERW) lparam;
297         psh->u3.phpage[psh->nPages++] = hpage;
298 
299         return TRUE;
300 }
301 
302 static void DoOpenProperties(ContextMenu *This, HWND hwnd)
303 {
304         static const UINT MAX_PROP_PAGES = 99;
305         static const WCHAR wszFolder[] = {'F','o','l','d','e','r', 0};
306         static const WCHAR wszFiletypeAll[] = {'*',0};
307         LPSHELLFOLDER lpDesktopSF;
308         LPSHELLFOLDER lpSF;
309         LPDATAOBJECT lpDo;
310         WCHAR wszFiletype[MAX_PATH];
311         WCHAR wszFilename[MAX_PATH];
312         PROPSHEETHEADERW psh;
313         HPROPSHEETPAGE hpages[MAX_PROP_PAGES];
314         HPSXA hpsxa;
315         UINT ret;
316 
317         TRACE("(%p)->(wnd=%p)\n", This, hwnd);
318 
319         ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
320         psh.dwSize = sizeof (PROPSHEETHEADERW);
321         psh.hwndParent = hwnd;
322         psh.dwFlags = PSH_PROPTITLE;
323         psh.nPages = 0;
324         psh.u3.phpage = hpages;
325         psh.u2.nStartPage = 0;
326 
327         _ILSimpleGetTextW(This->apidl[0], (LPVOID)wszFilename, MAX_PATH);
328         psh.pszCaption = (LPCWSTR)wszFilename;
329 
330         /* Find out where to look for the shell extensions */
331         if (_ILIsValue(This->apidl[0]))
332         {
333             char sTemp[64];
334             sTemp[0] = 0;
335             if (_ILGetExtension(This->apidl[0], sTemp, 64))
336             {
337                 HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE);
338                 MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wszFiletype, MAX_PATH);
339             }
340             else
341             {
342                 wszFiletype[0] = 0;
343             }
344         }
345         else if (_ILIsFolder(This->apidl[0]))
346         {
347             lstrcpynW(wszFiletype, wszFolder, 64);
348         }
349         else if (_ILIsSpecialFolder(This->apidl[0]))
350         {
351             LPGUID folderGUID;
352             static const WCHAR wszclsid[] = {'C','L','S','I','D','\\', 0};
353             folderGUID = _ILGetGUIDPointer(This->apidl[0]);
354             lstrcpyW(wszFiletype, wszclsid);
355             StringFromGUID2(folderGUID, &wszFiletype[6], MAX_PATH - 6);
356         }
357         else
358         {
359             FIXME("Requested properties for unknown type.\n");
360             return;
361         }
362 
363         /* Get a suitable DataObject for accessing the files */
364         SHGetDesktopFolder(&lpDesktopSF);
365         if (_ILIsPidlSimple(This->pidl))
366         {
367             ret = IShellFolder_GetUIObjectOf(lpDesktopSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
368                                              &IID_IDataObject, NULL, (LPVOID *)&lpDo);
369             IShellFolder_Release(lpDesktopSF);
370         }
371         else
372         {
373             IShellFolder_BindToObject(lpDesktopSF, This->pidl, NULL, &IID_IShellFolder, (LPVOID*) &lpSF);
374             ret = IShellFolder_GetUIObjectOf(lpSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
375                                              &IID_IDataObject, NULL, (LPVOID *)&lpDo);
376             IShellFolder_Release(lpSF);
377             IShellFolder_Release(lpDesktopSF);
378         }
379 
380         if (SUCCEEDED(ret))
381         {
382             hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
383             if (hpsxa != NULL)
384             {
385                 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
386                 SHDestroyPropSheetExtArray(hpsxa);
387             }
388             hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletypeAll, MAX_PROP_PAGES - psh.nPages, lpDo);
389             if (hpsxa != NULL)
390             {
391                 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
392                 SHDestroyPropSheetExtArray(hpsxa);
393             }
394             IDataObject_Release(lpDo);
395         }
396 
397         if (psh.nPages)
398             PropertySheetW(&psh);
399         else
400             FIXME("No property pages found.\n");
401 }
402 
403 static HRESULT WINAPI ItemMenu_InvokeCommand(
404         IContextMenu3 *iface,
405         LPCMINVOKECOMMANDINFO lpcmi)
406 {
407     ContextMenu *This = impl_from_IContextMenu3(iface);
408 
409     if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
410         FIXME("Is an EX structure\n");
411 
412     TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
413 
414     if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
415     {
416         TRACE("Invalid Verb %x\n",LOWORD(lpcmi->lpVerb));
417         return E_INVALIDARG;
418     }
419 
420     if (HIWORD(lpcmi->lpVerb) == 0)
421     {
422         switch(LOWORD(lpcmi->lpVerb - This->verb_offset))
423         {
424         case FCIDM_SHVIEW_EXPLORE:
425             TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
426             DoOpenExplore(This, lpcmi->hwnd, "explore");
427             break;
428         case FCIDM_SHVIEW_OPEN:
429             TRACE("Verb FCIDM_SHVIEW_OPEN\n");
430             DoOpenExplore(This, lpcmi->hwnd, "open");
431             break;
432         case FCIDM_SHVIEW_RENAME:
433         {
434             IShellBrowser *browser;
435 
436             /* get the active IShellView */
437             browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
438             if (browser)
439             {
440                 IShellView *view;
441 
442                 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
443                 {
444                     TRACE("(shellview=%p)\n", view);
445                     IShellView_SelectItem(view, This->apidl[0],
446                          SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
447                     IShellView_Release(view);
448                 }
449             }
450             break;
451         }
452         case FCIDM_SHVIEW_DELETE:
453             TRACE("Verb FCIDM_SHVIEW_DELETE\n");
454             DoDelete(This);
455             break;
456         case FCIDM_SHVIEW_COPY:
457             TRACE("Verb FCIDM_SHVIEW_COPY\n");
458             DoCopyOrCut(This, lpcmi->hwnd, FALSE);
459             break;
460         case FCIDM_SHVIEW_CUT:
461             TRACE("Verb FCIDM_SHVIEW_CUT\n");
462             DoCopyOrCut(This, lpcmi->hwnd, TRUE);
463             break;
464         case FCIDM_SHVIEW_PROPERTIES:
465             TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
466             DoOpenProperties(This, lpcmi->hwnd);
467             break;
468         default:
469             FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb)-This->verb_offset);
470             return E_INVALIDARG;
471         }
472     }
473     else
474     {
475         TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb));
476         if (strcmp(lpcmi->lpVerb,"delete")==0)
477             DoDelete(This);
478         else if (strcmp(lpcmi->lpVerb,"properties")==0)
479             DoOpenProperties(This, lpcmi->hwnd);
480         else {
481             FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb));
482             return E_FAIL;
483         }
484     }
485     return S_OK;
486 }
487 
488 static HRESULT WINAPI ItemMenu_GetCommandString(
489         IContextMenu3 *iface,
490         UINT_PTR idCommand,
491         UINT uFlags,
492         UINT* lpReserved,
493         LPSTR lpszName,
494         UINT uMaxNameLen)
495 {
496         ContextMenu *This = impl_from_IContextMenu3(iface);
497         HRESULT hr = E_INVALIDARG;
498 
499         TRACE("(%p)->(%lx flags=%x %p name=%p len=%x)\n", This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
500 
501         switch(uFlags)
502         {
503           case GCS_HELPTEXTA:
504           case GCS_HELPTEXTW:
505             hr = E_NOTIMPL;
506             break;
507 
508           case GCS_VERBA:
509             switch(idCommand-This->verb_offset)
510             {
511             case FCIDM_SHVIEW_RENAME:
512                 strcpy(lpszName, "rename");
513                 hr = S_OK;
514                 break;
515             }
516             break;
517 
518              /* NT 4.0 with IE 3.0x or no IE will always call This with GCS_VERBW. In This
519              case, you need to do the lstrcpyW to the pointer passed.*/
520           case GCS_VERBW:
521             switch(idCommand-This->verb_offset)
522             {
523             case FCIDM_SHVIEW_RENAME:
524                 MultiByteToWideChar( CP_ACP, 0, "rename", -1, (LPWSTR)lpszName, uMaxNameLen );
525                 hr = S_OK;
526                 break;
527             }
528             break;
529 
530           case GCS_VALIDATEA:
531           case GCS_VALIDATEW:
532             hr = S_OK;
533             break;
534         }
535         TRACE("-- (%p)->(name=%s)\n", This, lpszName);
536         return hr;
537 }
538 
539 /**************************************************************************
540 * NOTES
541 *  should be only in IContextMenu2 and IContextMenu3
542 *  is nevertheless called from word95
543 */
544 static HRESULT WINAPI ContextMenu_HandleMenuMsg(IContextMenu3 *iface, UINT msg,
545     WPARAM wParam, LPARAM lParam)
546 {
547     ContextMenu *This = impl_from_IContextMenu3(iface);
548     FIXME("(%p)->(0x%x 0x%lx 0x%lx): stub\n", This, msg, wParam, lParam);
549     return E_NOTIMPL;
550 }
551 
552 static HRESULT WINAPI ContextMenu_HandleMenuMsg2(IContextMenu3 *iface, UINT msg,
553     WPARAM wParam, LPARAM lParam, LRESULT *result)
554 {
555     ContextMenu *This = impl_from_IContextMenu3(iface);
556     FIXME("(%p)->(0x%x 0x%lx 0x%lx %p): stub\n", This, msg, wParam, lParam, result);
557     return E_NOTIMPL;
558 }
559 
560 static const IContextMenu3Vtbl ItemContextMenuVtbl =
561 {
562     ContextMenu_QueryInterface,
563     ContextMenu_AddRef,
564     ContextMenu_Release,
565     ItemMenu_QueryContextMenu,
566     ItemMenu_InvokeCommand,
567     ItemMenu_GetCommandString,
568     ContextMenu_HandleMenuMsg,
569     ContextMenu_HandleMenuMsg2
570 };
571 
572 HRESULT ItemMenu_Constructor(IShellFolder *parent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl,
573     REFIID riid, void **pObj)
574 {
575     ContextMenu* This;
576     HRESULT hr;
577     int i;
578 
579     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
580     if (!This) return E_OUTOFMEMORY;
581 
582     This->IContextMenu3_iface.lpVtbl = &ItemContextMenuVtbl;
583     This->ref = 1;
584     This->verb_offset = 0;
585     This->parent = parent;
586     if (parent) IShellFolder_AddRef(parent);
587 
588     This->pidl = ILClone(pidl);
589     This->apidl = _ILCopyaPidl(apidl, cidl);
590     This->cidl = cidl;
591     This->allvalues = TRUE;
592 
593     This->desktop = FALSE;
594 
595     for (i = 0; i < cidl; i++)
596        This->allvalues &= (_ILIsValue(apidl[i]) ? 1 : 0);
597 
598     hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
599     IContextMenu3_Release(&This->IContextMenu3_iface);
600 
601     return hr;
602 }
603 
604 /* Background menu implementation */
605 static HRESULT WINAPI BackgroundMenu_QueryContextMenu(
606         IContextMenu3 *iface,
607         HMENU hMenu,
608         UINT indexMenu,
609         UINT idCmdFirst,
610         UINT idCmdLast,
611         UINT uFlags)
612 {
613     ContextMenu *This = impl_from_IContextMenu3(iface);
614     HMENU hMyMenu;
615     UINT idMax;
616     HRESULT hr;
617 
618     TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
619           This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
620 
621     This->verb_offset = idCmdFirst;
622 
623     hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002");
624     if (uFlags & CMF_DEFAULTONLY)
625     {
626         HMENU ourMenu = GetSubMenu(hMyMenu,0);
627         UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED);
628         UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED);
629         if (newDef != oldDef)
630             SetMenuDefaultItem(hMenu,newDef,TRUE);
631         if (newDef!=0xFFFFFFFF)
632             hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1);
633         else
634             hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
635     }
636     else
637     {
638         idMax = Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
639                                   idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS);
640         hr =  MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst);
641     }
642     DestroyMenu(hMyMenu);
643 
644     TRACE("(%p)->returning 0x%x\n",This,hr);
645     return hr;
646 }
647 
648 static void DoNewFolder(ContextMenu *This, IShellView *view)
649 {
650     ISFHelper *helper;
651 
652     IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
653     if (helper)
654     {
655         WCHAR nameW[MAX_PATH];
656         LPITEMIDLIST pidl;
657 
658         ISFHelper_GetUniqueName(helper, nameW, MAX_PATH);
659         ISFHelper_AddFolder(helper, 0, nameW, &pidl);
660 
661         if (view)
662         {
663             /* if we are in a shellview do labeledit */
664             IShellView_SelectItem(view,
665                     pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
666                     |SVSI_FOCUSED|SVSI_SELECT));
667         }
668 
669         SHFree(pidl);
670         ISFHelper_Release(helper);
671     }
672 }
673 
674 static BOOL DoPaste(ContextMenu *This)
675 {
676         BOOL bSuccess = FALSE;
677         IDataObject * pda;
678 
679         TRACE("\n");
680 
681         if(SUCCEEDED(OleGetClipboard(&pda)))
682         {
683           STGMEDIUM medium;
684           FORMATETC formatetc;
685 
686           TRACE("pda=%p\n", pda);
687 
688           /* Set the FORMATETC structure*/
689           InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL);
690 
691           /* Get the pidls from IDataObject */
692           if(SUCCEEDED(IDataObject_GetData(pda,&formatetc,&medium)))
693           {
694             LPITEMIDLIST * apidl;
695             LPITEMIDLIST pidl;
696             IShellFolder *psfFrom = NULL, *psfDesktop;
697 
698             LPIDA lpcida = GlobalLock(medium.u.hGlobal);
699             TRACE("cida=%p\n", lpcida);
700 
701             apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
702 
703             /* bind to the source shellfolder */
704             SHGetDesktopFolder(&psfDesktop);
705             if(psfDesktop)
706             {
707               IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
708               IShellFolder_Release(psfDesktop);
709             }
710 
711             if (psfFrom)
712             {
713               /* get source and destination shellfolder */
714               ISFHelper *psfhlpdst, *psfhlpsrc;
715               IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
716               IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
717 
718               /* do the copy/move */
719               if (psfhlpdst && psfhlpsrc)
720               {
721                 ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
722                 /* FIXME handle move
723                 ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl);
724                 */
725               }
726               if(psfhlpdst) ISFHelper_Release(psfhlpdst);
727               if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
728               IShellFolder_Release(psfFrom);
729             }
730 
731             _ILFreeaPidl(apidl, lpcida->cidl);
732             SHFree(pidl);
733 
734             /* release the medium*/
735             ReleaseStgMedium(&medium);
736           }
737           IDataObject_Release(pda);
738         }
739 #if 0
740         HGLOBAL  hMem;
741 
742         OpenClipboard(NULL);
743         hMem = GetClipboardData(CF_HDROP);
744 
745         if(hMem)
746         {
747           char * pDropFiles = GlobalLock(hMem);
748           if(pDropFiles)
749           {
750             int len, offset = sizeof(DROPFILESTRUCT);
751 
752             while( pDropFiles[offset] != 0)
753             {
754               len = strlen(pDropFiles + offset);
755               TRACE("%s\n", pDropFiles + offset);
756               offset += len+1;
757             }
758           }
759           GlobalUnlock(hMem);
760         }
761         CloseClipboard();
762 #endif
763         return bSuccess;
764 }
765 
766 static HRESULT WINAPI BackgroundMenu_InvokeCommand(
767         IContextMenu3 *iface,
768         LPCMINVOKECOMMANDINFO lpcmi)
769 {
770     ContextMenu *This = impl_from_IContextMenu3(iface);
771     IShellBrowser *browser;
772     IShellView *view = NULL;
773     HWND hWnd = NULL;
774 
775     TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", This, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
776 
777     /* get the active IShellView */
778     if ((browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
779     {
780         if (SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
781             IShellView_GetWindow(view, &hWnd);
782     }
783 
784     if(HIWORD(lpcmi->lpVerb))
785     {
786         TRACE("%s\n", debugstr_a(lpcmi->lpVerb));
787 
788         if (!strcmp(lpcmi->lpVerb, CMDSTR_NEWFOLDERA))
789         {
790             DoNewFolder(This, view);
791         }
792         else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWLISTA))
793         {
794             if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW, 0), 0);
795         }
796         else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWDETAILSA))
797         {
798             if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW, 0), 0);
799         }
800         else
801         {
802             FIXME("please report: unknown verb %s\n", debugstr_a(lpcmi->lpVerb));
803         }
804     }
805     else
806     {
807         switch (LOWORD(lpcmi->lpVerb) - This->verb_offset)
808         {
809             case FCIDM_SHVIEW_REFRESH:
810                 if (view) IShellView_Refresh(view);
811                 break;
812 
813             case FCIDM_SHVIEW_NEWFOLDER:
814                 DoNewFolder(This, view);
815                 break;
816 
817             case FCIDM_SHVIEW_INSERT:
818                 DoPaste(This);
819                 break;
820 
821             case FCIDM_SHVIEW_PROPERTIES:
822                 if (This->desktop) {
823                     ShellExecuteA(lpcmi->hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
824                 } else {
825                     FIXME("launch item properties dialog\n");
826                 }
827                 break;
828 
829             default:
830                 /* if it's an id just pass it to the parent shv */
831                 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
832                 break;
833          }
834     }
835 
836     if (view)
837         IShellView_Release(view);
838 
839     return S_OK;
840 }
841 
842 static HRESULT WINAPI BackgroundMenu_GetCommandString(
843         IContextMenu3 *iface,
844         UINT_PTR idCommand,
845         UINT uFlags,
846         UINT* lpReserved,
847         LPSTR lpszName,
848         UINT uMaxNameLen)
849 {
850         ContextMenu *This = impl_from_IContextMenu3(iface);
851 
852         TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
853 
854         /* test the existence of the menu items, the file dialog enables
855            the buttons according to this */
856         if (uFlags == GCS_VALIDATEA)
857         {
858           if(HIWORD(idCommand))
859           {
860             if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
861                 !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
862                 !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
863             {
864               return S_OK;
865             }
866           }
867         }
868 
869         FIXME("unknown command string\n");
870         return E_FAIL;
871 }
872 
873 static const IContextMenu3Vtbl BackgroundContextMenuVtbl =
874 {
875     ContextMenu_QueryInterface,
876     ContextMenu_AddRef,
877     ContextMenu_Release,
878     BackgroundMenu_QueryContextMenu,
879     BackgroundMenu_InvokeCommand,
880     BackgroundMenu_GetCommandString,
881     ContextMenu_HandleMenuMsg,
882     ContextMenu_HandleMenuMsg2
883 };
884 
885 HRESULT BackgroundMenu_Constructor(IShellFolder *parent, BOOL desktop, REFIID riid, void **pObj)
886 {
887     ContextMenu *This;
888     HRESULT hr;
889 
890     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
891     if (!This) return E_OUTOFMEMORY;
892 
893     This->IContextMenu3_iface.lpVtbl = &BackgroundContextMenuVtbl;
894     This->ref = 1;
895     This->parent = parent;
896     This->verb_offset = 0;
897 
898     This->pidl = NULL;
899     This->apidl = NULL;
900     This->cidl = 0;
901     This->allvalues = FALSE;
902 
903     This->desktop = desktop;
904     if (parent) IShellFolder_AddRef(parent);
905 
906     hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
907     IContextMenu3_Release(&This->IContextMenu3_iface);
908 
909     return hr;
910 }
911 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.