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
25 #define NONAMELESSUNION
36 #include "shell32_main.h"
37 #include "shellfolder.h"
42 #include "wine/heap.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
47 #define FCIDM_BASE 0x7000
51 IContextMenu3 IContextMenu3_iface
;
52 IShellExtInit IShellExtInit_iface
;
53 IObjectWithSite IObjectWithSite_iface
;
59 LPITEMIDLIST pidl
; /* root pidl */
60 LPITEMIDLIST
*apidl
; /* array of child pidls */
64 /* background menu data */
68 static inline ContextMenu
*impl_from_IContextMenu3(IContextMenu3
*iface
)
70 return CONTAINING_RECORD(iface
, ContextMenu
, IContextMenu3_iface
);
73 static inline ContextMenu
*impl_from_IShellExtInit(IShellExtInit
*iface
)
75 return CONTAINING_RECORD(iface
, ContextMenu
, IShellExtInit_iface
);
78 static inline ContextMenu
*impl_from_IObjectWithSite(IObjectWithSite
*iface
)
80 return CONTAINING_RECORD(iface
, ContextMenu
, IObjectWithSite_iface
);
83 static HRESULT WINAPI
ContextMenu_QueryInterface(IContextMenu3
*iface
, REFIID riid
, LPVOID
*ppvObj
)
85 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
87 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), ppvObj
);
91 if (IsEqualIID(riid
, &IID_IUnknown
) ||
92 IsEqualIID(riid
, &IID_IContextMenu
) ||
93 IsEqualIID(riid
, &IID_IContextMenu2
) ||
94 IsEqualIID(riid
, &IID_IContextMenu3
))
96 *ppvObj
= &This
->IContextMenu3_iface
;
98 else if (IsEqualIID(riid
, &IID_IShellExtInit
))
100 *ppvObj
= &This
->IShellExtInit_iface
;
102 else if (IsEqualIID(riid
, &IID_IObjectWithSite
))
104 *ppvObj
= &This
->IObjectWithSite_iface
;
109 IContextMenu3_AddRef(iface
);
113 TRACE("-- Interface: E_NOINTERFACE\n");
114 return E_NOINTERFACE
;
117 static ULONG WINAPI
ContextMenu_AddRef(IContextMenu3
*iface
)
119 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
120 ULONG ref
= InterlockedIncrement(&This
->ref
);
121 TRACE("(%p)->(%lu)\n", This
, ref
);
125 static ULONG WINAPI
ContextMenu_Release(IContextMenu3
*iface
)
127 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
128 ULONG ref
= InterlockedDecrement(&This
->ref
);
130 TRACE("(%p)->(%lu)\n", This
, ref
);
135 IShellFolder_Release(This
->parent
);
138 _ILFreeaPidl(This
->apidl
, This
->cidl
);
146 static UINT
max_menu_id(HMENU hmenu
, UINT offset
, UINT last
)
151 for (i
= GetMenuItemCount(hmenu
) - 1; i
>= 0; i
--)
154 memset(&item
, 0, sizeof(MENUITEMINFOW
));
155 item
.cbSize
= sizeof(MENUITEMINFOW
);
156 item
.fMask
= MIIM_ID
| MIIM_SUBMENU
| MIIM_TYPE
;
157 if (!GetMenuItemInfoW(hmenu
, i
, TRUE
, &item
))
159 if (!(item
.fType
& MFT_SEPARATOR
))
163 UINT submenu_max_id
= max_menu_id(item
.hSubMenu
, offset
, last
);
164 if (max_id
< submenu_max_id
)
165 max_id
= submenu_max_id
;
167 if (item
.wID
+ offset
<= last
)
169 if (max_id
<= item
.wID
+ offset
)
170 max_id
= item
.wID
+ offset
+ 1;
177 static HRESULT WINAPI
ItemMenu_QueryContextMenu(
178 IContextMenu3
*iface
,
185 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
188 TRACE("(%p)->(%p %d 0x%x 0x%x 0x%x )\n", This
, hmenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
190 if(!(CMF_DEFAULTONLY
& uFlags
) && This
->cidl
> 0)
192 HMENU hmenures
= LoadMenuW(shell32_hInstance
, MAKEINTRESOURCEW(MENU_SHV_FILE
));
194 if(uFlags
& CMF_EXPLORE
)
195 RemoveMenu(hmenures
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
197 Shell_MergeMenus(hmenu
, GetSubMenu(hmenures
, 0), indexMenu
, idCmdFirst
- FCIDM_BASE
, idCmdLast
, MM_SUBMENUSHAVEIDS
);
198 uIDMax
= max_menu_id(GetSubMenu(hmenures
, 0), idCmdFirst
- FCIDM_BASE
, idCmdLast
);
200 DestroyMenu(hmenures
);
206 mi
.cbSize
= sizeof(mi
);
207 mi
.fMask
= MIIM_ID
| MIIM_STRING
| MIIM_FTYPE
;
210 GetMenuItemInfoW(hmenu
, FCIDM_SHVIEW_EXPLORE
- FCIDM_BASE
+ idCmdFirst
, MF_BYCOMMAND
, &mi
);
211 RemoveMenu(hmenu
, FCIDM_SHVIEW_EXPLORE
- FCIDM_BASE
+ idCmdFirst
, MF_BYCOMMAND
);
213 mi
.cbSize
= sizeof(mi
);
214 mi
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
| MIIM_STRING
;
216 mi
.fState
= MFS_ENABLED
;
217 mi
.wID
= FCIDM_SHVIEW_EXPLORE
- FCIDM_BASE
+ idCmdFirst
;
218 mi
.fType
= MFT_STRING
;
219 InsertMenuItemW(hmenu
, (uFlags
& CMF_EXPLORE
) ? 1 : 2, MF_BYPOSITION
, &mi
);
222 SetMenuDefaultItem(hmenu
, 0, MF_BYPOSITION
);
224 if(uFlags
& ~CMF_CANRENAME
)
225 RemoveMenu(hmenu
, FCIDM_SHVIEW_RENAME
- FCIDM_BASE
+ idCmdFirst
, MF_BYCOMMAND
);
228 UINT enable
= MF_BYCOMMAND
;
230 /* can't rename more than one item at a time*/
231 if (!This
->apidl
|| This
->cidl
> 1)
232 enable
|= MFS_DISABLED
;
235 DWORD attr
= SFGAO_CANRENAME
;
237 IShellFolder_GetAttributesOf(This
->parent
, 1, (LPCITEMIDLIST
*)This
->apidl
, &attr
);
238 enable
|= (attr
& SFGAO_CANRENAME
) ? MFS_ENABLED
: MFS_DISABLED
;
241 EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
- FCIDM_BASE
+ idCmdFirst
, enable
);
244 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, uIDMax
-idCmdFirst
);
246 return MAKE_HRESULT(SEVERITY_SUCCESS
, 0, 0);
249 /**************************************************************************
255 static void DoOpenExplore(ContextMenu
*This
, HWND hwnd
, LPCSTR verb
)
258 BOOL bFolderFound
= FALSE
;
260 SHELLEXECUTEINFOA sei
;
262 /* Find the first item in the list that is not a value. These commands
263 should never be invoked if there isn't at least one folder item in the list.*/
265 for(i
= 0; i
<This
->cidl
; i
++)
267 if(!_ILIsValue(This
->apidl
[i
]))
274 if (!bFolderFound
) return;
276 pidlFQ
= ILCombine(This
->pidl
, This
->apidl
[i
]);
278 ZeroMemory(&sei
, sizeof(sei
));
279 sei
.cbSize
= sizeof(sei
);
280 sei
.fMask
= SEE_MASK_IDLIST
| SEE_MASK_CLASSNAME
;
281 sei
.lpIDList
= pidlFQ
;
282 sei
.lpClass
= "Folder";
284 sei
.nShow
= SW_SHOWNORMAL
;
286 ShellExecuteExA(&sei
);
290 /**************************************************************************
293 * deletes the currently selected items
295 static void DoDelete(ContextMenu
*This
)
299 IShellFolder_QueryInterface(This
->parent
, &IID_ISFHelper
, (void**)&helper
);
302 ISFHelper_DeleteItems(helper
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
);
303 ISFHelper_Release(helper
);
307 /**************************************************************************
310 * copies the currently selected items into the clipboard
312 static void DoCopyOrCut(ContextMenu
*This
, HWND hwnd
, BOOL cut
)
314 IDataObject
*dataobject
;
316 TRACE("(%p)->(wnd=%p, cut=%d)\n", This
, hwnd
, cut
);
318 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->parent
, hwnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
, 0, (void**)&dataobject
)))
320 OleSetClipboard(dataobject
);
321 IDataObject_Release(dataobject
);
325 /**************************************************************************
326 * Properties_AddPropSheetCallback
328 * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
329 * propertysheet pages from shell extensions.
331 static BOOL CALLBACK
Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage
, LPARAM lparam
)
333 LPPROPSHEETHEADERW psh
= (LPPROPSHEETHEADERW
) lparam
;
334 psh
->u3
.phpage
[psh
->nPages
++] = hpage
;
339 static BOOL
format_date(FILETIME
*time
, WCHAR
*buffer
, DWORD size
)
345 if (!FileTimeToLocalFileTime(time
, &ft
))
348 if (!FileTimeToSystemTime(&ft
, &st
))
351 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, DATE_LONGDATE
, &st
, NULL
, buffer
, size
);
354 buffer
[ret
- 1] = ' ';
355 ret
= GetTimeFormatW(LOCALE_USER_DEFAULT
, 0, &st
, NULL
, buffer
+ ret
, size
- ret
);
360 static BOOL
get_program_description(WCHAR
*path
, WCHAR
*buffer
, DWORD size
)
362 WCHAR fileDescW
[41], *desc
;
363 DWORD versize
, *lang
;
368 versize
= GetFileVersionInfoSizeW(path
, NULL
);
369 if (!versize
) return FALSE
;
371 data
= heap_alloc(versize
);
372 if (!data
) return FALSE
;
374 if (!GetFileVersionInfoW(path
, 0, versize
, data
))
377 if (!VerQueryValueW(data
, L
"\\VarFileInfo\\Translation", (LPVOID
*)&lang
, &llen
))
380 for (i
= 0; i
< llen
/ sizeof(DWORD
); i
++)
382 swprintf(fileDescW
, ARRAY_SIZE(fileDescW
), L
"\\StringFileInfo\\%04x%04x\\FileDescription",
383 LOWORD(lang
[i
]), HIWORD(lang
[i
]));
384 if (VerQueryValueW(data
, fileDescW
, (LPVOID
*)&desc
, &dlen
))
386 if (dlen
> size
- 1) dlen
= size
- 1;
387 memcpy(buffer
, desc
, dlen
* sizeof(WCHAR
));
399 struct file_properties_info
401 WCHAR path
[MAX_PATH
];
407 static void init_file_properties_dlg(HWND hwndDlg
, struct file_properties_info
*props
)
409 WCHAR buffer
[MAX_PATH
], buffer2
[MAX_PATH
];
410 WIN32_FILE_ATTRIBUTE_DATA exinfo
;
413 SetDlgItemTextW(hwndDlg
, IDC_FPROP_PATH
, props
->filename
);
414 SetDlgItemTextW(hwndDlg
, IDC_FPROP_LOCATION
, props
->dir
);
416 if (SHGetFileInfoW(props
->path
, 0, &shinfo
, sizeof(shinfo
), SHGFI_TYPENAME
|SHGFI_ICON
))
420 SendDlgItemMessageW(hwndDlg
, IDC_FPROP_ICON
, STM_SETICON
, (WPARAM
)shinfo
.hIcon
, 0);
421 DestroyIcon(shinfo
.hIcon
);
423 if (shinfo
.szTypeName
[0])
424 SetDlgItemTextW(hwndDlg
, IDC_FPROP_TYPE
, shinfo
.szTypeName
);
427 if (!GetFileAttributesExW(props
->path
, GetFileExInfoStandard
, &exinfo
))
430 if (format_date(&exinfo
.ftCreationTime
, buffer
, ARRAY_SIZE(buffer
)))
431 SetDlgItemTextW(hwndDlg
, IDC_FPROP_CREATED
, buffer
);
433 if (exinfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
434 SendDlgItemMessageW(hwndDlg
, IDC_FPROP_READONLY
, BM_SETCHECK
, BST_CHECKED
, 0);
435 if (exinfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
436 SendDlgItemMessageW(hwndDlg
, IDC_FPROP_HIDDEN
, BM_SETCHECK
, BST_CHECKED
, 0);
437 if (exinfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
)
438 SendDlgItemMessageW(hwndDlg
, IDC_FPROP_ARCHIVE
, BM_SETCHECK
, BST_CHECKED
, 0);
440 if (exinfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
442 SetDlgItemTextW(hwndDlg
, IDC_FPROP_SIZE
, L
"(unknown)");
443 /* TODO: Implement counting for directories */
447 /* Information about files only */
448 StrFormatByteSizeW(((LONGLONG
)exinfo
.nFileSizeHigh
<< 32) | exinfo
.nFileSizeLow
,
449 buffer
, ARRAY_SIZE(buffer
));
450 SetDlgItemTextW(hwndDlg
, IDC_FPROP_SIZE
, buffer
);
452 if (format_date(&exinfo
.ftLastWriteTime
, buffer
, ARRAY_SIZE(buffer
)))
453 SetDlgItemTextW(hwndDlg
, IDC_FPROP_MODIFIED
, buffer
);
454 if (format_date(&exinfo
.ftLastAccessTime
, buffer
, ARRAY_SIZE(buffer
)))
455 SetDlgItemTextW(hwndDlg
, IDC_FPROP_ACCESSED
, buffer
);
457 if (FindExecutableW(props
->path
, NULL
, buffer
) <= (HINSTANCE
)32)
460 /* Information about executables */
461 if (SHGetFileInfoW(buffer
, 0, &shinfo
, sizeof(shinfo
), SHGFI_ICON
| SHGFI_SMALLICON
) && shinfo
.hIcon
)
462 SendDlgItemMessageW(hwndDlg
, IDC_FPROP_PROG_ICON
, STM_SETICON
, (WPARAM
)shinfo
.hIcon
, 0);
464 if (get_program_description(buffer
, buffer2
, ARRAY_SIZE(buffer2
)))
465 SetDlgItemTextW(hwndDlg
, IDC_FPROP_PROG_NAME
, buffer2
);
468 WCHAR
*p
= wcsrchr(buffer
, '\\');
469 SetDlgItemTextW(hwndDlg
, IDC_FPROP_PROG_NAME
, p
? ++p
: buffer
);
473 static INT_PTR CALLBACK
file_properties_proc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
479 LPPROPSHEETPAGEW page
= (LPPROPSHEETPAGEW
)lParam
;
480 SetWindowLongPtrW(hwndDlg
, DWLP_USER
, (LONG_PTR
)page
->lParam
);
481 init_file_properties_dlg(hwndDlg
, (struct file_properties_info
*)page
->lParam
);
486 if (LOWORD(wParam
) == IDC_FPROP_PROG_CHANGE
)
488 /* TODO: Implement file association dialog */
489 MessageBoxA(hwndDlg
, "Not implemented yet.", "Error", MB_OK
| MB_ICONEXCLAMATION
);
491 else if (LOWORD(wParam
) == IDC_FPROP_READONLY
||
492 LOWORD(wParam
) == IDC_FPROP_HIDDEN
||
493 LOWORD(wParam
) == IDC_FPROP_ARCHIVE
)
495 SendMessageW(GetParent(hwndDlg
), PSM_CHANGED
, (WPARAM
)hwndDlg
, 0);
497 else if (LOWORD(wParam
) == IDC_FPROP_PATH
&& HIWORD(wParam
) == EN_CHANGE
)
499 SendMessageW(GetParent(hwndDlg
), PSM_CHANGED
, (WPARAM
)hwndDlg
, 0);
505 LPPSHNOTIFY notify
= (LPPSHNOTIFY
)lParam
;
506 if (notify
->hdr
.code
== PSN_APPLY
)
508 struct file_properties_info
*props
= (struct file_properties_info
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
509 WCHAR newname
[MAX_PATH
], newpath
[MAX_PATH
];
512 attributes
= GetFileAttributesW(props
->path
);
513 if (attributes
!= INVALID_FILE_ATTRIBUTES
)
515 attributes
&= ~(FILE_ATTRIBUTE_READONLY
|FILE_ATTRIBUTE_HIDDEN
|FILE_ATTRIBUTE_ARCHIVE
);
517 if (SendDlgItemMessageW(hwndDlg
, IDC_FPROP_READONLY
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
518 attributes
|= FILE_ATTRIBUTE_READONLY
;
519 if (SendDlgItemMessageW(hwndDlg
, IDC_FPROP_HIDDEN
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
520 attributes
|= FILE_ATTRIBUTE_HIDDEN
;
521 if (SendDlgItemMessageW(hwndDlg
, IDC_FPROP_ARCHIVE
, BM_GETCHECK
, 0, 0) == BST_CHECKED
)
522 attributes
|= FILE_ATTRIBUTE_ARCHIVE
;
524 if (!SetFileAttributesW(props
->path
, attributes
))
525 ERR("failed to update file attributes of %s\n", debugstr_w(props
->path
));
528 /* Update filename if it was changed */
529 if (GetDlgItemTextW(hwndDlg
, IDC_FPROP_PATH
, newname
, ARRAY_SIZE(newname
)) &&
530 wcscmp(props
->filename
, newname
) &&
531 lstrlenW(props
->dir
) + lstrlenW(newname
) + 2 < ARRAY_SIZE(newpath
))
533 lstrcpyW(newpath
, props
->dir
);
534 lstrcatW(newpath
, L
"\\");
535 lstrcatW(newpath
, newname
);
537 if (!MoveFileW(props
->path
, newpath
))
538 ERR("failed to move file %s to %s\n", debugstr_w(props
->path
), debugstr_w(newpath
));
542 lstrcpyW(props
->path
, newpath
);
543 lstrcpyW(props
->dir
, newpath
);
544 if ((p
= wcsrchr(props
->dir
, '\\')))
547 props
->filename
= p
+ 1;
550 props
->filename
= props
->dir
;
551 SetDlgItemTextW(hwndDlg
, IDC_FPROP_LOCATION
, props
->dir
);
566 static UINT CALLBACK
file_properties_callback(HWND hwnd
, UINT uMsg
, LPPROPSHEETPAGEW page
)
568 struct file_properties_info
*props
= (struct file_properties_info
*)page
->lParam
;
569 if (uMsg
== PSPCB_RELEASE
)
576 static void init_file_properties_pages(IDataObject
*dataobject
, LPFNADDPROPSHEETPAGE lpfnAddPage
, LPARAM lParam
)
578 struct file_properties_info
*props
;
579 HPROPSHEETPAGE general_page
;
580 PROPSHEETPAGEW propsheet
;
586 props
= heap_alloc(sizeof(*props
));
589 format
.cfFormat
= CF_HDROP
;
591 format
.dwAspect
= DVASPECT_CONTENT
;
593 format
.tymed
= TYMED_HGLOBAL
;
595 hr
= IDataObject_GetData(dataobject
, &format
, &stgm
);
596 if (FAILED(hr
)) goto error
;
598 if (!DragQueryFileW((HDROP
)stgm
.u
.hGlobal
, 0, props
->path
, ARRAY_SIZE(props
->path
)))
600 ReleaseStgMedium(&stgm
);
604 ReleaseStgMedium(&stgm
);
606 props
->attrib
= GetFileAttributesW(props
->path
);
607 if (props
->attrib
== INVALID_FILE_ATTRIBUTES
)
610 lstrcpyW(props
->dir
, props
->path
);
611 if ((p
= wcsrchr(props
->dir
, '\\')))
614 props
->filename
= p
+ 1;
617 props
->filename
= props
->dir
;
619 memset(&propsheet
, 0, sizeof(propsheet
));
620 propsheet
.dwSize
= sizeof(propsheet
);
621 propsheet
.dwFlags
= PSP_DEFAULT
| PSP_USECALLBACK
;
622 propsheet
.hInstance
= shell32_hInstance
;
623 if (props
->attrib
& FILE_ATTRIBUTE_DIRECTORY
)
624 propsheet
.u
.pszTemplate
= (LPWSTR
)MAKEINTRESOURCE(IDD_FOLDER_PROPERTIES
);
626 propsheet
.u
.pszTemplate
= (LPWSTR
)MAKEINTRESOURCE(IDD_FILE_PROPERTIES
);
627 propsheet
.pfnDlgProc
= file_properties_proc
;
628 propsheet
.pfnCallback
= file_properties_callback
;
629 propsheet
.lParam
= (LPARAM
)props
;
631 general_page
= CreatePropertySheetPageW(&propsheet
);
633 lpfnAddPage(general_page
, lParam
);
640 #define MAX_PROP_PAGES 99
642 static void DoOpenProperties(ContextMenu
*This
, HWND hwnd
)
644 LPSHELLFOLDER lpDesktopSF
;
647 WCHAR wszFiletype
[MAX_PATH
];
648 WCHAR wszFilename
[MAX_PATH
];
649 PROPSHEETHEADERW psh
;
650 HPROPSHEETPAGE hpages
[MAX_PROP_PAGES
];
654 TRACE("(%p)->(wnd=%p)\n", This
, hwnd
);
656 ZeroMemory(&psh
, sizeof(PROPSHEETHEADERW
));
657 psh
.dwSize
= sizeof (PROPSHEETHEADERW
);
658 psh
.hwndParent
= hwnd
;
659 psh
.dwFlags
= PSH_PROPTITLE
;
661 psh
.u3
.phpage
= hpages
;
662 psh
.u2
.nStartPage
= 0;
664 _ILSimpleGetTextW(This
->apidl
[0], (LPVOID
)wszFilename
, MAX_PATH
);
665 psh
.pszCaption
= (LPCWSTR
)wszFilename
;
667 /* Find out where to look for the shell extensions */
668 if (_ILIsValue(This
->apidl
[0]))
672 if (_ILGetExtension(This
->apidl
[0], sTemp
, 64))
674 HCR_MapTypeToValueA(sTemp
, sTemp
, 64, TRUE
);
675 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wszFiletype
, MAX_PATH
);
682 else if (_ILIsFolder(This
->apidl
[0]))
684 lstrcpynW(wszFiletype
, L
"Folder", 64);
686 else if (_ILIsSpecialFolder(This
->apidl
[0]))
689 folderGUID
= _ILGetGUIDPointer(This
->apidl
[0]);
690 lstrcpyW(wszFiletype
, L
"CLSID\\");
691 StringFromGUID2(folderGUID
, &wszFiletype
[6], MAX_PATH
- 6);
695 FIXME("Requested properties for unknown type.\n");
699 /* Get a suitable DataObject for accessing the files */
700 SHGetDesktopFolder(&lpDesktopSF
);
701 if (_ILIsPidlSimple(This
->pidl
))
703 ret
= IShellFolder_GetUIObjectOf(lpDesktopSF
, hwnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
704 &IID_IDataObject
, NULL
, (LPVOID
*)&lpDo
);
705 IShellFolder_Release(lpDesktopSF
);
709 IShellFolder_BindToObject(lpDesktopSF
, This
->pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*) &lpSF
);
710 ret
= IShellFolder_GetUIObjectOf(lpSF
, hwnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
711 &IID_IDataObject
, NULL
, (LPVOID
*)&lpDo
);
712 IShellFolder_Release(lpSF
);
713 IShellFolder_Release(lpDesktopSF
);
718 init_file_properties_pages(lpDo
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
720 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, wszFiletype
, MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
723 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
724 SHDestroyPropSheetExtArray(hpsxa
);
726 hpsxa
= SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT
, L
"*", MAX_PROP_PAGES
- psh
.nPages
, lpDo
);
729 SHAddFromPropSheetExtArray(hpsxa
, Properties_AddPropSheetCallback
, (LPARAM
)&psh
);
730 SHDestroyPropSheetExtArray(hpsxa
);
732 IDataObject_Release(lpDo
);
736 PropertySheetW(&psh
);
738 FIXME("No property pages found.\n");
741 static HRESULT WINAPI
ItemMenu_InvokeCommand(
742 IContextMenu3
*iface
,
743 LPCMINVOKECOMMANDINFO lpcmi
)
745 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
747 if (lpcmi
->cbSize
!= sizeof(CMINVOKECOMMANDINFO
))
748 FIXME("Is an EX structure\n");
750 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This
,lpcmi
,lpcmi
->lpVerb
, lpcmi
->hwnd
);
752 if (IS_INTRESOURCE(lpcmi
->lpVerb
) && LOWORD(lpcmi
->lpVerb
) > FCIDM_SHVIEWLAST
)
754 TRACE("Invalid Verb %x\n", LOWORD(lpcmi
->lpVerb
));
758 if (IS_INTRESOURCE(lpcmi
->lpVerb
))
760 switch(LOWORD(lpcmi
->lpVerb
) + FCIDM_BASE
)
762 case FCIDM_SHVIEW_EXPLORE
:
763 TRACE("Verb FCIDM_SHVIEW_EXPLORE\n");
764 DoOpenExplore(This
, lpcmi
->hwnd
, "explore");
766 case FCIDM_SHVIEW_OPEN
:
767 TRACE("Verb FCIDM_SHVIEW_OPEN\n");
768 DoOpenExplore(This
, lpcmi
->hwnd
, "open");
770 case FCIDM_SHVIEW_RENAME
:
772 IShellBrowser
*browser
;
774 /* get the active IShellView */
775 browser
= (IShellBrowser
*)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
, 0, 0);
780 if(SUCCEEDED(IShellBrowser_QueryActiveShellView(browser
, &view
)))
782 TRACE("(shellview=%p)\n", view
);
783 IShellView_SelectItem(view
, This
->apidl
[0],
784 SVSI_DESELECTOTHERS
|SVSI_EDIT
|SVSI_ENSUREVISIBLE
|SVSI_FOCUSED
|SVSI_SELECT
);
785 IShellView_Release(view
);
790 case FCIDM_SHVIEW_DELETE
:
791 TRACE("Verb FCIDM_SHVIEW_DELETE\n");
794 case FCIDM_SHVIEW_COPY
:
795 TRACE("Verb FCIDM_SHVIEW_COPY\n");
796 DoCopyOrCut(This
, lpcmi
->hwnd
, FALSE
);
798 case FCIDM_SHVIEW_CUT
:
799 TRACE("Verb FCIDM_SHVIEW_CUT\n");
800 DoCopyOrCut(This
, lpcmi
->hwnd
, TRUE
);
802 case FCIDM_SHVIEW_PROPERTIES
:
803 TRACE("Verb FCIDM_SHVIEW_PROPERTIES\n");
804 DoOpenProperties(This
, lpcmi
->hwnd
);
807 FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi
->lpVerb
));
813 TRACE("Verb is %s\n",debugstr_a(lpcmi
->lpVerb
));
814 if (strcmp(lpcmi
->lpVerb
,"delete")==0)
816 else if (strcmp(lpcmi
->lpVerb
,"copy")==0)
817 DoCopyOrCut(This
, lpcmi
->hwnd
, FALSE
);
818 else if (strcmp(lpcmi
->lpVerb
,"cut")==0)
819 DoCopyOrCut(This
, lpcmi
->hwnd
, TRUE
);
820 else if (strcmp(lpcmi
->lpVerb
,"properties")==0)
821 DoOpenProperties(This
, lpcmi
->hwnd
);
823 FIXME("Unhandled string verb %s\n",debugstr_a(lpcmi
->lpVerb
));
830 static HRESULT WINAPI
ItemMenu_GetCommandString(IContextMenu3
*iface
, UINT_PTR cmdid
, UINT flags
,
831 UINT
*reserved
, LPSTR name
, UINT maxlen
)
833 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
834 const WCHAR
*cmdW
= NULL
;
837 TRACE("(%p)->(%Ix, %#x, %p, %p, %u)\n", This
, cmdid
, flags
, reserved
, name
, maxlen
);
848 switch (cmdid
+ FCIDM_BASE
)
850 case FCIDM_SHVIEW_OPEN
:
853 case FCIDM_SHVIEW_EXPLORE
:
856 case FCIDM_SHVIEW_CUT
:
859 case FCIDM_SHVIEW_COPY
:
862 case FCIDM_SHVIEW_CREATELINK
:
865 case FCIDM_SHVIEW_DELETE
:
868 case FCIDM_SHVIEW_PROPERTIES
:
869 cmdW
= L
"properties";
871 case FCIDM_SHVIEW_RENAME
:
882 if (flags
== GCS_VERBA
)
883 WideCharToMultiByte(CP_ACP
, 0, cmdW
, -1, name
, maxlen
, NULL
, NULL
);
885 lstrcpynW((WCHAR
*)name
, cmdW
, maxlen
);
887 TRACE("name %s\n", flags
== GCS_VERBA
? debugstr_a(name
) : debugstr_w((WCHAR
*)name
));
898 /**************************************************************************
900 * should be only in IContextMenu2 and IContextMenu3
901 * is nevertheless called from word95
903 static HRESULT WINAPI
ContextMenu_HandleMenuMsg(IContextMenu3
*iface
, UINT msg
,
904 WPARAM wParam
, LPARAM lParam
)
906 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
907 FIXME("(%p)->(0x%x 0x%Ix 0x%Ix): stub\n", This
, msg
, wParam
, lParam
);
911 static HRESULT WINAPI
ContextMenu_HandleMenuMsg2(IContextMenu3
*iface
, UINT msg
,
912 WPARAM wParam
, LPARAM lParam
, LRESULT
*result
)
914 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
915 FIXME("(%p)->(0x%x 0x%Ix 0x%Ix %p): stub\n", This
, msg
, wParam
, lParam
, result
);
919 static const IContextMenu3Vtbl ItemContextMenuVtbl
=
921 ContextMenu_QueryInterface
,
924 ItemMenu_QueryContextMenu
,
925 ItemMenu_InvokeCommand
,
926 ItemMenu_GetCommandString
,
927 ContextMenu_HandleMenuMsg
,
928 ContextMenu_HandleMenuMsg2
931 static HRESULT WINAPI
ShellExtInit_QueryInterface(IShellExtInit
*iface
, REFIID riid
, void **obj
)
933 ContextMenu
*This
= impl_from_IShellExtInit(iface
);
934 return IContextMenu3_QueryInterface(&This
->IContextMenu3_iface
, riid
, obj
);
937 static ULONG WINAPI
ShellExtInit_AddRef(IShellExtInit
*iface
)
939 ContextMenu
*This
= impl_from_IShellExtInit(iface
);
940 return IContextMenu3_AddRef(&This
->IContextMenu3_iface
);
943 static ULONG WINAPI
ShellExtInit_Release(IShellExtInit
*iface
)
945 ContextMenu
*This
= impl_from_IShellExtInit(iface
);
946 return IContextMenu3_Release(&This
->IContextMenu3_iface
);
949 static HRESULT WINAPI
ShellExtInit_Initialize(IShellExtInit
*iface
, LPCITEMIDLIST folder
,
950 IDataObject
*dataobj
, HKEY progidkey
)
952 ContextMenu
*This
= impl_from_IShellExtInit(iface
);
954 FIXME("(%p)->(%p %p %p): stub\n", This
, folder
, dataobj
, progidkey
);
959 static const IShellExtInitVtbl ShellExtInitVtbl
=
961 ShellExtInit_QueryInterface
,
963 ShellExtInit_Release
,
964 ShellExtInit_Initialize
967 static HRESULT WINAPI
ObjectWithSite_QueryInterface(IObjectWithSite
*iface
, REFIID riid
, void **obj
)
969 ContextMenu
*This
= impl_from_IObjectWithSite(iface
);
970 return IContextMenu3_QueryInterface(&This
->IContextMenu3_iface
, riid
, obj
);
973 static ULONG WINAPI
ObjectWithSite_AddRef(IObjectWithSite
*iface
)
975 ContextMenu
*This
= impl_from_IObjectWithSite(iface
);
976 return IContextMenu3_AddRef(&This
->IContextMenu3_iface
);
979 static ULONG WINAPI
ObjectWithSite_Release(IObjectWithSite
*iface
)
981 ContextMenu
*This
= impl_from_IObjectWithSite(iface
);
982 return IContextMenu3_Release(&This
->IContextMenu3_iface
);
985 static HRESULT WINAPI
ObjectWithSite_SetSite(IObjectWithSite
*iface
, IUnknown
*site
)
987 ContextMenu
*This
= impl_from_IObjectWithSite(iface
);
989 FIXME("(%p)->(%p): stub\n", This
, site
);
994 static HRESULT WINAPI
ObjectWithSite_GetSite(IObjectWithSite
*iface
, REFIID riid
, void **site
)
996 ContextMenu
*This
= impl_from_IObjectWithSite(iface
);
998 FIXME("(%p)->(%s %p): stub\n", This
, debugstr_guid(riid
), site
);
1003 static const IObjectWithSiteVtbl ObjectWithSiteVtbl
=
1005 ObjectWithSite_QueryInterface
,
1006 ObjectWithSite_AddRef
,
1007 ObjectWithSite_Release
,
1008 ObjectWithSite_SetSite
,
1009 ObjectWithSite_GetSite
,
1012 HRESULT
ItemMenu_Constructor(IShellFolder
*parent
, LPCITEMIDLIST pidl
, const LPCITEMIDLIST
*apidl
, UINT cidl
,
1013 REFIID riid
, void **pObj
)
1019 This
= heap_alloc(sizeof(*This
));
1020 if (!This
) return E_OUTOFMEMORY
;
1022 This
->IContextMenu3_iface
.lpVtbl
= &ItemContextMenuVtbl
;
1023 This
->IShellExtInit_iface
.lpVtbl
= &ShellExtInitVtbl
;
1024 This
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1026 This
->parent
= parent
;
1027 if (parent
) IShellFolder_AddRef(parent
);
1029 This
->pidl
= ILClone(pidl
);
1030 This
->apidl
= _ILCopyaPidl(apidl
, cidl
);
1032 This
->allvalues
= TRUE
;
1034 This
->desktop
= FALSE
;
1036 for (i
= 0; i
< cidl
; i
++)
1037 This
->allvalues
&= (_ILIsValue(apidl
[i
]) ? 1 : 0);
1039 hr
= IContextMenu3_QueryInterface(&This
->IContextMenu3_iface
, riid
, pObj
);
1040 IContextMenu3_Release(&This
->IContextMenu3_iface
);
1045 /* Background menu implementation */
1046 static HRESULT WINAPI
BackgroundMenu_QueryContextMenu(
1047 IContextMenu3
*iface
,
1054 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
1059 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
1060 This
, hMenu
, indexMenu
, idCmdFirst
, idCmdLast
, uFlags
);
1062 hMyMenu
= LoadMenuA(shell32_hInstance
, "MENU_002");
1063 if (uFlags
& CMF_DEFAULTONLY
)
1065 HMENU ourMenu
= GetSubMenu(hMyMenu
,0);
1066 UINT oldDef
= GetMenuDefaultItem(hMenu
,TRUE
,GMDI_USEDISABLED
);
1067 UINT newDef
= GetMenuDefaultItem(ourMenu
,TRUE
,GMDI_USEDISABLED
);
1068 if (newDef
!= oldDef
)
1069 SetMenuDefaultItem(hMenu
,newDef
,TRUE
);
1070 if (newDef
!=0xFFFFFFFF)
1071 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, newDef
+1);
1073 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, 0);
1077 Shell_MergeMenus (hMenu
, GetSubMenu(hMyMenu
,0), indexMenu
,
1078 idCmdFirst
- FCIDM_BASE
, idCmdLast
, MM_SUBMENUSHAVEIDS
);
1079 idMax
= max_menu_id(GetSubMenu(hMyMenu
, 0), idCmdFirst
- FCIDM_BASE
, idCmdLast
);
1080 hr
= MAKE_HRESULT(SEVERITY_SUCCESS
, FACILITY_NULL
, idMax
-idCmdFirst
);
1082 DestroyMenu(hMyMenu
);
1084 TRACE("(%p)->returning 0x%lx\n",This
,hr
);
1088 static void DoNewFolder(ContextMenu
*This
, IShellView
*view
)
1092 IShellFolder_QueryInterface(This
->parent
, &IID_ISFHelper
, (void**)&helper
);
1095 WCHAR nameW
[MAX_PATH
];
1098 ISFHelper_GetUniqueName(helper
, nameW
, MAX_PATH
);
1099 ISFHelper_AddFolder(helper
, 0, nameW
, &pidl
);
1103 /* if we are in a shellview do labeledit */
1104 IShellView_SelectItem(view
,
1105 pidl
,(SVSI_DESELECTOTHERS
| SVSI_EDIT
| SVSI_ENSUREVISIBLE
1106 |SVSI_FOCUSED
|SVSI_SELECT
));
1110 ISFHelper_Release(helper
);
1114 static HRESULT
paste_pidls(ContextMenu
*This
, ITEMIDLIST
**pidls
, UINT count
)
1116 IShellFolder
*psfDesktop
;
1120 /* bind to the source shellfolder */
1121 hr
= SHGetDesktopFolder(&psfDesktop
);
1125 for (i
= 0; SUCCEEDED(hr
) && i
< count
; i
++) {
1126 ITEMIDLIST
*pidl_dir
= NULL
;
1127 ITEMIDLIST
*pidl_item
;
1128 IShellFolder
*psfFrom
= NULL
;
1130 pidl_dir
= ILClone(pidls
[i
]);
1131 ILRemoveLastID(pidl_dir
);
1132 pidl_item
= ILFindLastID(pidls
[i
]);
1133 hr
= IShellFolder_BindToObject(psfDesktop
, pidl_dir
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfFrom
);
1137 /* get source and destination shellfolder */
1138 ISFHelper
*psfhlpdst
= NULL
, *psfhlpsrc
= NULL
;
1139 hr
= IShellFolder_QueryInterface(This
->parent
, &IID_ISFHelper
, (void**)&psfhlpdst
);
1141 hr
= IShellFolder_QueryInterface(psfFrom
, &IID_ISFHelper
, (void**)&psfhlpsrc
);
1143 /* do the copy/move */
1144 if (psfhlpdst
&& psfhlpsrc
)
1146 hr
= ISFHelper_CopyItems(psfhlpdst
, psfFrom
, 1, (LPCITEMIDLIST
*)&pidl_item
);
1147 /* FIXME handle move
1148 ISFHelper_DeleteItems(psfhlpsrc, 1, &pidl_item);
1151 if(psfhlpdst
) ISFHelper_Release(psfhlpdst
);
1152 if(psfhlpsrc
) ISFHelper_Release(psfhlpsrc
);
1153 IShellFolder_Release(psfFrom
);
1158 IShellFolder_Release(psfDesktop
);
1162 static HRESULT
DoPaste(ContextMenu
*This
)
1169 hr
= OleGetClipboard(&pda
);
1173 FORMATETC formatetc
;
1176 TRACE("pda=%p\n", pda
);
1178 /* Set the FORMATETC structure*/
1179 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
), TYMED_HGLOBAL
);
1181 /* Get the pidls from IDataObject */
1182 format_hr
= IDataObject_GetData(pda
,&formatetc
,&medium
);
1183 if(SUCCEEDED(format_hr
))
1185 LPITEMIDLIST
* apidl
;
1188 LPIDA lpcida
= GlobalLock(medium
.u
.hGlobal
);
1189 TRACE("cida=%p\n", lpcida
);
1192 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1195 hr
= paste_pidls(This
, apidl
, lpcida
->cidl
);
1196 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1200 hr
= HRESULT_FROM_WIN32(GetLastError());
1201 GlobalUnlock(medium
.u
.hGlobal
);
1204 hr
= HRESULT_FROM_WIN32(GetLastError());
1205 ReleaseStgMedium(&medium
);
1208 if(FAILED(format_hr
))
1210 InitFormatEtc(formatetc
, CF_HDROP
, TYMED_HGLOBAL
);
1211 format_hr
= IDataObject_GetData(pda
,&formatetc
,&medium
);
1212 if(SUCCEEDED(format_hr
))
1214 WCHAR path
[MAX_PATH
];
1218 TRACE("CF_HDROP=%p\n", medium
.u
.hGlobal
);
1219 count
= DragQueryFileW(medium
.u
.hGlobal
, -1, NULL
, 0);
1220 pidls
= SHAlloc(count
*sizeof(ITEMIDLIST
*));
1223 for (i
= 0; i
< count
; i
++)
1225 DragQueryFileW(medium
.u
.hGlobal
, i
, path
, ARRAY_SIZE(path
));
1226 if ((pidls
[i
] = ILCreateFromPathW(path
)) == NULL
)
1233 hr
= paste_pidls(This
, pidls
, count
);
1234 _ILFreeaPidl(pidls
, count
);
1237 hr
= HRESULT_FROM_WIN32(GetLastError());
1238 ReleaseStgMedium(&medium
);
1242 if (FAILED(format_hr
))
1244 ERR("there are no supported and retrievable clipboard formats\n");
1248 IDataObject_Release(pda
);
1253 OpenClipboard(NULL
);
1254 hMem
= GetClipboardData(CF_HDROP
);
1258 char * pDropFiles
= GlobalLock(hMem
);
1261 int len
, offset
= sizeof(DROPFILESTRUCT
);
1263 while( pDropFiles
[offset
] != 0)
1265 len
= strlen(pDropFiles
+ offset
);
1266 TRACE("%s\n", pDropFiles
+ offset
);
1277 static HRESULT WINAPI
BackgroundMenu_InvokeCommand(
1278 IContextMenu3
*iface
,
1279 LPCMINVOKECOMMANDINFO lpcmi
)
1281 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
1282 IShellBrowser
*browser
;
1283 IShellView
*view
= NULL
;
1286 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", This
, lpcmi
, lpcmi
->lpVerb
, lpcmi
->hwnd
);
1288 /* get the active IShellView */
1289 if ((browser
= (IShellBrowser
*)SendMessageA(lpcmi
->hwnd
, CWM_GETISHELLBROWSER
, 0, 0)))
1291 if (SUCCEEDED(IShellBrowser_QueryActiveShellView(browser
, &view
)))
1292 IShellView_GetWindow(view
, &hWnd
);
1295 if(HIWORD(lpcmi
->lpVerb
))
1297 TRACE("%s\n", debugstr_a(lpcmi
->lpVerb
));
1299 if (!strcmp(lpcmi
->lpVerb
, CMDSTR_NEWFOLDERA
))
1301 DoNewFolder(This
, view
);
1303 else if (!strcmp(lpcmi
->lpVerb
, CMDSTR_VIEWLISTA
))
1305 if (hWnd
) SendMessageA(hWnd
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_LISTVIEW
, 0), 0);
1307 else if (!strcmp(lpcmi
->lpVerb
, CMDSTR_VIEWDETAILSA
))
1309 if (hWnd
) SendMessageA(hWnd
, WM_COMMAND
, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW
, 0), 0);
1311 else if (!strcmp(lpcmi
->lpVerb
, "paste"))
1317 FIXME("please report: unknown verb %s\n", debugstr_a(lpcmi
->lpVerb
));
1322 switch (LOWORD(lpcmi
->lpVerb
) + FCIDM_BASE
)
1324 case FCIDM_SHVIEW_REFRESH
:
1325 if (view
) IShellView_Refresh(view
);
1328 case FCIDM_SHVIEW_NEWFOLDER
:
1329 DoNewFolder(This
, view
);
1332 case FCIDM_SHVIEW_INSERT
:
1336 case FCIDM_SHVIEW_PROPERTIES
:
1337 if (This
->desktop
) {
1338 ShellExecuteA(lpcmi
->hwnd
, "open", "rundll32.exe shell32.dll,Control_RunDLL desk.cpl", NULL
, NULL
, SW_SHOWNORMAL
);
1340 FIXME("launch item properties dialog\n");
1345 /* if it's an id just pass it to the parent shv */
1346 if (hWnd
) SendMessageA(hWnd
, WM_COMMAND
, MAKEWPARAM(LOWORD(lpcmi
->lpVerb
), 0), 0);
1352 IShellView_Release(view
);
1357 static HRESULT WINAPI
BackgroundMenu_GetCommandString(
1358 IContextMenu3
*iface
,
1365 ContextMenu
*This
= impl_from_IContextMenu3(iface
);
1366 const WCHAR
*cmdW
= NULL
;
1367 HRESULT hr
= E_FAIL
;
1369 TRACE("(%p)->(idcom=%Ix flags=%x %p name=%p len=%x)\n",This
, idCommand
, uFlags
, lpReserved
, lpszName
, uMaxNameLen
);
1380 switch (idCommand
+ FCIDM_BASE
)
1382 case FCIDM_SHVIEW_INSERT
:
1385 case FCIDM_SHVIEW_PROPERTIES
:
1386 cmdW
= L
"properties";
1396 if (uFlags
== GCS_VERBA
)
1397 WideCharToMultiByte(CP_ACP
, 0, cmdW
, -1, lpszName
, uMaxNameLen
, NULL
, NULL
);
1399 lstrcpynW((WCHAR
*)lpszName
, cmdW
, uMaxNameLen
);
1400 TRACE("name %s\n", uFlags
== GCS_VERBA
? debugstr_a(lpszName
) : debugstr_w((WCHAR
*)lpszName
));
1406 /* test the existence of the menu items, the file dialog enables
1407 the buttons according to this */
1408 if (HIWORD(idCommand
))
1410 if (!strcmp((LPSTR
)idCommand
, CMDSTR_VIEWLISTA
) ||
1411 !strcmp((LPSTR
)idCommand
, CMDSTR_VIEWDETAILSA
) ||
1412 !strcmp((LPSTR
)idCommand
, CMDSTR_NEWFOLDERA
))
1416 FIXME("unknown command string %s\n", uFlags
== GCS_VALIDATEA
? debugstr_a((LPSTR
)idCommand
) : debugstr_w((WCHAR
*)idCommand
));
1425 static const IContextMenu3Vtbl BackgroundContextMenuVtbl
=
1427 ContextMenu_QueryInterface
,
1429 ContextMenu_Release
,
1430 BackgroundMenu_QueryContextMenu
,
1431 BackgroundMenu_InvokeCommand
,
1432 BackgroundMenu_GetCommandString
,
1433 ContextMenu_HandleMenuMsg
,
1434 ContextMenu_HandleMenuMsg2
1437 HRESULT
BackgroundMenu_Constructor(IShellFolder
*parent
, BOOL desktop
, REFIID riid
, void **pObj
)
1442 This
= heap_alloc(sizeof(*This
));
1443 if (!This
) return E_OUTOFMEMORY
;
1445 This
->IContextMenu3_iface
.lpVtbl
= &BackgroundContextMenuVtbl
;
1446 This
->IShellExtInit_iface
.lpVtbl
= &ShellExtInitVtbl
;
1447 This
->IObjectWithSite_iface
.lpVtbl
= &ObjectWithSiteVtbl
;
1449 This
->parent
= parent
;
1454 This
->allvalues
= FALSE
;
1456 This
->desktop
= desktop
;
1457 if (parent
) IShellFolder_AddRef(parent
);
1459 hr
= IContextMenu3_QueryInterface(&This
->IContextMenu3_iface
, riid
, pObj
);
1460 IContextMenu3_Release(&This
->IContextMenu3_iface
);