mfmediaengine: Remove unnecessary import library.
[wine.git] / dlls / shell32 / shlview_cmenu.c
blob6c05904bb91824d684aa8d11ec358beae16fbf10
1 /*
2 * IContextMenu for items in the shellview
4 * Copyright 1998-2000 Juergen Schmied <juergen.schmied@debitel.net>,
5 * <juergen.schmied@metronet.de>
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.
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.
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
22 #include <string.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include "winerror.h"
29 #include "windef.h"
30 #include "wingdi.h"
31 #include "pidl.h"
32 #include "undocshell.h"
33 #include "shlobj.h"
34 #include "winreg.h"
35 #include "prsht.h"
37 #include "shell32_main.h"
38 #include "shellfolder.h"
40 #include "shresdef.h"
41 #include "shlwapi.h"
43 #include "wine/heap.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(shell);
48 #define FCIDM_BASE 0x7000
50 typedef struct
52 IContextMenu3 IContextMenu3_iface;
53 IShellExtInit IShellExtInit_iface;
54 IObjectWithSite IObjectWithSite_iface;
55 LONG ref;
57 IShellFolder* parent;
59 /* item menu data */
60 LPITEMIDLIST pidl; /* root pidl */
61 LPITEMIDLIST *apidl; /* array of child pidls */
62 UINT cidl;
63 BOOL allvalues;
65 /* background menu data */
66 BOOL desktop;
67 } ContextMenu;
69 static inline ContextMenu *impl_from_IContextMenu3(IContextMenu3 *iface)
71 return CONTAINING_RECORD(iface, ContextMenu, IContextMenu3_iface);
74 static inline ContextMenu *impl_from_IShellExtInit(IShellExtInit *iface)
76 return CONTAINING_RECORD(iface, ContextMenu, IShellExtInit_iface);
79 static inline ContextMenu *impl_from_IObjectWithSite(IObjectWithSite *iface)
81 return CONTAINING_RECORD(iface, ContextMenu, IObjectWithSite_iface);
84 static HRESULT WINAPI ContextMenu_QueryInterface(IContextMenu3 *iface, REFIID riid, LPVOID *ppvObj)
86 ContextMenu *This = impl_from_IContextMenu3(iface);
88 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObj);
90 *ppvObj = NULL;
92 if (IsEqualIID(riid, &IID_IUnknown) ||
93 IsEqualIID(riid, &IID_IContextMenu) ||
94 IsEqualIID(riid, &IID_IContextMenu2) ||
95 IsEqualIID(riid, &IID_IContextMenu3))
97 *ppvObj = &This->IContextMenu3_iface;
99 else if (IsEqualIID(riid, &IID_IShellExtInit))
101 *ppvObj = &This->IShellExtInit_iface;
103 else if (IsEqualIID(riid, &IID_IObjectWithSite))
105 *ppvObj = &This->IObjectWithSite_iface;
108 if(*ppvObj)
110 IContextMenu3_AddRef(iface);
111 return S_OK;
114 TRACE("-- Interface: E_NOINTERFACE\n");
115 return E_NOINTERFACE;
118 static ULONG WINAPI ContextMenu_AddRef(IContextMenu3 *iface)
120 ContextMenu *This = impl_from_IContextMenu3(iface);
121 ULONG ref = InterlockedIncrement(&This->ref);
122 TRACE("(%p)->(%u)\n", This, ref);
123 return ref;
126 static ULONG WINAPI ContextMenu_Release(IContextMenu3 *iface)
128 ContextMenu *This = impl_from_IContextMenu3(iface);
129 ULONG ref = InterlockedDecrement(&This->ref);
131 TRACE("(%p)->(%u)\n", This, ref);
133 if (!ref)
135 if(This->parent)
136 IShellFolder_Release(This->parent);
138 SHFree(This->pidl);
139 _ILFreeaPidl(This->apidl, This->cidl);
141 heap_free(This);
144 return ref;
147 static UINT max_menu_id(HMENU hmenu, UINT offset, UINT last)
149 int i;
150 UINT max_id = 0;
152 for (i = GetMenuItemCount(hmenu) - 1; i >= 0; i--)
154 MENUITEMINFOW item;
155 memset(&item, 0, sizeof(MENUITEMINFOW));
156 item.cbSize = sizeof(MENUITEMINFOW);
157 item.fMask = MIIM_ID | MIIM_SUBMENU | MIIM_TYPE;
158 if (!GetMenuItemInfoW(hmenu, i, TRUE, &item))
159 continue;
160 if (!(item.fType & MFT_SEPARATOR))
162 if (item.hSubMenu)
164 UINT submenu_max_id = max_menu_id(item.hSubMenu, offset, last);
165 if (max_id < submenu_max_id)
166 max_id = submenu_max_id;
168 if (item.wID + offset <= last)
170 if (max_id <= item.wID + offset)
171 max_id = item.wID + offset + 1;
175 return max_id;
178 static HRESULT WINAPI ItemMenu_QueryContextMenu(
179 IContextMenu3 *iface,
180 HMENU hmenu,
181 UINT indexMenu,
182 UINT idCmdFirst,
183 UINT idCmdLast,
184 UINT uFlags)
186 ContextMenu *This = impl_from_IContextMenu3(iface);
187 INT uIDMax;
189 TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
191 if(!(CMF_DEFAULTONLY & uFlags) && This->cidl > 0)
193 HMENU hmenures = LoadMenuW(shell32_hInstance, MAKEINTRESOURCEW(MENU_SHV_FILE));
195 if(uFlags & CMF_EXPLORE)
196 RemoveMenu(hmenures, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
198 Shell_MergeMenus(hmenu, GetSubMenu(hmenures, 0), indexMenu, idCmdFirst - FCIDM_BASE, idCmdLast, MM_SUBMENUSHAVEIDS);
199 uIDMax = max_menu_id(GetSubMenu(hmenures, 0), idCmdFirst - FCIDM_BASE, idCmdLast);
201 DestroyMenu(hmenures);
203 if(This->allvalues)
205 MENUITEMINFOW mi;
206 WCHAR str[255];
207 mi.cbSize = sizeof(mi);
208 mi.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE;
209 mi.dwTypeData = str;
210 mi.cch = 255;
211 GetMenuItemInfoW(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND, &mi);
212 RemoveMenu(hmenu, FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
214 mi.cbSize = sizeof(mi);
215 mi.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_STRING;
216 mi.dwTypeData = str;
217 mi.fState = MFS_ENABLED;
218 mi.wID = FCIDM_SHVIEW_EXPLORE - FCIDM_BASE + idCmdFirst;
219 mi.fType = MFT_STRING;
220 InsertMenuItemW(hmenu, (uFlags & CMF_EXPLORE) ? 1 : 2, MF_BYPOSITION, &mi);
223 SetMenuDefaultItem(hmenu, 0, MF_BYPOSITION);
225 if(uFlags & ~CMF_CANRENAME)
226 RemoveMenu(hmenu, FCIDM_SHVIEW_RENAME - FCIDM_BASE + idCmdFirst, MF_BYCOMMAND);
227 else
229 UINT enable = MF_BYCOMMAND;
231 /* can't rename more than one item at a time*/
232 if (!This->apidl || This->cidl > 1)
233 enable |= MFS_DISABLED;
234 else
236 DWORD attr = SFGAO_CANRENAME;
238 IShellFolder_GetAttributesOf(This->parent, 1, (LPCITEMIDLIST*)This->apidl, &attr);
239 enable |= (attr & SFGAO_CANRENAME) ? MFS_ENABLED : MFS_DISABLED;
242 EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME - FCIDM_BASE + idCmdFirst, enable);
245 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, uIDMax-idCmdFirst);
247 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
250 /**************************************************************************
251 * DoOpenExplore
253 * for folders only
256 static void DoOpenExplore(ContextMenu *This, HWND hwnd, LPCSTR verb)
258 UINT i;
259 BOOL bFolderFound = FALSE;
260 LPITEMIDLIST pidlFQ;
261 SHELLEXECUTEINFOA sei;
263 /* Find the first item in the list that is not a value. These commands
264 should never be invoked if there isn't at least one folder item in the list.*/
266 for(i = 0; i<This->cidl; i++)
268 if(!_ILIsValue(This->apidl[i]))
270 bFolderFound = TRUE;
271 break;
275 if (!bFolderFound) return;
277 pidlFQ = ILCombine(This->pidl, This->apidl[i]);
279 ZeroMemory(&sei, sizeof(sei));
280 sei.cbSize = sizeof(sei);
281 sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
282 sei.lpIDList = pidlFQ;
283 sei.lpClass = "Folder";
284 sei.hwnd = hwnd;
285 sei.nShow = SW_SHOWNORMAL;
286 sei.lpVerb = verb;
287 ShellExecuteExA(&sei);
288 SHFree(pidlFQ);
291 /**************************************************************************
292 * DoDelete
294 * deletes the currently selected items
296 static void DoDelete(ContextMenu *This)
298 ISFHelper *helper;
300 IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
301 if (helper)
303 ISFHelper_DeleteItems(helper, This->cidl, (LPCITEMIDLIST*)This->apidl);
304 ISFHelper_Release(helper);
308 /**************************************************************************
309 * DoCopyOrCut
311 * copies the currently selected items into the clipboard
313 static void DoCopyOrCut(ContextMenu *This, HWND hwnd, BOOL cut)
315 IDataObject *dataobject;
317 TRACE("(%p)->(wnd=%p, cut=%d)\n", This, hwnd, cut);
319 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->parent, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject, 0, (void**)&dataobject)))
321 OleSetClipboard(dataobject);
322 IDataObject_Release(dataobject);
326 /**************************************************************************
327 * Properties_AddPropSheetCallback
329 * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
330 * propertysheet pages from shell extensions.
332 static BOOL CALLBACK Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
334 LPPROPSHEETHEADERW psh = (LPPROPSHEETHEADERW) lparam;
335 psh->u3.phpage[psh->nPages++] = hpage;
337 return TRUE;
340 static BOOL format_date(FILETIME *time, WCHAR *buffer, DWORD size)
342 FILETIME ft;
343 SYSTEMTIME st;
344 int ret;
346 if (!FileTimeToLocalFileTime(time, &ft))
347 return FALSE;
349 if (!FileTimeToSystemTime(&ft, &st))
350 return FALSE;
352 ret = GetDateFormatW(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, buffer, size);
353 if (ret)
355 buffer[ret - 1] = ' ';
356 ret = GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &st, NULL, buffer + ret , size - ret);
358 return ret != 0;
361 static BOOL get_program_description(WCHAR *path, WCHAR *buffer, DWORD size)
363 WCHAR fileDescW[41], *desc;
364 DWORD versize, *lang;
365 UINT dlen, llen, i;
366 BOOL ret = FALSE;
367 PVOID data;
369 versize = GetFileVersionInfoSizeW(path, NULL);
370 if (!versize) return FALSE;
372 data = heap_alloc(versize);
373 if (!data) return FALSE;
375 if (!GetFileVersionInfoW(path, 0, versize, data))
376 goto out;
378 if (!VerQueryValueW(data, L"\\VarFileInfo\\Translation", (LPVOID *)&lang, &llen))
379 goto out;
381 for (i = 0; i < llen / sizeof(DWORD); i++)
383 swprintf(fileDescW, ARRAY_SIZE(fileDescW), L"\\StringFileInfo\\%04x%04x\\FileDescription",
384 LOWORD(lang[i]), HIWORD(lang[i]));
385 if (VerQueryValueW(data, fileDescW, (LPVOID *)&desc, &dlen))
387 if (dlen > size - 1) dlen = size - 1;
388 memcpy(buffer, desc, dlen * sizeof(WCHAR));
389 buffer[dlen] = 0;
390 ret = TRUE;
391 break;
395 out:
396 heap_free(data);
397 return ret;
400 struct file_properties_info
402 WCHAR path[MAX_PATH];
403 WCHAR dir[MAX_PATH];
404 WCHAR *filename;
405 DWORD attrib;
408 static void init_file_properties_dlg(HWND hwndDlg, struct file_properties_info *props)
410 WCHAR buffer[MAX_PATH], buffer2[MAX_PATH];
411 WIN32_FILE_ATTRIBUTE_DATA exinfo;
412 SHFILEINFOW shinfo;
414 SetDlgItemTextW(hwndDlg, IDC_FPROP_PATH, props->filename);
415 SetDlgItemTextW(hwndDlg, IDC_FPROP_LOCATION, props->dir);
417 if (SHGetFileInfoW(props->path, 0, &shinfo, sizeof(shinfo), SHGFI_TYPENAME|SHGFI_ICON))
419 if (shinfo.hIcon)
421 SendDlgItemMessageW(hwndDlg, IDC_FPROP_ICON, STM_SETICON, (WPARAM)shinfo.hIcon, 0);
422 DestroyIcon(shinfo.hIcon);
424 if (shinfo.szTypeName[0])
425 SetDlgItemTextW(hwndDlg, IDC_FPROP_TYPE, shinfo.szTypeName);
428 if (!GetFileAttributesExW(props->path, GetFileExInfoStandard, &exinfo))
429 return;
431 if (format_date(&exinfo.ftCreationTime, buffer, ARRAY_SIZE(buffer)))
432 SetDlgItemTextW(hwndDlg, IDC_FPROP_CREATED, buffer);
434 if (exinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
435 SendDlgItemMessageW(hwndDlg, IDC_FPROP_READONLY, BM_SETCHECK, BST_CHECKED, 0);
436 if (exinfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
437 SendDlgItemMessageW(hwndDlg, IDC_FPROP_HIDDEN, BM_SETCHECK, BST_CHECKED, 0);
438 if (exinfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
439 SendDlgItemMessageW(hwndDlg, IDC_FPROP_ARCHIVE, BM_SETCHECK, BST_CHECKED, 0);
441 if (exinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
443 SetDlgItemTextW(hwndDlg, IDC_FPROP_SIZE, L"(unknown)");
444 /* TODO: Implement counting for directories */
445 return;
448 /* Information about files only */
449 StrFormatByteSizeW(((LONGLONG)exinfo.nFileSizeHigh << 32) | exinfo.nFileSizeLow,
450 buffer, ARRAY_SIZE(buffer));
451 SetDlgItemTextW(hwndDlg, IDC_FPROP_SIZE, buffer);
453 if (format_date(&exinfo.ftLastWriteTime, buffer, ARRAY_SIZE(buffer)))
454 SetDlgItemTextW(hwndDlg, IDC_FPROP_MODIFIED, buffer);
455 if (format_date(&exinfo.ftLastAccessTime, buffer, ARRAY_SIZE(buffer)))
456 SetDlgItemTextW(hwndDlg, IDC_FPROP_ACCESSED, buffer);
458 if (FindExecutableW(props->path, NULL, buffer) <= (HINSTANCE)32)
459 return;
461 /* Information about executables */
462 if (SHGetFileInfoW(buffer, 0, &shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_SMALLICON) && shinfo.hIcon)
463 SendDlgItemMessageW(hwndDlg, IDC_FPROP_PROG_ICON, STM_SETICON, (WPARAM)shinfo.hIcon, 0);
465 if (get_program_description(buffer, buffer2, ARRAY_SIZE(buffer2)))
466 SetDlgItemTextW(hwndDlg, IDC_FPROP_PROG_NAME, buffer2);
467 else
469 WCHAR *p = wcsrchr(buffer, '\\');
470 SetDlgItemTextW(hwndDlg, IDC_FPROP_PROG_NAME, p ? ++p : buffer);
474 static INT_PTR CALLBACK file_properties_proc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
476 switch (uMsg)
478 case WM_INITDIALOG:
480 LPPROPSHEETPAGEW page = (LPPROPSHEETPAGEW)lParam;
481 SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)page->lParam);
482 init_file_properties_dlg(hwndDlg, (struct file_properties_info *)page->lParam);
483 break;
486 case WM_COMMAND:
487 if (LOWORD(wParam) == IDC_FPROP_PROG_CHANGE)
489 /* TODO: Implement file association dialog */
490 MessageBoxA(hwndDlg, "Not implemented yet.", "Error", MB_OK | MB_ICONEXCLAMATION);
492 else if (LOWORD(wParam) == IDC_FPROP_READONLY ||
493 LOWORD(wParam) == IDC_FPROP_HIDDEN ||
494 LOWORD(wParam) == IDC_FPROP_ARCHIVE)
496 SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
498 else if (LOWORD(wParam) == IDC_FPROP_PATH && HIWORD(wParam) == EN_CHANGE)
500 SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0);
502 break;
504 case WM_NOTIFY:
506 LPPSHNOTIFY notify = (LPPSHNOTIFY)lParam;
507 if (notify->hdr.code == PSN_APPLY)
509 struct file_properties_info *props = (struct file_properties_info *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
510 WCHAR newname[MAX_PATH], newpath[MAX_PATH];
511 DWORD attributes;
513 attributes = GetFileAttributesW(props->path);
514 if (attributes != INVALID_FILE_ATTRIBUTES)
516 attributes &= ~(FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_ARCHIVE);
518 if (SendDlgItemMessageW(hwndDlg, IDC_FPROP_READONLY, BM_GETCHECK, 0, 0) == BST_CHECKED)
519 attributes |= FILE_ATTRIBUTE_READONLY;
520 if (SendDlgItemMessageW(hwndDlg, IDC_FPROP_HIDDEN, BM_GETCHECK, 0, 0) == BST_CHECKED)
521 attributes |= FILE_ATTRIBUTE_HIDDEN;
522 if (SendDlgItemMessageW(hwndDlg, IDC_FPROP_ARCHIVE, BM_GETCHECK, 0, 0) == BST_CHECKED)
523 attributes |= FILE_ATTRIBUTE_ARCHIVE;
525 if (!SetFileAttributesW(props->path, attributes))
526 ERR("failed to update file attributes of %s\n", debugstr_w(props->path));
529 /* Update filename if it was changed */
530 if (GetDlgItemTextW(hwndDlg, IDC_FPROP_PATH, newname, ARRAY_SIZE(newname)) &&
531 wcscmp(props->filename, newname) &&
532 lstrlenW(props->dir) + lstrlenW(newname) + 2 < ARRAY_SIZE(newpath))
534 lstrcpyW(newpath, props->dir);
535 lstrcatW(newpath, L"\\");
536 lstrcatW(newpath, newname);
538 if (!MoveFileW(props->path, newpath))
539 ERR("failed to move file %s to %s\n", debugstr_w(props->path), debugstr_w(newpath));
540 else
542 WCHAR *p;
543 lstrcpyW(props->path, newpath);
544 lstrcpyW(props->dir, newpath);
545 if ((p = wcsrchr(props->dir, '\\')))
547 *p = 0;
548 props->filename = p + 1;
550 else
551 props->filename = props->dir;
552 SetDlgItemTextW(hwndDlg, IDC_FPROP_LOCATION, props->dir);
556 return TRUE;
559 break;
561 default:
562 break;
564 return FALSE;
567 static UINT CALLBACK file_properties_callback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGEW page)
569 struct file_properties_info *props = (struct file_properties_info *)page->lParam;
570 if (uMsg == PSPCB_RELEASE)
572 heap_free(props);
574 return 1;
577 static void init_file_properties_pages(IDataObject *dataobject, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
579 struct file_properties_info *props;
580 HPROPSHEETPAGE general_page;
581 PROPSHEETPAGEW propsheet;
582 FORMATETC format;
583 STGMEDIUM stgm;
584 HRESULT hr;
585 WCHAR *p;
587 props = heap_alloc(sizeof(*props));
588 if (!props) return;
590 format.cfFormat = CF_HDROP;
591 format.ptd = NULL;
592 format.dwAspect = DVASPECT_CONTENT;
593 format.lindex = -1;
594 format.tymed = TYMED_HGLOBAL;
596 hr = IDataObject_GetData(dataobject, &format, &stgm);
597 if (FAILED(hr)) goto error;
599 if (!DragQueryFileW((HDROP)stgm.u.hGlobal, 0, props->path, ARRAY_SIZE(props->path)))
601 ReleaseStgMedium(&stgm);
602 goto error;
605 ReleaseStgMedium(&stgm);
607 props->attrib = GetFileAttributesW(props->path);
608 if (props->attrib == INVALID_FILE_ATTRIBUTES)
609 goto error;
611 lstrcpyW(props->dir, props->path);
612 if ((p = wcsrchr(props->dir, '\\')))
614 *p = 0;
615 props->filename = p + 1;
617 else
618 props->filename = props->dir;
620 memset(&propsheet, 0, sizeof(propsheet));
621 propsheet.dwSize = sizeof(propsheet);
622 propsheet.dwFlags = PSP_DEFAULT | PSP_USECALLBACK;
623 propsheet.hInstance = shell32_hInstance;
624 if (props->attrib & FILE_ATTRIBUTE_DIRECTORY)
625 propsheet.u.pszTemplate = (LPWSTR)MAKEINTRESOURCE(IDD_FOLDER_PROPERTIES);
626 else
627 propsheet.u.pszTemplate = (LPWSTR)MAKEINTRESOURCE(IDD_FILE_PROPERTIES);
628 propsheet.pfnDlgProc = file_properties_proc;
629 propsheet.pfnCallback = file_properties_callback;
630 propsheet.lParam = (LPARAM)props;
632 general_page = CreatePropertySheetPageW(&propsheet);
633 if (general_page)
634 lpfnAddPage(general_page, lParam);
635 return;
637 error:
638 heap_free(props);
641 #define MAX_PROP_PAGES 99
643 static void DoOpenProperties(ContextMenu *This, HWND hwnd)
645 LPSHELLFOLDER lpDesktopSF;
646 LPSHELLFOLDER lpSF;
647 LPDATAOBJECT lpDo;
648 WCHAR wszFiletype[MAX_PATH];
649 WCHAR wszFilename[MAX_PATH];
650 PROPSHEETHEADERW psh;
651 HPROPSHEETPAGE hpages[MAX_PROP_PAGES];
652 HPSXA hpsxa;
653 UINT ret;
655 TRACE("(%p)->(wnd=%p)\n", This, hwnd);
657 ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
658 psh.dwSize = sizeof (PROPSHEETHEADERW);
659 psh.hwndParent = hwnd;
660 psh.dwFlags = PSH_PROPTITLE;
661 psh.nPages = 0;
662 psh.u3.phpage = hpages;
663 psh.u2.nStartPage = 0;
665 _ILSimpleGetTextW(This->apidl[0], (LPVOID)wszFilename, MAX_PATH);
666 psh.pszCaption = (LPCWSTR)wszFilename;
668 /* Find out where to look for the shell extensions */
669 if (_ILIsValue(This->apidl[0]))
671 char sTemp[64];
672 sTemp[0] = 0;
673 if (_ILGetExtension(This->apidl[0], sTemp, 64))
675 HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE);
676 MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wszFiletype, MAX_PATH);
678 else
680 wszFiletype[0] = 0;
683 else if (_ILIsFolder(This->apidl[0]))
685 lstrcpynW(wszFiletype, L"Folder", 64);
687 else if (_ILIsSpecialFolder(This->apidl[0]))
689 LPGUID folderGUID;
690 folderGUID = _ILGetGUIDPointer(This->apidl[0]);
691 lstrcpyW(wszFiletype, L"CLSID\\");
692 StringFromGUID2(folderGUID, &wszFiletype[6], MAX_PATH - 6);
694 else
696 FIXME("Requested properties for unknown type.\n");
697 return;
700 /* Get a suitable DataObject for accessing the files */
701 SHGetDesktopFolder(&lpDesktopSF);
702 if (_ILIsPidlSimple(This->pidl))
704 ret = IShellFolder_GetUIObjectOf(lpDesktopSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
705 &IID_IDataObject, NULL, (LPVOID *)&lpDo);
706 IShellFolder_Release(lpDesktopSF);
708 else
710 IShellFolder_BindToObject(lpDesktopSF, This->pidl, NULL, &IID_IShellFolder, (LPVOID*) &lpSF);
711 ret = IShellFolder_GetUIObjectOf(lpSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
712 &IID_IDataObject, NULL, (LPVOID *)&lpDo);
713 IShellFolder_Release(lpSF);
714 IShellFolder_Release(lpDesktopSF);
717 if (SUCCEEDED(ret))
719 init_file_properties_pages(lpDo, Properties_AddPropSheetCallback, (LPARAM)&psh);
721 hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
722 if (hpsxa != NULL)
724 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
725 SHDestroyPropSheetExtArray(hpsxa);
727 hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, L"*", MAX_PROP_PAGES - psh.nPages, lpDo);
728 if (hpsxa != NULL)
730 SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
731 SHDestroyPropSheetExtArray(hpsxa);
733 IDataObject_Release(lpDo);
736 if (psh.nPages)
737 PropertySheetW(&psh);
738 else
739 FIXME("No property pages found.\n");
742 static HRESULT WINAPI ItemMenu_InvokeCommand(
743 IContextMenu3 *iface,
744 LPCMINVOKECOMMANDINFO lpcmi)
746 ContextMenu *This = impl_from_IContextMenu3(iface);
748 if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
749 FIXME("Is an EX structure\n");
751 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
753 if (IS_INTRESOURCE(lpcmi->lpVerb) && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
755 TRACE("Invalid Verb %x\n", LOWORD(lpcmi->lpVerb));
756 return E_INVALIDARG;
759 if (IS_INTRESOURCE(lpcmi->lpVerb))
761 switch(LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
763 case FCIDM_SHVIEW_EXPLORE:
764 TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
765 DoOpenExplore(This, lpcmi->hwnd, "explore");
766 break;
767 case FCIDM_SHVIEW_OPEN:
768 TRACE("Verb FCIDM_SHVIEW_OPEN\n");
769 DoOpenExplore(This, lpcmi->hwnd, "open");
770 break;
771 case FCIDM_SHVIEW_RENAME:
773 IShellBrowser *browser;
775 /* get the active IShellView */
776 browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0);
777 if (browser)
779 IShellView *view;
781 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
783 TRACE("(shellview=%p)\n", view);
784 IShellView_SelectItem(view, This->apidl[0],
785 SVSI_DESELECTOTHERS|SVSI_EDIT|SVSI_ENSUREVISIBLE|SVSI_FOCUSED|SVSI_SELECT);
786 IShellView_Release(view);
789 break;
791 case FCIDM_SHVIEW_DELETE:
792 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
793 DoDelete(This);
794 break;
795 case FCIDM_SHVIEW_COPY:
796 TRACE("Verb FCIDM_SHVIEW_COPY\n");
797 DoCopyOrCut(This, lpcmi->hwnd, FALSE);
798 break;
799 case FCIDM_SHVIEW_CUT:
800 TRACE("Verb FCIDM_SHVIEW_CUT\n");
801 DoCopyOrCut(This, lpcmi->hwnd, TRUE);
802 break;
803 case FCIDM_SHVIEW_PROPERTIES:
804 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
805 DoOpenProperties(This, lpcmi->hwnd);
806 break;
807 default:
808 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
809 return E_INVALIDARG;
812 else
814 TRACE("Verb is %s\n",debugstr_a(lpcmi->lpVerb));
815 if (strcmp(lpcmi->lpVerb,"delete")==0)
816 DoDelete(This);
817 else if (strcmp(lpcmi->lpVerb,"copy")==0)
818 DoCopyOrCut(This, lpcmi->hwnd, FALSE);
819 else if (strcmp(lpcmi->lpVerb,"cut")==0)
820 DoCopyOrCut(This, lpcmi->hwnd, TRUE);
821 else if (strcmp(lpcmi->lpVerb,"properties")==0)
822 DoOpenProperties(This, lpcmi->hwnd);
823 else {
824 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi->lpVerb));
825 return E_FAIL;
828 return S_OK;
831 static HRESULT WINAPI ItemMenu_GetCommandString(IContextMenu3 *iface, UINT_PTR cmdid, UINT flags,
832 UINT *reserved, LPSTR name, UINT maxlen)
834 ContextMenu *This = impl_from_IContextMenu3(iface);
835 const WCHAR *cmdW = NULL;
836 HRESULT hr = S_OK;
838 TRACE("(%p)->(%lx, %#x, %p, %p, %u)\n", This, cmdid, flags, reserved, name, maxlen);
840 switch (flags)
842 case GCS_HELPTEXTA:
843 case GCS_HELPTEXTW:
844 hr = E_NOTIMPL;
845 break;
847 case GCS_VERBA:
848 case GCS_VERBW:
849 switch (cmdid + FCIDM_BASE)
851 case FCIDM_SHVIEW_OPEN:
852 cmdW = L"open";
853 break;
854 case FCIDM_SHVIEW_EXPLORE:
855 cmdW = L"explore";
856 break;
857 case FCIDM_SHVIEW_CUT:
858 cmdW = L"cut";
859 break;
860 case FCIDM_SHVIEW_COPY:
861 cmdW = L"copy";
862 break;
863 case FCIDM_SHVIEW_CREATELINK:
864 cmdW = L"link";
865 break;
866 case FCIDM_SHVIEW_DELETE:
867 cmdW = L"delete";
868 break;
869 case FCIDM_SHVIEW_PROPERTIES:
870 cmdW = L"properties";
871 break;
872 case FCIDM_SHVIEW_RENAME:
873 cmdW = L"rename";
874 break;
877 if (!cmdW)
879 hr = E_INVALIDARG;
880 break;
883 if (flags == GCS_VERBA)
884 WideCharToMultiByte(CP_ACP, 0, cmdW, -1, name, maxlen, NULL, NULL);
885 else
886 lstrcpynW((WCHAR *)name, cmdW, maxlen);
888 TRACE("name %s\n", flags == GCS_VERBA ? debugstr_a(name) : debugstr_w((WCHAR *)name));
889 break;
891 case GCS_VALIDATEA:
892 case GCS_VALIDATEW:
893 break;
896 return hr;
899 /**************************************************************************
900 * NOTES
901 * should be only in IContextMenu2 and IContextMenu3
902 * is nevertheless called from word95
904 static HRESULT WINAPI ContextMenu_HandleMenuMsg(IContextMenu3 *iface, UINT msg,
905 WPARAM wParam, LPARAM lParam)
907 ContextMenu *This = impl_from_IContextMenu3(iface);
908 FIXME("(%p)->(0x%x 0x%lx 0x%lx): stub\n", This, msg, wParam, lParam);
909 return E_NOTIMPL;
912 static HRESULT WINAPI ContextMenu_HandleMenuMsg2(IContextMenu3 *iface, UINT msg,
913 WPARAM wParam, LPARAM lParam, LRESULT *result)
915 ContextMenu *This = impl_from_IContextMenu3(iface);
916 FIXME("(%p)->(0x%x 0x%lx 0x%lx %p): stub\n", This, msg, wParam, lParam, result);
917 return E_NOTIMPL;
920 static const IContextMenu3Vtbl ItemContextMenuVtbl =
922 ContextMenu_QueryInterface,
923 ContextMenu_AddRef,
924 ContextMenu_Release,
925 ItemMenu_QueryContextMenu,
926 ItemMenu_InvokeCommand,
927 ItemMenu_GetCommandString,
928 ContextMenu_HandleMenuMsg,
929 ContextMenu_HandleMenuMsg2
932 static HRESULT WINAPI ShellExtInit_QueryInterface(IShellExtInit *iface, REFIID riid, void **obj)
934 ContextMenu *This = impl_from_IShellExtInit(iface);
935 return IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, obj);
938 static ULONG WINAPI ShellExtInit_AddRef(IShellExtInit *iface)
940 ContextMenu *This = impl_from_IShellExtInit(iface);
941 return IContextMenu3_AddRef(&This->IContextMenu3_iface);
944 static ULONG WINAPI ShellExtInit_Release(IShellExtInit *iface)
946 ContextMenu *This = impl_from_IShellExtInit(iface);
947 return IContextMenu3_Release(&This->IContextMenu3_iface);
950 static HRESULT WINAPI ShellExtInit_Initialize(IShellExtInit *iface, LPCITEMIDLIST folder,
951 IDataObject *dataobj, HKEY progidkey)
953 ContextMenu *This = impl_from_IShellExtInit(iface);
955 FIXME("(%p)->(%p %p %p): stub\n", This, folder, dataobj, progidkey);
957 return E_NOTIMPL;
960 static const IShellExtInitVtbl ShellExtInitVtbl =
962 ShellExtInit_QueryInterface,
963 ShellExtInit_AddRef,
964 ShellExtInit_Release,
965 ShellExtInit_Initialize
968 static HRESULT WINAPI ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **obj)
970 ContextMenu *This = impl_from_IObjectWithSite(iface);
971 return IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, obj);
974 static ULONG WINAPI ObjectWithSite_AddRef(IObjectWithSite *iface)
976 ContextMenu *This = impl_from_IObjectWithSite(iface);
977 return IContextMenu3_AddRef(&This->IContextMenu3_iface);
980 static ULONG WINAPI ObjectWithSite_Release(IObjectWithSite *iface)
982 ContextMenu *This = impl_from_IObjectWithSite(iface);
983 return IContextMenu3_Release(&This->IContextMenu3_iface);
986 static HRESULT WINAPI ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *site)
988 ContextMenu *This = impl_from_IObjectWithSite(iface);
990 FIXME("(%p)->(%p): stub\n", This, site);
992 return E_NOTIMPL;
995 static HRESULT WINAPI ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID riid, void **site)
997 ContextMenu *This = impl_from_IObjectWithSite(iface);
999 FIXME("(%p)->(%s %p): stub\n", This, debugstr_guid(riid), site);
1001 return E_NOTIMPL;
1004 static const IObjectWithSiteVtbl ObjectWithSiteVtbl =
1006 ObjectWithSite_QueryInterface,
1007 ObjectWithSite_AddRef,
1008 ObjectWithSite_Release,
1009 ObjectWithSite_SetSite,
1010 ObjectWithSite_GetSite,
1013 HRESULT ItemMenu_Constructor(IShellFolder *parent, LPCITEMIDLIST pidl, const LPCITEMIDLIST *apidl, UINT cidl,
1014 REFIID riid, void **pObj)
1016 ContextMenu* This;
1017 HRESULT hr;
1018 UINT i;
1020 This = heap_alloc(sizeof(*This));
1021 if (!This) return E_OUTOFMEMORY;
1023 This->IContextMenu3_iface.lpVtbl = &ItemContextMenuVtbl;
1024 This->IShellExtInit_iface.lpVtbl = &ShellExtInitVtbl;
1025 This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
1026 This->ref = 1;
1027 This->parent = parent;
1028 if (parent) IShellFolder_AddRef(parent);
1030 This->pidl = ILClone(pidl);
1031 This->apidl = _ILCopyaPidl(apidl, cidl);
1032 This->cidl = cidl;
1033 This->allvalues = TRUE;
1035 This->desktop = FALSE;
1037 for (i = 0; i < cidl; i++)
1038 This->allvalues &= (_ILIsValue(apidl[i]) ? 1 : 0);
1040 hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
1041 IContextMenu3_Release(&This->IContextMenu3_iface);
1043 return hr;
1046 /* Background menu implementation */
1047 static HRESULT WINAPI BackgroundMenu_QueryContextMenu(
1048 IContextMenu3 *iface,
1049 HMENU hMenu,
1050 UINT indexMenu,
1051 UINT idCmdFirst,
1052 UINT idCmdLast,
1053 UINT uFlags)
1055 ContextMenu *This = impl_from_IContextMenu3(iface);
1056 HMENU hMyMenu;
1057 UINT idMax;
1058 HRESULT hr;
1060 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
1061 This, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
1063 hMyMenu = LoadMenuA(shell32_hInstance, "MENU_002");
1064 if (uFlags & CMF_DEFAULTONLY)
1066 HMENU ourMenu = GetSubMenu(hMyMenu,0);
1067 UINT oldDef = GetMenuDefaultItem(hMenu,TRUE,GMDI_USEDISABLED);
1068 UINT newDef = GetMenuDefaultItem(ourMenu,TRUE,GMDI_USEDISABLED);
1069 if (newDef != oldDef)
1070 SetMenuDefaultItem(hMenu,newDef,TRUE);
1071 if (newDef!=0xFFFFFFFF)
1072 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, newDef+1);
1073 else
1074 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
1076 else
1078 Shell_MergeMenus (hMenu, GetSubMenu(hMyMenu,0), indexMenu,
1079 idCmdFirst - FCIDM_BASE, idCmdLast, MM_SUBMENUSHAVEIDS);
1080 idMax = max_menu_id(GetSubMenu(hMyMenu, 0), idCmdFirst - FCIDM_BASE, idCmdLast);
1081 hr = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, idMax-idCmdFirst);
1083 DestroyMenu(hMyMenu);
1085 TRACE("(%p)->returning 0x%x\n",This,hr);
1086 return hr;
1089 static void DoNewFolder(ContextMenu *This, IShellView *view)
1091 ISFHelper *helper;
1093 IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&helper);
1094 if (helper)
1096 WCHAR nameW[MAX_PATH];
1097 LPITEMIDLIST pidl;
1099 ISFHelper_GetUniqueName(helper, nameW, MAX_PATH);
1100 ISFHelper_AddFolder(helper, 0, nameW, &pidl);
1102 if (view)
1104 /* if we are in a shellview do labeledit */
1105 IShellView_SelectItem(view,
1106 pidl,(SVSI_DESELECTOTHERS | SVSI_EDIT | SVSI_ENSUREVISIBLE
1107 |SVSI_FOCUSED|SVSI_SELECT));
1110 SHFree(pidl);
1111 ISFHelper_Release(helper);
1115 static HRESULT paste_pidls(ContextMenu *This, ITEMIDLIST **pidls, UINT count)
1117 IShellFolder *psfDesktop;
1118 UINT i;
1119 HRESULT hr = S_OK;
1121 /* bind to the source shellfolder */
1122 hr = SHGetDesktopFolder(&psfDesktop);
1123 if (FAILED(hr))
1124 return hr;
1126 for (i = 0; SUCCEEDED(hr) && i < count; i++) {
1127 ITEMIDLIST *pidl_dir = NULL;
1128 ITEMIDLIST *pidl_item;
1129 IShellFolder *psfFrom = NULL;
1131 pidl_dir = ILClone(pidls[i]);
1132 ILRemoveLastID(pidl_dir);
1133 pidl_item = ILFindLastID(pidls[i]);
1134 hr = IShellFolder_BindToObject(psfDesktop, pidl_dir, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom);
1136 if (psfFrom)
1138 /* get source and destination shellfolder */
1139 ISFHelper *psfhlpdst = NULL, *psfhlpsrc = NULL;
1140 hr = IShellFolder_QueryInterface(This->parent, &IID_ISFHelper, (void**)&psfhlpdst);
1141 if (SUCCEEDED(hr))
1142 hr = IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (void**)&psfhlpsrc);
1144 /* do the copy/move */
1145 if (psfhlpdst && psfhlpsrc)
1147 hr = ISFHelper_CopyItems(psfhlpdst, psfFrom, 1, (LPCITEMIDLIST*)&pidl_item);
1148 /* FIXME handle move
1149 ISFHelper_DeleteItems(psfhlpsrc, 1, &pidl_item);
1152 if(psfhlpdst) ISFHelper_Release(psfhlpdst);
1153 if(psfhlpsrc) ISFHelper_Release(psfhlpsrc);
1154 IShellFolder_Release(psfFrom);
1156 SHFree(pidl_dir);
1159 IShellFolder_Release(psfDesktop);
1160 return hr;
1163 static HRESULT DoPaste(ContextMenu *This)
1165 IDataObject * pda;
1166 HRESULT hr;
1168 TRACE("\n");
1170 hr = OleGetClipboard(&pda);
1171 if(SUCCEEDED(hr))
1173 STGMEDIUM medium;
1174 FORMATETC formatetc;
1175 HRESULT format_hr;
1177 TRACE("pda=%p\n", pda);
1179 /* Set the FORMATETC structure*/
1180 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW), TYMED_HGLOBAL);
1182 /* Get the pidls from IDataObject */
1183 format_hr = IDataObject_GetData(pda,&formatetc,&medium);
1184 if(SUCCEEDED(format_hr))
1186 LPITEMIDLIST * apidl;
1187 LPITEMIDLIST pidl;
1189 LPIDA lpcida = GlobalLock(medium.u.hGlobal);
1190 TRACE("cida=%p\n", lpcida);
1191 if(lpcida)
1193 apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
1194 if (apidl)
1196 hr = paste_pidls(This, apidl, lpcida->cidl);
1197 _ILFreeaPidl(apidl, lpcida->cidl);
1198 SHFree(pidl);
1200 else
1201 hr = HRESULT_FROM_WIN32(GetLastError());
1202 GlobalUnlock(medium.u.hGlobal);
1204 else
1205 hr = HRESULT_FROM_WIN32(GetLastError());
1206 ReleaseStgMedium(&medium);
1209 if(FAILED(format_hr))
1211 InitFormatEtc(formatetc, CF_HDROP, TYMED_HGLOBAL);
1212 format_hr = IDataObject_GetData(pda,&formatetc,&medium);
1213 if(SUCCEEDED(format_hr))
1215 WCHAR path[MAX_PATH];
1216 UINT i, count;
1217 ITEMIDLIST **pidls;
1219 TRACE("CF_HDROP=%p\n", medium.u.hGlobal);
1220 count = DragQueryFileW(medium.u.hGlobal, -1, NULL, 0);
1221 pidls = SHAlloc(count*sizeof(ITEMIDLIST**));
1222 if (pidls)
1224 for (i = 0; i < count; i++)
1226 DragQueryFileW(medium.u.hGlobal, i, path, ARRAY_SIZE(path));
1227 if ((pidls[i] = ILCreateFromPathW(path)) == NULL)
1229 hr = E_FAIL;
1230 break;
1233 if (SUCCEEDED(hr))
1234 hr = paste_pidls(This, pidls, count);
1235 _ILFreeaPidl(pidls, count);
1237 else
1238 hr = HRESULT_FROM_WIN32(GetLastError());
1239 ReleaseStgMedium(&medium);
1243 if (FAILED(format_hr))
1245 ERR("there are no supported and retrievable clipboard formats\n");
1246 hr = format_hr;
1249 IDataObject_Release(pda);
1251 #if 0
1252 HGLOBAL hMem;
1254 OpenClipboard(NULL);
1255 hMem = GetClipboardData(CF_HDROP);
1257 if(hMem)
1259 char * pDropFiles = GlobalLock(hMem);
1260 if(pDropFiles)
1262 int len, offset = sizeof(DROPFILESTRUCT);
1264 while( pDropFiles[offset] != 0)
1266 len = strlen(pDropFiles + offset);
1267 TRACE("%s\n", pDropFiles + offset);
1268 offset += len+1;
1271 GlobalUnlock(hMem);
1273 CloseClipboard();
1274 #endif
1275 return hr;
1278 static HRESULT WINAPI BackgroundMenu_InvokeCommand(
1279 IContextMenu3 *iface,
1280 LPCMINVOKECOMMANDINFO lpcmi)
1282 ContextMenu *This = impl_from_IContextMenu3(iface);
1283 IShellBrowser *browser;
1284 IShellView *view = NULL;
1285 HWND hWnd = NULL;
1287 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", This, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
1289 /* get the active IShellView */
1290 if ((browser = (IShellBrowser*)SendMessageA(lpcmi->hwnd, CWM_GETISHELLBROWSER, 0, 0)))
1292 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(browser, &view)))
1293 IShellView_GetWindow(view, &hWnd);
1296 if(HIWORD(lpcmi->lpVerb))
1298 TRACE("%s\n", debugstr_a(lpcmi->lpVerb));
1300 if (!strcmp(lpcmi->lpVerb, CMDSTR_NEWFOLDERA))
1302 DoNewFolder(This, view);
1304 else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWLISTA))
1306 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW, 0), 0);
1308 else if (!strcmp(lpcmi->lpVerb, CMDSTR_VIEWDETAILSA))
1310 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW, 0), 0);
1312 else if (!strcmp(lpcmi->lpVerb, "paste"))
1314 DoPaste(This);
1316 else
1318 FIXME("please report: unknown verb %s\n", debugstr_a(lpcmi->lpVerb));
1321 else
1323 switch (LOWORD(lpcmi->lpVerb) + FCIDM_BASE)
1325 case FCIDM_SHVIEW_REFRESH:
1326 if (view) IShellView_Refresh(view);
1327 break;
1329 case FCIDM_SHVIEW_NEWFOLDER:
1330 DoNewFolder(This, view);
1331 break;
1333 case FCIDM_SHVIEW_INSERT:
1334 DoPaste(This);
1335 break;
1337 case FCIDM_SHVIEW_PROPERTIES:
1338 if (This->desktop) {
1339 ShellExecuteA(lpcmi->hwnd, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL, NULL, SW_SHOWNORMAL);
1340 } else {
1341 FIXME("launch item properties dialog\n");
1343 break;
1345 default:
1346 /* if it's an id just pass it to the parent shv */
1347 if (hWnd) SendMessageA(hWnd, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0);
1348 break;
1352 if (view)
1353 IShellView_Release(view);
1355 return S_OK;
1358 static HRESULT WINAPI BackgroundMenu_GetCommandString(
1359 IContextMenu3 *iface,
1360 UINT_PTR idCommand,
1361 UINT uFlags,
1362 UINT* lpReserved,
1363 LPSTR lpszName,
1364 UINT uMaxNameLen)
1366 ContextMenu *This = impl_from_IContextMenu3(iface);
1367 const WCHAR *cmdW = NULL;
1368 HRESULT hr = E_FAIL;
1370 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n",This, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
1372 switch (uFlags)
1374 case GCS_HELPTEXTA:
1375 case GCS_HELPTEXTW:
1376 hr = E_NOTIMPL;
1377 break;
1379 case GCS_VERBA:
1380 case GCS_VERBW:
1381 switch (idCommand + FCIDM_BASE)
1383 case FCIDM_SHVIEW_INSERT:
1384 cmdW = L"paste";
1385 break;
1386 case FCIDM_SHVIEW_PROPERTIES:
1387 cmdW = L"properties";
1388 break;
1391 if (!cmdW)
1393 hr = E_INVALIDARG;
1394 break;
1397 if (uFlags == GCS_VERBA)
1398 WideCharToMultiByte(CP_ACP, 0, cmdW, -1, lpszName, uMaxNameLen, NULL, NULL);
1399 else
1400 lstrcpynW((WCHAR *)lpszName, cmdW, uMaxNameLen);
1401 TRACE("name %s\n", uFlags == GCS_VERBA ? debugstr_a(lpszName) : debugstr_w((WCHAR *)lpszName));
1402 hr = S_OK;
1403 break;
1405 case GCS_VALIDATEA:
1406 case GCS_VALIDATEW:
1407 /* test the existence of the menu items, the file dialog enables
1408 the buttons according to this */
1409 if (HIWORD(idCommand))
1411 if (!strcmp((LPSTR)idCommand, CMDSTR_VIEWLISTA) ||
1412 !strcmp((LPSTR)idCommand, CMDSTR_VIEWDETAILSA) ||
1413 !strcmp((LPSTR)idCommand, CMDSTR_NEWFOLDERA))
1414 hr = S_OK;
1415 else
1417 FIXME("unknown command string %s\n", uFlags == GCS_VALIDATEA ? debugstr_a((LPSTR)idCommand) : debugstr_w((WCHAR*)idCommand));
1418 hr = E_FAIL;
1421 break;
1423 return hr;
1426 static const IContextMenu3Vtbl BackgroundContextMenuVtbl =
1428 ContextMenu_QueryInterface,
1429 ContextMenu_AddRef,
1430 ContextMenu_Release,
1431 BackgroundMenu_QueryContextMenu,
1432 BackgroundMenu_InvokeCommand,
1433 BackgroundMenu_GetCommandString,
1434 ContextMenu_HandleMenuMsg,
1435 ContextMenu_HandleMenuMsg2
1438 HRESULT BackgroundMenu_Constructor(IShellFolder *parent, BOOL desktop, REFIID riid, void **pObj)
1440 ContextMenu *This;
1441 HRESULT hr;
1443 This = heap_alloc(sizeof(*This));
1444 if (!This) return E_OUTOFMEMORY;
1446 This->IContextMenu3_iface.lpVtbl = &BackgroundContextMenuVtbl;
1447 This->IShellExtInit_iface.lpVtbl = &ShellExtInitVtbl;
1448 This->IObjectWithSite_iface.lpVtbl = &ObjectWithSiteVtbl;
1449 This->ref = 1;
1450 This->parent = parent;
1452 This->pidl = NULL;
1453 This->apidl = NULL;
1454 This->cidl = 0;
1455 This->allvalues = FALSE;
1457 This->desktop = desktop;
1458 if (parent) IShellFolder_AddRef(parent);
1460 hr = IContextMenu3_QueryInterface(&This->IContextMenu3_iface, riid, pObj);
1461 IContextMenu3_Release(&This->IContextMenu3_iface);
1463 return hr;