From 79253e6534b61fe4ff59731667163ccbed7b5534 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 16 Aug 2015 23:19:29 +0200 Subject: [PATCH] Added patch to implement shell32 NewMenu class with new folder item. --- README.md | 3 +- debian/changelog | 1 + patches/patchinstall.sh | 20 + ...plement-NewMenu-with-new-folder-item.patch | 647 ++++++++++++++++++ patches/shell32-NewMenu_Interface/definition | 1 + 5 files changed, 671 insertions(+), 1 deletion(-) create mode 100644 patches/shell32-NewMenu_Interface/0001-shell32-Implement-NewMenu-with-new-folder-item.patch create mode 100644 patches/shell32-NewMenu_Interface/definition diff --git a/README.md b/README.md index 011f611e..ba229770 100644 --- a/README.md +++ b/README.md @@ -39,12 +39,13 @@ Wine. All those differences are also documented on the Included bug fixes and improvements ----------------------------------- -**Bug fixes and features included in the next upcoming release [9]:** +**Bug fixes and features included in the next upcoming release [10]:** * Add IDragSourceHelper stub interface ([Wine Bug #24699](https://bugs.winehq.org/show_bug.cgi?id=24699)) * Catch invalid memory accesses in imagehlp.CheckSumMappedFile * Fix implementation of ntdll.MapViewOfSection * Implement enumeration of sound devices and basic properties to dxdiagn ([Wine Bug #32613](https://bugs.winehq.org/show_bug.cgi?id=32613)) +* Implement shell32 NewMenu class with new folder item ([Wine Bug #24812](https://bugs.winehq.org/show_bug.cgi?id=24812)) * Implement special handling for calling GetChildContainer with an empty string ([Wine Bug #38014](https://bugs.winehq.org/show_bug.cgi?id=38014)) * Implement vcomp locking functions ([Wine Bug #26688](https://bugs.winehq.org/show_bug.cgi?id=26688)) * Improve startup performance by delaying font initialization diff --git a/debian/changelog b/debian/changelog index db277b9e..98c00d69 100644 --- a/debian/changelog +++ b/debian/changelog @@ -11,6 +11,7 @@ wine-staging (1.7.50) UNRELEASED; urgency=low (fixes Wine Staging Bug #401). * Added patch to set SFGAO_HASSUBFOLDER only when there are really subfolders. * Added patch to fix multiple uninitialized memory issues in wineserver. + * Added patch to implement shell32 NewMenu class with new folder item. * Removed patch to move security cookie initialization from memory management to loader. -- Sebastian Lackner Tue, 11 Aug 2015 06:12:14 +0200 diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 251ef264..5002d8b3 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -229,6 +229,7 @@ patch_enable_all () enable_shell32_File_Property_Dialog="$1" enable_shell32_IDragSourceHelper="$1" enable_shell32_Icons="$1" + enable_shell32_NewMenu_Interface="$1" enable_shell32_Placeholder_Icons="$1" enable_shell32_Progress_Dialog="$1" enable_shell32_RunDLL_CallEntry16="$1" @@ -777,6 +778,9 @@ patch_enable () shell32-Icons) enable_shell32_Icons="$2" ;; + shell32-NewMenu_Interface) + enable_shell32_NewMenu_Interface="$2" + ;; shell32-Placeholder_Icons) enable_shell32_Placeholder_Icons="$2" ;; @@ -4721,6 +4725,22 @@ if test "$enable_shell32_Icons" -eq 1; then ) >> "$patchlist" fi +# Patchset shell32-NewMenu_Interface +# | +# | This patchset fixes the following Wine bugs: +# | * [#24812] Implement shell32 NewMenu class with new folder item +# | +# | Modified files: +# | * dlls/shell32/Makefile.in, dlls/shell32/shell32_classes.idl, dlls/shell32/shell32_main.h, dlls/shell32/shellnew.c, +# | dlls/shell32/shellole.c, include/shlguid.h +# | +if test "$enable_shell32_NewMenu_Interface" -eq 1; then + patch_apply shell32-NewMenu_Interface/0001-shell32-Implement-NewMenu-with-new-folder-item.patch + ( + echo '+ { "Michael Müller", "shell32: Implement NewMenu with new folder item.", 1 },'; + ) >> "$patchlist" +fi + # Patchset shell32-Placeholder_Icons # | # | This patchset fixes the following Wine bugs: diff --git a/patches/shell32-NewMenu_Interface/0001-shell32-Implement-NewMenu-with-new-folder-item.patch b/patches/shell32-NewMenu_Interface/0001-shell32-Implement-NewMenu-with-new-folder-item.patch new file mode 100644 index 00000000..a3481918 --- /dev/null +++ b/patches/shell32-NewMenu_Interface/0001-shell32-Implement-NewMenu-with-new-folder-item.patch @@ -0,0 +1,647 @@ +From 0e08c56df7f0d6beefbf6726f9db0b5ad3541348 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michael=20M=C3=BCller?= +Date: Sun, 16 Aug 2015 17:34:22 +0200 +Subject: shell32: Implement NewMenu with new folder item. + +--- + dlls/shell32/Makefile.in | 1 + + dlls/shell32/shell32_classes.idl | 5 + + dlls/shell32/shell32_main.h | 1 + + dlls/shell32/shellnew.c | 558 +++++++++++++++++++++++++++++++++++++++ + dlls/shell32/shellole.c | 1 + + include/shlguid.h | 2 + + 6 files changed, 568 insertions(+) + create mode 100644 dlls/shell32/shellnew.c + +diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in +index 038db7f..7b677ff 100644 +--- a/dlls/shell32/Makefile.in ++++ b/dlls/shell32/Makefile.in +@@ -32,6 +32,7 @@ C_SRCS = \ + shelldispatch.c \ + shellitem.c \ + shelllink.c \ ++ shellnew.c \ + shellole.c \ + shellord.c \ + shellpath.c \ +diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl +index f0131e7..0140fec 100644 +--- a/dlls/shell32/shell32_classes.idl ++++ b/dlls/shell32/shell32_classes.idl +@@ -76,6 +76,11 @@ coclass KnownFolderManager { interface IKnownFolderManager; } + + [ + threading(apartment), ++ uuid(d969a300-e7ff-11d0-a93b-00a0c90f2719) ++] coclass NewMenu { interface IShellExtInit; } ++ ++[ ++ threading(apartment), + uuid(00bb2763-6a77-11d0-a535-00c04fd7d062) + ] coclass AutoComplete { interface IAutoComplete2; } + +diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h +index 492f79f..83c5655 100644 +--- a/dlls/shell32/shell32_main.h ++++ b/dlls/shell32/shell32_main.h +@@ -98,6 +98,7 @@ HRESULT WINAPI RecycleBin_Constructor(IUnknown * pUnkOuter, REFIID riif, LPVOID + HRESULT WINAPI QueryAssociations_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppOutput) DECLSPEC_HIDDEN; + HRESULT WINAPI ExplorerBrowser_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; + HRESULT WINAPI KnownFolderManager_Constructor(IUnknown *pUnkOuter, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; ++HRESULT WINAPI NewMenu_Constructor(IUnknown *outer, REFIID riid, LPVOID *ppv) DECLSPEC_HIDDEN; + extern HRESULT CPanel_GetIconLocationW(LPCITEMIDLIST, LPWSTR, UINT, int*) DECLSPEC_HIDDEN; + HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN; + HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN; +diff --git a/dlls/shell32/shellnew.c b/dlls/shell32/shellnew.c +new file mode 100644 +index 0000000..59e18d6 +--- /dev/null ++++ b/dlls/shell32/shellnew.c +@@ -0,0 +1,558 @@ ++/* ++ * Copyright 2015 Michael Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ */ ++ ++#define COBJMACROS ++#define NONAMELESSUNION ++ ++#include "wine/debug.h" ++#include "winerror.h" ++#include "windef.h" ++#include "winbase.h" ++#include "winnls.h" ++#include "winreg.h" ++ ++#include "winuser.h" ++#include "wingdi.h" ++#include "shlobj.h" ++#include "undocshell.h" ++ ++#include "pidl.h" ++#include "shell32_main.h" ++#include "shlguid.h" ++#include "shlwapi.h" ++#include "shresdef.h" ++#include "shellfolder.h" ++ ++WINE_DEFAULT_DEBUG_CHANNEL(shell); ++ ++typedef struct ++{ ++ IShellExtInit IShellExtInit_iface; ++ IContextMenu IContextMenu_iface; ++ IContextMenu3 IContextMenu3_iface; ++ IObjectWithSite IObjectWithSite_iface; ++ ++ LONG ref; ++ IUnknown *site; ++ LPITEMIDLIST pidl; ++ HICON icon_folder; ++ ++ UINT folder_cmd; ++} NewMenuImpl; ++ ++static inline NewMenuImpl *impl_from_IShellExtInit(IShellExtInit *iface) ++{ ++ return CONTAINING_RECORD(iface, NewMenuImpl, IShellExtInit_iface); ++} ++ ++static inline NewMenuImpl *impl_from_IContextMenu(IContextMenu *iface) ++{ ++ return CONTAINING_RECORD(iface, NewMenuImpl, IContextMenu_iface); ++} ++ ++static inline NewMenuImpl *impl_from_IContextMenu3(IContextMenu3 *iface) ++{ ++ return CONTAINING_RECORD(iface, NewMenuImpl, IContextMenu3_iface); ++} ++ ++static inline NewMenuImpl *impl_from_IObjectWithSite(IObjectWithSite *iface) ++{ ++ return CONTAINING_RECORD(iface, NewMenuImpl, IObjectWithSite_iface); ++} ++ ++static HRESULT WINAPI ++NewMenu_ExtInit_QueryInterface(IShellExtInit *iface, REFIID riid, void **ppv) ++{ ++ NewMenuImpl *This = impl_from_IShellExtInit(iface); ++ TRACE("(%p)->(%s)\n", This, debugstr_guid(riid)); ++ ++ *ppv = NULL; ++ ++ if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IShellExtInit)) ++ { ++ *ppv = &This->IShellExtInit_iface; ++ } ++ else if (IsEqualIID(riid, &IID_IObjectWithSite)) ++ { ++ *ppv = &This->IObjectWithSite_iface; ++ } ++ else if (IsEqualIID(riid, &IID_IContextMenu)) ++ { ++ *ppv = &This->IContextMenu_iface; ++ } ++ else if (IsEqualIID(riid, &IID_IContextMenu3)) ++ { ++ *ppv = &This->IContextMenu3_iface; ++ } ++ ++ if (*ppv) ++ { ++ IUnknown_AddRef((IUnknown *)*ppv); ++ TRACE("-- Interface: (%p)->(%p)\n", ppv, *ppv); ++ return S_OK; ++ } ++ ++ ERR("-- Interface: E_NOINTERFACE for %s\n", debugstr_guid(riid)); ++ return E_NOINTERFACE; ++} ++ ++static ULONG WINAPI ++NewMenu_ExtInit_AddRef(IShellExtInit *iface) ++{ ++ NewMenuImpl *This = impl_from_IShellExtInit(iface); ++ ULONG ref = InterlockedIncrement(&This->ref); ++ ++ TRACE("(%p), new refcount=%i\n", iface, ref); ++ ++ return ref; ++} ++ ++static ULONG WINAPI ++NewMenu_ExtInit_Release(IShellExtInit *iface) ++{ ++ NewMenuImpl *This = impl_from_IShellExtInit(iface); ++ ULONG ref = InterlockedDecrement(&This->ref); ++ ++ TRACE("(%p), new refcount=%i\n", iface, ref); ++ ++ if (!ref) ++ { ++ if (This->site) IUnknown_Release(This->site); ++ if (This->pidl) ILFree(This->pidl); ++ HeapFree(GetProcessHeap(), 0, This); ++ } ++ ++ return ref; ++} ++ ++static HRESULT WINAPI ++NewMenu_ExtInit_Initialize(IShellExtInit *iface, LPCITEMIDLIST pidl, IDataObject *obj, HKEY key) ++{ ++ NewMenuImpl *This = impl_from_IShellExtInit(iface); ++ ++ TRACE("(%p)->(%p, %p, %p)\n", This, pidl, obj, key ); ++ ++ if (!pidl) ++ return E_FAIL; ++ ++ if (This->pidl) ILFree(This->pidl); ++ This->pidl = ILClone(pidl); ++ This->icon_folder = LoadImageW(shell32_hInstance, (LPCWSTR)MAKEINTRESOURCE(IDI_SHELL_FOLDER), IMAGE_ICON, ++ GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED); ++ ++ return S_OK; ++} ++ ++static const IShellExtInitVtbl eivt = ++{ ++ NewMenu_ExtInit_QueryInterface, ++ NewMenu_ExtInit_AddRef, ++ NewMenu_ExtInit_Release, ++ NewMenu_ExtInit_Initialize ++}; ++ ++ ++static HRESULT WINAPI ++NewMenu_ObjectWithSite_QueryInterface(IObjectWithSite *iface, REFIID riid, void **ppv) ++{ ++ NewMenuImpl *This = impl_from_IObjectWithSite(iface); ++ return NewMenu_ExtInit_QueryInterface(&This->IShellExtInit_iface, riid, ppv); ++} ++ ++static ULONG WINAPI ++NewMenu_ObjectWithSite_AddRef(IObjectWithSite *iface) ++{ ++ NewMenuImpl *This = impl_from_IObjectWithSite(iface); ++ return NewMenu_ExtInit_AddRef(&This->IShellExtInit_iface); ++} ++ ++static ULONG WINAPI ++NewMenu_ObjectWithSite_Release(IObjectWithSite *iface) ++{ ++ NewMenuImpl *This = impl_from_IObjectWithSite(iface); ++ return NewMenu_ExtInit_Release(&This->IShellExtInit_iface); ++} ++ ++static HRESULT WINAPI ++NewMenu_ObjectWithSite_GetSite(IObjectWithSite *iface, REFIID iid, void **ppv) ++{ ++ NewMenuImpl *This = impl_from_IObjectWithSite(iface); ++ ++ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv); ++ ++ if (!This->site) ++ return E_FAIL; ++ ++ return IUnknown_QueryInterface(This->site, iid, ppv); ++} ++ ++static HRESULT WINAPI ++NewMenu_ObjectWithSite_SetSite(IObjectWithSite *iface, IUnknown *punk) ++{ ++ NewMenuImpl *This = impl_from_IObjectWithSite(iface); ++ ++ TRACE("(%p)->(%p)\n", This, punk); ++ ++ if (punk) ++ IUnknown_AddRef(punk); ++ ++ if (This->site) ++ IUnknown_Release(This->site); ++ ++ This->site = punk; ++ return S_OK; ++} ++ ++static const IObjectWithSiteVtbl owsvt = ++{ ++ NewMenu_ObjectWithSite_QueryInterface, ++ NewMenu_ObjectWithSite_AddRef, ++ NewMenu_ObjectWithSite_Release, ++ NewMenu_ObjectWithSite_SetSite, ++ NewMenu_ObjectWithSite_GetSite, ++}; ++ ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_QueryInterface(IContextMenu3 *iface, REFIID riid, void **ppv) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ return NewMenu_ExtInit_QueryInterface(&This->IShellExtInit_iface, riid, ppv); ++} ++ ++static ULONG WINAPI ++NewMenu_ContextMenu3_AddRef(IContextMenu3 *iface) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ return NewMenu_ExtInit_AddRef(&This->IShellExtInit_iface); ++} ++ ++static ULONG WINAPI ++NewMenu_ContextMenu3_Release(IContextMenu3 *iface) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ return NewMenu_ExtInit_Release(&This->IShellExtInit_iface); ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_GetCommandString(IContextMenu3 *iface, UINT_PTR cmd, UINT type, ++ UINT *reserved, LPSTR name, UINT max_len) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ ++ FIXME("(%p)->(%lu %u %p %p %u): stub\n", This, cmd, type, reserved, name, max_len); ++ ++ return E_NOTIMPL; ++} ++ ++static HRESULT create_folder(NewMenuImpl *This, IShellView *view) ++{ ++ IFolderView *folder_view = NULL; ++ IShellFolder *desktop = NULL; ++ IShellFolder *parent = NULL; ++ ISFHelper *helper = NULL; ++ LPITEMIDLIST pidl = NULL; ++ WCHAR nameW[MAX_PATH]; ++ HRESULT hr; ++ ++ if (view) ++ { ++ hr = IShellView_QueryInterface(view, &IID_IFolderView, (void **)&folder_view); ++ if (FAILED(hr)) return hr; ++ ++ hr = IFolderView_GetFolder(folder_view, &IID_IShellFolder, (void **)&parent); ++ if (FAILED(hr)) goto out; ++ } ++ else ++ { ++ hr = SHGetDesktopFolder(&desktop); ++ if (FAILED(hr)) goto out; ++ ++ hr = IShellFolder_BindToObject(desktop, This->pidl, NULL, &IID_IShellFolder, (void **)&parent); ++ if (FAILED(hr)) goto out; ++ } ++ ++ IShellFolder_QueryInterface(parent, &IID_ISFHelper, (void **)&helper); ++ if (FAILED(hr)) goto out; ++ ++ hr = ISFHelper_GetUniqueName(helper, nameW, MAX_PATH); ++ if (FAILED(hr)) goto out; ++ ++ hr = ISFHelper_AddFolder(helper, 0, nameW, &pidl); ++ if (FAILED(hr)) goto out; ++ ++ if (view) ++ { ++ IShellView_SelectItem(view, pidl, SVSI_DESELECTOTHERS | SVSI_EDIT | ++ SVSI_ENSUREVISIBLE | SVSI_FOCUSED | SVSI_SELECT); ++ } ++ ++out: ++ if (pidl) SHFree(pidl); ++ if (helper) ISFHelper_Release(helper); ++ if (parent) IShellFolder_Release(parent); ++ if (desktop) IShellFolder_Release(desktop); ++ if (folder_view) IFolderView_Release(folder_view); ++ return hr; ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_InvokeCommand(IContextMenu3 *iface, LPCMINVOKECOMMANDINFO info) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ IShellBrowser *browser; ++ IShellView *view = NULL; ++ HRESULT hr = E_FAIL; ++ ++ TRACE("(%p)->(%p)\n", This, info); ++ ++ /* New Folder */ ++ if (info->lpVerb == 0) ++ { ++ if ((browser = (IShellBrowser *)SendMessageA(info->hwnd, CWM_GETISHELLBROWSER, 0, 0))) ++ { ++ if (FAILED(IShellBrowser_QueryActiveShellView(browser, &view))) ++ view = NULL; ++ } ++ hr = create_folder(This, view); ++ if (view) IShellView_Release(view); ++ } ++ ++ return hr; ++} ++ ++static UINT insert_new_menu_items(NewMenuImpl *This, HMENU menu, UINT pos, UINT cmd_first, UINT cmd_last) ++{ ++ MENUITEMINFOW item; ++ WCHAR buffer[256]; ++ ++ memset(&item, 0, sizeof(item)); ++ item.cbSize = sizeof(item); ++ ++ if (cmd_first > cmd_last) ++ return cmd_first; ++ ++ /* FIXME: on windows it is only 'Folder' not 'New Folder' */ ++ if (!LoadStringW(shell32_hInstance, IDS_NEWFOLDER, buffer, sizeof(buffer) / sizeof(WCHAR))) ++ buffer[0] = 0; ++ ++ item.fMask = MIIM_ID | MIIM_BITMAP | MIIM_STRING; ++ item.dwTypeData = buffer; ++ item.cch = strlenW(buffer); ++ item.wID = cmd_first; ++ item.hbmpItem = HBMMENU_CALLBACK; ++ if (InsertMenuItemW(menu, pos, TRUE, &item)) ++ { ++ This->folder_cmd = cmd_first++; ++ pos++; ++ } ++ ++ return cmd_first; ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_QueryContextMenu(IContextMenu3 *iface, HMENU menu, UINT index, ++ UINT cmd_first, UINT cmd_last, UINT flags) ++{ ++ static WCHAR newW[] = {'N','e','w',0}; ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ MENUITEMINFOW item; ++ HMENU submenu; ++ UINT id; ++ ++ TRACE("(%p)->(%p, %u, %u, %u, %u)\n", This, ++ menu, index, cmd_first, cmd_last, flags ); ++ ++ if (!This->pidl) ++ return E_FAIL; ++ ++ submenu = CreateMenu(); ++ if (!submenu) return E_FAIL; ++ ++ id = insert_new_menu_items(This, submenu, 0, cmd_first, cmd_last); ++ ++ memset(&item, 0, sizeof(item)); ++ item.cbSize = sizeof(item); ++ item.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE | MIIM_SUBMENU; ++ item.fType = MFT_STRING; ++ item.wID = -1; ++ item.dwTypeData = newW; /* FIXME: load from resource file */ ++ item.cch = strlenW(newW); ++ item.fState = MFS_ENABLED; ++ item.hSubMenu = submenu; ++ ++ if (!InsertMenuItemW(menu, index, TRUE, &item)) ++ return E_FAIL; ++ ++ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id); ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_HandleMenuMsg2(IContextMenu3 *iface, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *result) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu3(iface); ++ ++ TRACE("(%p)->(%u, %lx, %lx, %p)\n", This, uMsg, wParam, lParam, result); ++ ++ switch (uMsg) ++ { ++ case WM_MEASUREITEM: ++ { ++ MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *)lParam; ++ if (!mis || mis->CtlType != ODT_MENU) ++ break; ++ ++ if (This->folder_cmd == mis->itemID) ++ { ++ mis->itemWidth = GetSystemMetrics(SM_CXSMICON); ++ mis->itemHeight = GetSystemMetrics(SM_CYSMICON); ++ } ++ ++ if (result) *result = TRUE; ++ break; ++ } ++ ++ case WM_DRAWITEM: ++ { ++ DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam; ++ HICON icon = 0; ++ UINT x, y; ++ ++ if (!dis || dis->CtlType != ODT_MENU) ++ break; ++ ++ if (This->folder_cmd == dis->itemID) ++ icon = This->icon_folder; ++ ++ if (!icon) ++ break; ++ ++ x = (dis->rcItem.right - dis->rcItem.left - GetSystemMetrics(SM_CXSMICON)) / 2; ++ y = (dis->rcItem.bottom - dis->rcItem.top - GetSystemMetrics(SM_CYSMICON)) / 2; ++ DrawStateW(dis->hDC, NULL, NULL, (LPARAM)icon, 0, x, y, 0, 0, DST_ICON | DSS_NORMAL); ++ ++ if (result) *result = TRUE; ++ break; ++ } ++ } ++ ++ return S_OK; ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu3_HandleMenuMsg(IContextMenu3 *iface, UINT uMsg, WPARAM wParam, LPARAM lParam) ++{ ++ return NewMenu_ContextMenu3_HandleMenuMsg2(iface, uMsg, wParam, lParam, NULL); ++} ++ ++static const IContextMenu3Vtbl cmvt3 = ++{ ++ NewMenu_ContextMenu3_QueryInterface, ++ NewMenu_ContextMenu3_AddRef, ++ NewMenu_ContextMenu3_Release, ++ NewMenu_ContextMenu3_QueryContextMenu, ++ NewMenu_ContextMenu3_InvokeCommand, ++ NewMenu_ContextMenu3_GetCommandString, ++ NewMenu_ContextMenu3_HandleMenuMsg, ++ NewMenu_ContextMenu3_HandleMenuMsg2 ++}; ++ ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu_QueryInterface(IContextMenu *iface, REFIID riid, void **ppv) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ExtInit_QueryInterface(&This->IShellExtInit_iface, riid, ppv); ++} ++ ++static ULONG WINAPI ++NewMenu_ContextMenu_AddRef(IContextMenu *iface) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ExtInit_AddRef(&This->IShellExtInit_iface); ++} ++ ++static ULONG WINAPI ++NewMenu_ContextMenu_Release(IContextMenu *iface) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ExtInit_Release(&This->IShellExtInit_iface); ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu_QueryContextMenu(IContextMenu *iface, HMENU menu, UINT index, ++ UINT cmd_first, UINT cmd_last, UINT flags) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ContextMenu3_QueryContextMenu(&This->IContextMenu3_iface, menu, index, ++ cmd_first, cmd_last, flags); ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu_InvokeCommand(IContextMenu *iface, LPCMINVOKECOMMANDINFO info) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ContextMenu3_InvokeCommand(&This->IContextMenu3_iface, info); ++} ++ ++static HRESULT WINAPI ++NewMenu_ContextMenu_GetCommandString(IContextMenu *iface, UINT_PTR cmd, UINT type, ++ UINT *reserved, LPSTR name, UINT max_len) ++{ ++ NewMenuImpl *This = impl_from_IContextMenu(iface); ++ return NewMenu_ContextMenu3_GetCommandString(&This->IContextMenu3_iface, cmd, type, reserved, name, max_len); ++} ++ ++static const IContextMenuVtbl cmvt = ++{ ++ NewMenu_ContextMenu_QueryInterface, ++ NewMenu_ContextMenu_AddRef, ++ NewMenu_ContextMenu_Release, ++ NewMenu_ContextMenu_QueryContextMenu, ++ NewMenu_ContextMenu_InvokeCommand, ++ NewMenu_ContextMenu_GetCommandString ++}; ++ ++ ++HRESULT WINAPI NewMenu_Constructor(IUnknown *outer, REFIID riid, void **obj) ++{ ++ NewMenuImpl *menu; ++ HRESULT hr; ++ ++ TRACE("outer=%p riid=%s\n", outer, debugstr_guid(riid)); ++ ++ *obj = NULL; ++ ++ if (outer) ++ return CLASS_E_NOAGGREGATION; ++ ++ menu = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NewMenuImpl)); ++ if (!menu) return E_OUTOFMEMORY; ++ ++ menu->ref = 1; ++ menu->IShellExtInit_iface.lpVtbl = &eivt; ++ menu->IContextMenu_iface.lpVtbl = &cmvt; ++ menu->IContextMenu3_iface.lpVtbl = &cmvt3; ++ menu->IObjectWithSite_iface.lpVtbl = &owsvt; ++ ++ TRACE("(%p)\n", menu); ++ ++ hr = IShellExtInit_QueryInterface(&menu->IShellExtInit_iface, riid, obj); ++ IShellExtInit_Release(&menu->IShellExtInit_iface); ++ return hr; ++} +diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c +index 637a101..9c1df75 100644 +--- a/dlls/shell32/shellole.c ++++ b/dlls/shell32/shellole.c +@@ -83,6 +83,7 @@ static const struct { + {&CLSID_ExplorerBrowser,ExplorerBrowser_Constructor}, + {&CLSID_KnownFolderManager, KnownFolderManager_Constructor}, + {&CLSID_Shell, IShellDispatch_Constructor}, ++ {&CLSID_NewMenu, NewMenu_Constructor}, + {NULL, NULL} + }; + +diff --git a/include/shlguid.h b/include/shlguid.h +index 2279def..09aacc5 100644 +--- a/include/shlguid.h ++++ b/include/shlguid.h +@@ -146,6 +146,8 @@ DEFINE_GUID(CLSID_ProgressDialog, 0xf8383852, 0xfcd3, 0x11d1, 0xa6, 0xb9, 0x0, 0 + + DEFINE_GUID(CLSID_ShellItem, 0x2fe352ea, 0xfd1f, 0x11d2, 0xb1, 0xf4, 0x00, 0xc0, 0x4f, 0x8e, 0xeb, 0x3e); + ++DEFINE_GUID(CLSID_NewMenu, 0xd969a300, 0xe7ff, 0x11d0, 0xa9, 0x3b, 0x0, 0xa0, 0xc9, 0xf, 0x27, 0x19); ++ + #define PSGUID_SHELLDETAILS {0x28636aa6, 0x953d, 0x11d2, 0xb5, 0xd6, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0} + DEFINE_GUID(FMTID_ShellDetails, 0x28636aa6, 0x953d, 0x11d2, 0xb5, 0xd6, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0); + #define PID_FINDDATA 0 +-- +2.5.0 + diff --git a/patches/shell32-NewMenu_Interface/definition b/patches/shell32-NewMenu_Interface/definition new file mode 100644 index 00000000..36964efc --- /dev/null +++ b/patches/shell32-NewMenu_Interface/definition @@ -0,0 +1 @@ +Fixes: [24812] Implement shell32 NewMenu class with new folder item