78564: Subject: [PATCH 1/5] shell32: Implement loading of context menu shell extensions

buildbot at kegel.com buildbot at kegel.com
Fri Sep 9 07:51:59 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 while building Wine.
Full details are available at: http://buildbot.kegel.com/builders/runtests-default/builds/0 (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;
 }
 



More information about the wine-tests-results mailing list