78565: Subject: [PATCH 2/5] shell32: Use SHCreateDefaultContextMenu to create context menus
buildbot at kegel.com
buildbot at kegel.com
Fri Sep 9 07:53:29 CDT 2011
This is an experimental automated build and test service.
Please feel free to ignore this email while we work the kinks out.
The Buildbot has detected a failed build on builder runtests-default-x86_64 while building Wine.
Full details are available at: http://buildbot.kegel.com/builders/runtests-default-x86_64/builds/1 (though maybe not for long, as I'm still reinstalling the buildbot periodically while experimenting)
BUILD FAILED: failed shell_2
For more info about this message, see http://wiki.winehq.org/BuildBot
-------------- next part --------------
From: Jay Yang <jkelleyy at gmail.com>
Subject: [PATCH 1/5] shell32: Implement loading of context menu shell extensions
Message-Id: <4E68F60B.7050001 at gmail.com>
Date: Thu, 08 Sep 2011 13:06:19 -0400
I can't remember what try number I was on so I've sent these five patches without a try number.
---
dlls/shell32/shell32_main.h | 2 +
dlls/shell32/shfldr.h | 2 -
dlls/shell32/shlmenu.c | 160 ++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 161 insertions(+), 3 deletions(-)
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index 96b3098..e043916 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -204,4 +204,6 @@ HRESULT SHELL_RegisterShellFolders(void) DECLSPEC_HIDDEN;
/* Detect Shell Links */
BOOL SHELL_IsShortcut(LPCITEMIDLIST) DECLSPEC_HIDDEN;
+#define CHARS_IN_GUID 39
+
#endif
diff --git a/dlls/shell32/shfldr.h b/dlls/shell32/shfldr.h
index 052b040..90c84d1 100644
--- a/dlls/shell32/shfldr.h
+++ b/dlls/shell32/shfldr.h
@@ -20,8 +20,6 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#define CHARS_IN_GUID 39
-
typedef struct {
int colnameid;
int pcsFlags;
diff --git a/dlls/shell32/shlmenu.c b/dlls/shell32/shlmenu.c
index 4006807..070b40d 100644
--- a/dlls/shell32/shlmenu.c
+++ b/dlls/shell32/shlmenu.c
@@ -1246,14 +1246,172 @@ static const IContextMenu3Vtbl CompositeCMenuVtbl=
CompositeCMenu_HandleMenuMsg2
};
+static BOOL ShouldEnforceApprovedList(void)
+{
+ static const WCHAR policies_key_name[]={'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','P','o','l','i','c','i','e','s','\\','E','x','p','l','o','r','e','r','\0'};
+ static const WCHAR enforce_value_name[]={'E','n','f','o','r','c','e','S','h','e','l','l','E','x','t','e','n','s','i','o','n','S','e','c','u','r','i','t','y','\0'};
+ DWORD value=0;
+ DWORD length = sizeof(value);
+ RegGetValueW(HKEY_CURRENT_USER,policies_key_name,enforce_value_name,RRF_RT_REG_DWORD,NULL,&value,&length);
+ return value==1;
+}
+
static HRESULT SHELL_CreateContextMenu(HWND hwnd, IContextMenu* system_menu,
IShellFolder *folder, LPCITEMIDLIST folder_pidl,
LPCITEMIDLIST *apidl, UINT cidl, const HKEY *aKeys,
UINT cKeys,REFIID riid, void** ppv)
{
+ static const WCHAR cmenu_handler_key[]={'s','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s','\0'};
+ static const WCHAR approved_key_name[]={'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','S','h','e','l','l',' ','E','x','t','e','n','s','i','o','n','s','\\','A','p','p','r','o','v','e','d','\0'};
HRESULT ret;
+ HKEY approved_key;
+ LPWSTR name=NULL;
+ IContextMenu **menus=NULL;
+ HKEY *new_keys;
+ UINT i;
+ UINT key_count = 0;
+ UINT handler_count=0;
+ UINT real_handler_count=0;
+ UINT max_key_length=0;
+ CLSID *clsid_table;
+ BOOL enforce_approved = ShouldEnforceApprovedList();
TRACE("(%p,%p,%p,%p,%p,%u,%p,%u,%s,%p)\n",hwnd,system_menu,folder,folder_pidl,apidl,cidl,aKeys,cKeys,shdebugstr_guid(riid),ppv);
- ret = CompositeCMenu_Constructor(&system_menu,1,riid,ppv);
+ new_keys = HeapAlloc(GetProcessHeap(),0,sizeof(HKEY)*cKeys);
+ if(!new_keys)
+ return E_OUTOFMEMORY;
+ for(i=0;i<cKeys;i++)
+ {
+ HKEY new_key;
+ if(!RegOpenKeyExW(aKeys[i],cmenu_handler_key,0,KEY_READ,&new_key))
+ {
+ new_keys[i]=new_key;
+ key_count++;
+ }
+ else
+ new_keys[i]=NULL;
+ }
+ /*find out how many handlers there are*/
+ for(i=0;i<cKeys;i++)
+ {
+ UINT subkeys,key_length;
+ if(!new_keys[i])
+ continue;
+ RegQueryInfoKeyW(new_keys[i],NULL,NULL,NULL,&subkeys,&key_length,NULL,NULL,NULL,NULL,NULL,NULL);
+ handler_count+=subkeys;
+ max_key_length = max(key_length,max_key_length);
+ }
+ /*Get the Approved key*/
+ if(enforce_approved)
+ enforce_approved = (ERROR_SUCCESS==RegOpenKeyExW(HKEY_LOCAL_MACHINE,approved_key_name,0,KEY_READ,&approved_key));
+ /*
+ * Use a linear search in a table to check if we've used the CLSID already,
+ * this should be fast enough for any reasonable number of handlers
+ */
+ clsid_table = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CLSID)*handler_count);
+ if(!clsid_table)
+ {
+ ret = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ handler_count++;
+ menus = HeapAlloc(GetProcessHeap(),0,sizeof(IContextMenu*)*handler_count);
+ if(!menus)
+ {
+ ret = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ name = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(max_key_length+1));
+ if(!name)
+ {
+ ret = E_OUTOFMEMORY;
+ goto cleanup;
+ }
+ /*get all the handlers*/
+ for(i=0;i<cKeys;i++)
+ {
+ CLSID id;
+ WCHAR clsid[CHARS_IN_GUID];
+ UINT index=0;
+ UINT length = max_key_length+1;
+ if(!new_keys[i])
+ continue;
+ while(ERROR_NO_MORE_ITEMS!=RegEnumKeyExW(new_keys[i],index,name,&length,
+ NULL,NULL,NULL,NULL))
+ {
+ HRESULT hres;
+ LPWSTR str;
+ BOOL unique=FALSE;
+ UINT j;
+ index++;
+ if(FAILED(CLSIDFromString(name,&id)))
+ {
+ /*try to get a CLSID from the value*/
+ length=sizeof(clsid);
+ if(!RegGetValueW(new_keys[i],name,NULL,RRF_RT_REG_SZ,NULL,clsid,&length))
+ if(FAILED(CLSIDFromString(clsid,&id)))
+ continue;
+ }
+ if(SUCCEEDED(StringFromCLSID(&id,&str)))
+ {
+ /*check the approved key*/
+ if(enforce_approved && RegGetValueW(approved_key,NULL,str,RRF_RT_REG_SZ,NULL,NULL,0))
+ continue;
+ CoTaskMemFree(str);
+ }
+ /*check if we've seen this extension before*/
+ for(j=0;j<handler_count;j++)
+ {
+ CLSID *curr_clsid = clsid_table+j;
+ if(IsEqualCLSID(curr_clsid,&CLSID_NULL))
+ {
+ *curr_clsid=id;
+ unique=TRUE;
+ break;
+ }
+ if(IsEqualCLSID(curr_clsid,&id))
+ {
+ unique=FALSE;
+ break;
+ }
+ }
+ if(!unique)
+ continue;
+ TRACE("Loading shell extension with clsid %s\n",shdebugstr_guid(&id));
+ hres = CoCreateInstance(&id,NULL,CLSCTX_INPROC_SERVER,&IID_IContextMenu,
+ (void**)(menus+real_handler_count));
+ if(SUCCEEDED(hres))
+ {
+ IShellExtInit *init;
+ hres = IContextMenu_QueryInterface(menus[real_handler_count],&IID_IShellExtInit,(void**)&init);
+ if(SUCCEEDED(hres))
+ {
+ IDataObject *data=NULL;
+ IShellFolder_GetUIObjectOf(folder,hwnd,cidl,(LPCITEMIDLIST*)apidl,
+ &IID_IDataObject,NULL,(void**)&data);
+ IShellExtInit_Initialize(init,folder_pidl,data,aKeys[i]);
+ if(data)
+ IDataObject_Release(data);
+ IShellExtInit_Release(init);
+ }
+ real_handler_count++;
+ }
+ }
+ }
+ if(enforce_approved)
+ RegCloseKey(approved_key);
+ menus[real_handler_count] = system_menu;
+ real_handler_count++;
+ ret = CompositeCMenu_Constructor(menus,real_handler_count,riid,ppv);
+ for(i=0;i<real_handler_count-1;i++)
+ IContextMenu_Release(menus[i]);
+ cleanup:
+ HeapFree(GetProcessHeap(),0,menus);
+ HeapFree(GetProcessHeap(),0,name);
+ if(new_keys)
+ for(i=0;i<cKeys;i++)
+ RegCloseKey(new_keys[i]);
+ HeapFree(GetProcessHeap(),0,clsid_table);
+ HeapFree(GetProcessHeap(),0,new_keys);
return ret;
}
From: Jay Yang <jkelleyy at gmail.com>
Subject: [PATCH 2/5] shell32: Use SHCreateDefaultContextMenu to create context menus
Message-Id: <4E68F60F.70400 at gmail.com>
Date: Thu, 08 Sep 2011 13:06:23 -0400
---
dlls/shell32/classes.c | 47 +++++++++++++++++++++++++++++++++++++++++
dlls/shell32/shell32_main.h | 1 +
dlls/shell32/shfldr.h | 13 +++++++++++
dlls/shell32/shfldr_desktop.c | 8 ++----
dlls/shell32/shfldr_fs.c | 7 +----
dlls/shell32/shfldr_mycomp.c | 4 +--
dlls/shell32/shfldr_unixfs.c | 11 ++++++---
dlls/shell32/shlmenu.c | 44 ++++++++++++++++++++++++++++++++++++++
dlls/shell32/shlview.c | 35 ++++++++++++++++++------------
9 files changed, 139 insertions(+), 31 deletions(-)
diff --git a/dlls/shell32/classes.c b/dlls/shell32/classes.c
index 9fbdf0e..c81fc70 100644
--- a/dlls/shell32/classes.c
+++ b/dlls/shell32/classes.c
@@ -473,3 +473,50 @@ BOOL HCR_GetFolderAttributes(LPCITEMIDLIST pidlFolder, LPDWORD pdwAttributes)
return TRUE;
}
+
+/*
+ * Gets subkeys of HKCR from which to load shell extensions
+ */
+UINT HCR_GetExtensionsKeysForPidl(LPCITEMIDLIST pidl,HKEY *aKeys)
+{
+ static const WCHAR star_str[] = {'*','\0'};
+ static const WCHAR drive_str[] = {'d','r','i','v','e','\0'};
+ static const WCHAR folder_str[] = {'f','o','l','d','e','r','\0'};
+ static const WCHAR directory_str[] = {'d','i','r','e','c','t','o','r','y','\0'};
+ static const WCHAR all_str[] = {'A','l','l','F','i','l','e','S','y','s','t','e','m','O','b','j','e','c','t','s','\0'};
+
+ UINT cKeys=0;
+ if(_ILIsFolder(pidl))
+ {
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,directory_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,folder_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ }
+ else if(_ILIsDrive(pidl))
+ {
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,directory_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,drive_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ }
+ else if(_ILIsSpecialFolder(pidl))
+ {
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,directory_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ }
+ else
+ {
+ char type[256];
+ char extension[MAX_EXTENSION_LENGTH+1]={'.','\0'};
+ if(_ILGetExtension(pidl,extension,sizeof(extension)) &&
+ HCR_MapTypeToValueA(extension, type, sizeof(type), FALSE) &&
+ RegOpenKeyExA(HKEY_CLASSES_ROOT,type,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,star_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ }
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,all_str,0,KEY_ENUMERATE_SUB_KEYS,aKeys+cKeys)==ERROR_SUCCESS)
+ cKeys++;
+ return cKeys;
+}
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index e043916..2ba484c 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -58,6 +58,7 @@ BOOL HCR_GetDefaultVerbW( HKEY hkeyClass, LPCWSTR szVerb, LPWSTR szDest, DWORD l
BOOL HCR_GetExecuteCommandW( HKEY hkeyClass, LPCWSTR szClass, LPCWSTR szVerb, LPWSTR szDest, DWORD len ) DECLSPEC_HIDDEN;
BOOL HCR_GetDefaultIconW(LPCWSTR szClass, LPWSTR szDest, DWORD len, int* picon_idx) DECLSPEC_HIDDEN;
BOOL HCR_GetClassNameW(REFIID riid, LPWSTR szDest, DWORD len) DECLSPEC_HIDDEN;
+UINT HCR_GetExtensionsKeysForPidl(LPCITEMIDLIST pidl,HKEY *aKeys) DECLSPEC_HIDDEN;
/* ANSI versions of above functions, supposed to go away as soon as they are not used anymore */
BOOL HCR_MapTypeToValueA(LPCSTR szExtension, LPSTR szFileType, LONG len, BOOL bPrependDot) DECLSPEC_HIDDEN;
diff --git a/dlls/shell32/shfldr.h b/dlls/shell32/shfldr.h
index 90c84d1..6222392 100644
--- a/dlls/shell32/shfldr.h
+++ b/dlls/shell32/shfldr.h
@@ -73,5 +73,18 @@ static inline int SHELL32_GUIDToStringW (REFGUID guid, LPWSTR str)
void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags) DECLSPEC_HIDDEN;
BOOL SHELL_FS_HideExtension(LPCWSTR pwszPath) DECLSPEC_HIDDEN;
+HRESULT SHELL_CreateContextMenu(HWND hwnd, IContextMenu* system_menu,
+ IShellFolder *folder, LPCITEMIDLIST folder_pidl,
+ LPCITEMIDLIST *apidl, UINT cidl, const HKEY *aKeys,
+ UINT cKeys,REFIID riid, void** ppv) DECLSPEC_HIDDEN;
+
+HRESULT SHELL_CreateItemContextMenu(HWND hwnd, IShellFolder *folder,
+ LPITEMIDLIST folder_pidl,
+ const LPCITEMIDLIST *apidl, UINT cidl,
+ REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+HRESULT SHELL_CreateBackgroundContextMenu(HWND hwnd, IShellFolder *folder,
+ LPITEMIDLIST folder_pidl,
+ REFIID riid, void **ppv) DECLSPEC_HIDDEN;
+
DEFINE_GUID( CLSID_UnixFolder, 0xcc702eb2, 0x7dc5, 0x11d9, 0xc6, 0x87, 0x00, 0x04, 0x23, 0x8a, 0x01, 0xcd );
DEFINE_GUID( CLSID_UnixDosFolder, 0x9d20aae8, 0x0625, 0x44b0, 0x9c, 0xa7, 0x71, 0x88, 0x9c, 0x22, 0x54, 0xd9 );
diff --git a/dlls/shell32/shfldr_desktop.c b/dlls/shell32/shfldr_desktop.c
index 9bf08ef..b6fbdac 100644
--- a/dlls/shell32/shfldr_desktop.c
+++ b/dlls/shell32/shfldr_desktop.c
@@ -429,8 +429,7 @@ static HRESULT WINAPI ISF_Desktop_fnCreateViewObject (IShellFolder2 * iface,
}
else if (IsEqualIID (riid, &IID_IContextMenu))
{
- WARN ("IContextMenu not implemented\n");
- hr = E_NOTIMPL;
+ hr = SHELL_CreateBackgroundContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,riid,ppvOut);
}
else if (IsEqualIID (riid, &IID_IShellView))
{
@@ -529,10 +528,9 @@ static HRESULT WINAPI ISF_Desktop_fnGetUIObjectOf (IShellFolder2 * iface,
if (IsEqualIID (riid, &IID_IContextMenu))
{
if (cidl > 0)
- pObj = (LPUNKNOWN) ISvItemCm_Constructor( (IShellFolder *) iface, This->pidlRoot, apidl, cidl);
+ hr = SHELL_CreateItemContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,apidl,cidl,riid,(void**)&pObj);
else
- pObj = (LPUNKNOWN) ISvBgCm_Constructor( (IShellFolder *) iface, TRUE);
- hr = S_OK;
+ hr = SHELL_CreateBackgroundContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,riid,(void**)&pObj);
}
else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
{
diff --git a/dlls/shell32/shfldr_fs.c b/dlls/shell32/shfldr_fs.c
index 969f18d..381b868 100644
--- a/dlls/shell32/shfldr_fs.c
+++ b/dlls/shell32/shfldr_fs.c
@@ -543,8 +543,7 @@ IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner,
if (IsEqualIID (riid, &IID_IDropTarget)) {
hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, ppvOut);
} else if (IsEqualIID (riid, &IID_IContextMenu)) {
- FIXME ("IContextMenu not implemented\n");
- hr = E_NOTIMPL;
+ hr = SHELL_CreateBackgroundContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,riid,ppvOut);
} else if (IsEqualIID (riid, &IID_IShellView)) {
pShellView = IShellView_Constructor ((IShellFolder *) iface);
if (pShellView) {
@@ -743,9 +742,7 @@ IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
}
if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
- pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface,
- This->pidlRoot, apidl, cidl);
- hr = S_OK;
+ hr = SHELL_CreateItemContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,apidl,cidl,riid,(void**)&pObj);
} else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
This->pidlRoot, apidl, cidl);
diff --git a/dlls/shell32/shfldr_mycomp.c b/dlls/shell32/shfldr_mycomp.c
index b9cbea4..dcb698b 100644
--- a/dlls/shell32/shfldr_mycomp.c
+++ b/dlls/shell32/shfldr_mycomp.c
@@ -531,9 +531,7 @@ static HRESULT WINAPI ISF_MyComputer_fnGetUIObjectOf (IShellFolder2 * iface,
if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
{
- pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface,
- This->pidlRoot, apidl, cidl);
- hr = S_OK;
+ hr = SHELL_CreateItemContextMenu(hwndOwner,(IShellFolder*)iface,This->pidlRoot,apidl,cidl,riid,(void**)&pObj);
}
else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
{
diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index 9649df8..8dfc2b2 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -1083,7 +1083,8 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_CreateViewObject(IShellFolder2* i
REFIID riid, void** ppv)
{
HRESULT hr = E_INVALIDARG;
-
+ UnixFolder *This = ADJUST_THIS(UnixFolder, IShellFolder2, iface);
+
TRACE("(iface=%p, hwndOwner=%p, riid=%p, ppv=%p) stub\n", iface, hwndOwner, riid, ppv);
if (!ppv) return E_INVALIDARG;
@@ -1100,7 +1101,10 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_CreateViewObject(IShellFolder2* i
} else if (IsEqualIID(&IID_IDropTarget, riid)) {
hr = IShellFolder2_QueryInterface(iface, &IID_IDropTarget, ppv);
}
-
+ else if (IsEqualIID(&IID_IContextMenu,riid)) {
+ hr = SHELL_CreateBackgroundContextMenu(hwndOwner,(IShellFolder*)iface,This->m_pidlLocation,riid,ppv);
+ }
+
return hr;
}
@@ -1167,8 +1171,7 @@ static HRESULT WINAPI UnixFolder_IShellFolder2_GetUIObjectOf(IShellFolder2* ifac
}
if (IsEqualIID(&IID_IContextMenu, riid)) {
- *ppvOut = ISvItemCm_Constructor((IShellFolder*)iface, This->m_pidlLocation, apidl, cidl);
- return S_OK;
+ return SHELL_CreateItemContextMenu(hwndOwner,(IShellFolder*)iface,This->m_pidlLocation,apidl,cidl,riid,ppvOut);
} else if (IsEqualIID(&IID_IDataObject, riid)) {
*ppvOut = IDataObject_Constructor(hwndOwner, This->m_pidlLocation, apidl, cidl);
return S_OK;
diff --git a/dlls/shell32/shlmenu.c b/dlls/shell32/shlmenu.c
index 070b40d..ca77edf 100644
--- a/dlls/shell32/shlmenu.c
+++ b/dlls/shell32/shlmenu.c
@@ -1464,3 +1464,47 @@ HRESULT WINAPI SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID rii
ILFree(folder_pidl);
return ret;
}
+
+HRESULT SHELL_CreateItemContextMenu(HWND hwnd, IShellFolder *folder,
+ LPITEMIDLIST folder_pidl,
+ LPCITEMIDLIST *apidl, UINT cidl,
+ REFIID riid, void **ppv)
+{
+ DEFCONTEXTMENU menu_info = {hwnd,NULL,folder_pidl,folder,cidl,apidl,NULL,0,NULL};
+ UINT cKeys = 0;
+ /*
+ * 16 is the maximum number of keys that SHCreateDefaultContextMenu
+ * can handle on windows, while our the current implementation does not have
+ * such a limitation, it makes for a nice round number to use here
+ */
+ HKEY aKeys[16] = {NULL};
+ UINT i;
+ HRESULT hres;
+ cKeys = HCR_GetExtensionsKeysForPidl(apidl[0],aKeys);
+ menu_info.cKeys=cKeys;
+ menu_info.aKeys=aKeys;
+ hres = SHCreateDefaultContextMenu(&menu_info,riid,ppv);
+ for(i=0;i<cKeys;i++)
+ RegCloseKey(aKeys[i]);
+ return hres;
+}
+
+HRESULT SHELL_CreateBackgroundContextMenu(HWND hwnd, IShellFolder *folder,
+ LPITEMIDLIST folder_pidl,
+ REFIID riid, void **ppv)
+{
+ static const WCHAR background_str[]={'d','i','r','e','c','t','o','r','y','\\','b','a','c','k','g','r','o','u','n','d','\0'};
+ HKEY background_key;
+ HRESULT hres;
+ IContextMenu *system_menu;
+ ULONG attributes=SFGAO_FILESYSTEM;
+ UINT key_count=0;
+ HCR_GetFolderAttributes(ILFindLastID(folder_pidl),&attributes);
+ if(attributes)
+ if(RegOpenKeyExW(HKEY_CLASSES_ROOT,background_str,0,KEY_ENUMERATE_SUB_KEYS,&background_key)==ERROR_SUCCESS)
+ key_count=1;
+ system_menu = (IContextMenu*)ISvBgCm_Constructor(folder,_ILIsDesktop(folder_pidl));
+ hres = SHELL_CreateContextMenu(hwnd,system_menu,folder,folder_pidl,NULL,0,&background_key,key_count,riid,ppv);
+ IContextMenu_Release(system_menu);
+ return hres;
+}
diff --git a/dlls/shell32/shlview.c b/dlls/shell32/shlview.c
index eee447e..cf692b7 100644
--- a/dlls/shell32/shlview.c
+++ b/dlls/shell32/shlview.c
@@ -42,6 +42,7 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
+#include <stdio.h>
#define COBJMACROS
#define NONAMELESSUNION
@@ -66,6 +67,7 @@
#include "pidl.h"
#include "shell32_main.h"
#include "shellfolder.h"
+#include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -1017,7 +1019,7 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
BOOL fExplore = FALSE;
HWND hwndTree = 0;
LPCONTEXTMENU pContextMenu = NULL;
- IContextMenu2 *pCM = NULL;
+ IContextMenu *pCM = NULL;
CMINVOKECOMMANDINFO cmi;
TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
@@ -1092,24 +1094,29 @@ static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL
}
else /* background context menu */
{
- hMenu = CreatePopupMenu();
+ HRESULT hr;
+ hMenu = CreatePopupMenu();
+ hr = IShellFolder_CreateViewObject(This->pSFParent,This->hWndParent,&IID_IContextMenu,(void**)&pCM);
+ if(FAILED(hr))
+ hr= SHELL_CreateBackgroundContextMenu(This->hWndParent,This->pSFParent,
+ NULL,&IID_IContextMenu,(void**)&pCM);
- pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
- IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
+ IContextMenu_QueryContextMenu(pCM, hMenu, 0, 1, 0xFFFF, 0);
- uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
- DestroyMenu(hMenu);
+ uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
+ DestroyMenu(hMenu);
- TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
+ TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
- ZeroMemory(&cmi, sizeof(cmi));
- cmi.cbSize = sizeof(cmi);
- cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
- cmi.hwnd = This->hWndParent;
- IContextMenu2_InvokeCommand(pCM, &cmi);
+ ZeroMemory(&cmi, sizeof(cmi));
+ cmi.cbSize = sizeof(cmi);
+ cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
+ cmi.hwnd = This->hWndParent;
+ IContextMenu_InvokeCommand(pCM, &cmi);
- IContextMenu2_Release(pCM);
- }
+ IContextMenu_Release(pCM);
+ DestroyMenu(hMenu);
+ }
}
/**********************************************************
More information about the wine-tests-results
mailing list