78568: Subject: [PATCH 5/5] shell32: Implement a default property sheet for file system objects

buildbot at kegel.com buildbot at kegel.com
Thu Sep 8 17:34:07 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-heaptest while building Wine.
Full details are available at: http://buildbot.kegel.com/builders/runtests-heaptest/builds/5 (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);
+    }
 }
 
 /**********************************************************

From: Jay Yang <jkelleyy at gmail.com>
Subject: [PATCH 3/5] shell32: Implement SHOpenPropSheet
Message-Id: <4E68F619.4010801 at gmail.com>
Date: Thu, 08 Sep 2011 13:06:33 -0400

---
 dlls/shell32/Makefile.in  |    1 +
 dlls/shell32/propsheet.c  |  124 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/shell32/shell32.spec |    2 +
 include/shlobj.h          |    3 +
 4 files changed, 130 insertions(+), 0 deletions(-)
 create mode 100644 dlls/shell32/propsheet.c

diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in
index c5cc72a..a50a0e2 100644
--- a/dlls/shell32/Makefile.in
+++ b/dlls/shell32/Makefile.in
@@ -24,6 +24,7 @@ C_SRCS = \
 	folders.c \
 	iconcache.c \
 	pidl.c \
+	propsheet.c \
 	recyclebin.c \
 	shell32_main.c \
 	shelldispatch.c \
diff --git a/dlls/shell32/propsheet.c b/dlls/shell32/propsheet.c
new file mode 100644
index 0000000..a0371e5
--- /dev/null
+++ b/dlls/shell32/propsheet.c
@@ -0,0 +1,124 @@
+/*
+ * Shell property sheets
+ *
+ * Copyright 2011 Jay Yang
+ *
+ * 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
+#define NONAMELESSSTRUCT
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "wine/debug.h"
+#include "shellapi.h"
+#include "debughlp.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+
+static WINAPI BOOL AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
+{
+	PROPSHEETHEADERW *psh = (PROPSHEETHEADERW*)lparam;
+	psh->u3.phpage[psh->nPages++] = hpage;
+	return TRUE;
+}
+
+BOOL WINAPI SHOpenPropSheetA(LPCSTR pszCaption, HKEY *ahkey, UINT ckeys, const CLSID *pclsidDef, IDataObject *pdtobj, IShellBrowser *psb, LPCSTR pStartPage)
+{
+    BOOL ret;
+    LPWSTR wszCaption,wszStartPage;
+    UINT length;
+    length = MultiByteToWideChar(CP_ACP, 0, pszCaption, -1, NULL, 0);
+    wszCaption = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*length);
+    length = MultiByteToWideChar(CP_ACP, 0, pszCaption, -1, wszCaption, length);
+    length = MultiByteToWideChar(CP_ACP, 0, pStartPage, -1, NULL, 0);
+    wszStartPage = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*length);
+    length = MultiByteToWideChar(CP_ACP, 0, pStartPage, -1, wszStartPage, length);
+    ret = SHOpenPropSheetW(wszCaption,ahkey,ckeys,pclsidDef,pdtobj,psb,wszStartPage);
+    HeapFree(GetProcessHeap(),0,wszCaption);
+    HeapFree(GetProcessHeap(),0,wszStartPage);
+    return ret;
+}
+
+BOOL WINAPI SHOpenPropSheetW(LPCWSTR pszCaption, HKEY *ahkey, UINT ckeys, const CLSID *pclsidDef, IDataObject *pdtobj, IShellBrowser *psb, LPCWSTR pStartPage)
+{
+    /*
+     * this value is arbitrary, but there should be no reasonable way to display
+     * this many property sheets anyways
+     */
+    static const UINT MAX_PROP_PAGES = 99;
+    IShellPropSheetExt *def_ext;
+    IShellExtInit *init_iface;
+    PROPSHEETHEADERW psh;
+    HPROPSHEETPAGE pages[MAX_PROP_PAGES];
+    UINT i;
+
+    TRACE("(%s,%p,%u,%s,%p,%p,%s)\n", debugstr_w(pszCaption),ahkey,ckeys,shdebugstr_guid(pclsidDef),pdtobj,psb,debugstr_w(pStartPage));
+
+    ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
+    psh.dwSize = sizeof (PROPSHEETHEADERW);
+    psh.hwndParent = NULL;
+    psh.dwFlags = PSH_DEFAULT;
+    if(pStartPage)
+    {
+        psh.dwFlags |= PSH_USEPSTARTPAGE;
+        psh.u2.pStartPage = pStartPage;
+    }
+    else
+        psh.u2.nStartPage = 0;
+    psh.nPages = 0;
+    psh.u3.phpage = pages;
+    if(pszCaption)
+    {
+        psh.dwFlags |= PSH_PROPTITLE;
+        psh.pszCaption = pszCaption;
+    }
+    if(pclsidDef)
+    {
+        if(SUCCEEDED(CoCreateInstance(pclsidDef,NULL,CLSCTX_INPROC_SERVER,&IID_IShellPropSheetExt,(void**)&def_ext)))
+        {
+            if(SUCCEEDED(IShellPropSheetExt_QueryInterface(def_ext,&IID_IShellExtInit,(void**)&init_iface)))
+            {
+                if(SUCCEEDED(IShellExtInit_Initialize(init_iface,NULL,pdtobj,NULL)))
+                {
+                    HRESULT hr = IShellPropSheetExt_AddPages(def_ext,AddPropSheetCallback,(LPARAM)&psh);
+                    if(SUCCEEDED(hr) && hr!=0 && !pStartPage)
+                        psh.u2.nStartPage = hr;
+                }
+                IShellPropSheetExt_Release(def_ext);
+            }
+            IShellPropSheetExt_Release(def_ext);
+        }
+    }
+    for(i=0;i<ckeys;i++)
+    {
+        HPSXA ext_array = SHCreatePropSheetExtArrayEx(ahkey[i],NULL,MAX_PROP_PAGES-psh.nPages,pdtobj);
+        SHAddFromPropSheetExtArray(ext_array,AddPropSheetCallback,(LPARAM)&psh);
+        SHDestroyPropSheetExtArray(ext_array);
+    }
+    if (psh.nPages)
+    {
+        PropertySheetW(&psh);
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
diff --git a/dlls/shell32/shell32.spec b/dlls/shell32/shell32.spec
index 2ac4310..11a45a0 100644
--- a/dlls/shell32/shell32.spec
+++ b/dlls/shell32/shell32.spec
@@ -463,3 +463,5 @@
 @ stdcall StrStrIW(wstr wstr) shlwapi.StrStrIW
 @ stdcall StrStrW(wstr wstr) shlwapi.StrStrW
 @ stdcall WOWShellExecute(long str str str str long ptr)
+@ stdcall SHOpenPropSheetA(str ptr long ptr ptr ptr str)
+@ stdcall SHOpenPropSheetW(wstr ptr long ptr ptr ptr wstr)
diff --git a/include/shlobj.h b/include/shlobj.h
index 3e9df2c..bfa1479 100644
--- a/include/shlobj.h
+++ b/include/shlobj.h
@@ -68,6 +68,9 @@ BOOL         WINAPI SHGetPathFromIDListW(LPCITEMIDLIST,LPWSTR);
 INT          WINAPI SHHandleUpdateImage(LPCITEMIDLIST);
 HRESULT      WINAPI SHILCreateFromPath(LPCWSTR,LPITEMIDLIST*,DWORD*);
 HRESULT      WINAPI SHLoadOLE(LPARAM);
+BOOL         WINAPI SHOpenPropSheetA(LPCSTR,HKEY*,UINT,const CLSID*,IDataObject*,IShellBrowser*,LPCSTR);
+BOOL         WINAPI SHOpenPropSheetW(LPCWSTR,HKEY*,UINT,const CLSID*,IDataObject*,IShellBrowser*,LPCWSTR);
+#define             SHOpenPropSheet WINELIB_NAME_AW(SHOpenPropSheet)
 HRESULT      WINAPI SHParseDisplayName(LPCWSTR,IBindCtx*,LPITEMIDLIST*,SFGAOF,SFGAOF*);
 HRESULT      WINAPI SHPathPrepareForWriteA(HWND,IUnknown*,LPCSTR,DWORD);
 HRESULT      WINAPI SHPathPrepareForWriteW(HWND,IUnknown*,LPCWSTR,DWORD);

From: Jay Yang <jkelleyy at gmail.com>
Subject: [PATCH 4/5] shell32: Use SHOpenPropSheet to open property sheets
Message-Id: <4E68F61C.8040205 at gmail.com>
Date: Thu, 08 Sep 2011 13:06:36 -0400

---
 dlls/shell32/shv_item_cmenu.c |  124 ++++------------------------------------
 1 files changed, 13 insertions(+), 111 deletions(-)

diff --git a/dlls/shell32/shv_item_cmenu.c b/dlls/shell32/shv_item_cmenu.c
index 245bbd4..4306537 100644
--- a/dlls/shell32/shv_item_cmenu.c
+++ b/dlls/shell32/shv_item_cmenu.c
@@ -377,121 +377,23 @@ static BOOL DoCopyOrCut(ItemCmImpl *This, HWND hwnd, BOOL bCut)
 }
 
 /**************************************************************************
- * Properties_AddPropSheetCallback
- *
- * Used by DoOpenProperties through SHCreatePropSheetExtArrayEx to add
- * propertysheet pages from shell extensions.
- */
-static BOOL CALLBACK Properties_AddPropSheetCallback(HPROPSHEETPAGE hpage, LPARAM lparam)
-{
-	LPPROPSHEETHEADERW psh = (LPPROPSHEETHEADERW) lparam;
-	psh->u3.phpage[psh->nPages++] = hpage;
-
-	return TRUE;
-}
-
-/**************************************************************************
  * DoOpenProperties
  */
 static void DoOpenProperties(ItemCmImpl *This, HWND hwnd)
 {
-	static const UINT MAX_PROP_PAGES = 99;
-	static const WCHAR wszFolder[] = {'F','o','l','d','e','r', 0};
-	static const WCHAR wszFiletypeAll[] = {'*',0};
-	LPSHELLFOLDER lpDesktopSF;
-	LPSHELLFOLDER lpSF;
-	LPDATAOBJECT lpDo;
-	WCHAR wszFiletype[MAX_PATH];
-	WCHAR wszFilename[MAX_PATH];
-	PROPSHEETHEADERW psh;
-	HPROPSHEETPAGE hpages[MAX_PROP_PAGES];
-	HPSXA hpsxa;
-	UINT ret;
-
-	TRACE("(%p)->(wnd=%p)\n", This, hwnd);
-
-	ZeroMemory(&psh, sizeof(PROPSHEETHEADERW));
-	psh.dwSize = sizeof (PROPSHEETHEADERW);
-	psh.hwndParent = hwnd;
-	psh.dwFlags = PSH_PROPTITLE;
-	psh.nPages = 0;
-	psh.u3.phpage = hpages;
-	psh.u2.nStartPage = 0;
-
-	_ILSimpleGetTextW(This->apidl[0], (LPVOID)&wszFilename, MAX_PATH);
-	psh.pszCaption = (LPCWSTR)&wszFilename;
-
-	/* Find out where to look for the shell extensions */
-	if (_ILIsValue(This->apidl[0]))
-	{
-	    char sTemp[64];
-	    sTemp[0] = 0;
-	    if (_ILGetExtension(This->apidl[0], sTemp, 64))
-	    {
-		HCR_MapTypeToValueA(sTemp, sTemp, 64, TRUE);
-		MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wszFiletype, MAX_PATH);
-	    }
-	    else
-	    {
-		wszFiletype[0] = 0;
-	    }
-	}
-	else if (_ILIsFolder(This->apidl[0]))
-	{
-	    lstrcpynW(wszFiletype, wszFolder, 64);
-	}
-	else if (_ILIsSpecialFolder(This->apidl[0]))
-	{
-	    LPGUID folderGUID;
-	    static const WCHAR wszclsid[] = {'C','L','S','I','D','\\', 0};
-	    folderGUID = _ILGetGUIDPointer(This->apidl[0]);
-	    lstrcpyW(wszFiletype, wszclsid);
-	    StringFromGUID2(folderGUID, &wszFiletype[6], MAX_PATH - 6);
-	}
-	else
-	{
-	    FIXME("Requested properties for unknown type.\n");
-	    return;
-	}
-
-	/* Get a suitable DataObject for accessing the files */
-	SHGetDesktopFolder(&lpDesktopSF);
-	if (_ILIsPidlSimple(This->pidl))
-	{
-	    ret = IShellFolder_GetUIObjectOf(lpDesktopSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
-					     &IID_IDataObject, NULL, (LPVOID *)&lpDo);
-	    IShellFolder_Release(lpDesktopSF);
-	}
-	else
-	{
-	    IShellFolder_BindToObject(lpDesktopSF, This->pidl, NULL, &IID_IShellFolder, (LPVOID*) &lpSF);
-	    ret = IShellFolder_GetUIObjectOf(lpSF, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
-					     &IID_IDataObject, NULL, (LPVOID *)&lpDo);
-	    IShellFolder_Release(lpSF);
-	    IShellFolder_Release(lpDesktopSF);
-	}
-
-	if (SUCCEEDED(ret))
-	{
-	    hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletype, MAX_PROP_PAGES - psh.nPages, lpDo);
-	    if (hpsxa != NULL)
-	    {
-		SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
-		SHDestroyPropSheetExtArray(hpsxa);
-	    }
-	    hpsxa = SHCreatePropSheetExtArrayEx(HKEY_CLASSES_ROOT, wszFiletypeAll, MAX_PROP_PAGES - psh.nPages, lpDo);
-	    if (hpsxa != NULL)
-	    {
-		SHAddFromPropSheetExtArray(hpsxa, Properties_AddPropSheetCallback, (LPARAM)&psh);
-		SHDestroyPropSheetExtArray(hpsxa);
-	    }
-	    IDataObject_Release(lpDo);
-	}
-
-	if (psh.nPages)
-	    PropertySheetW(&psh);
-	else
-	    FIXME("No property pages found.\n");
+    LPDATAOBJECT lpDo;
+    WCHAR wszFilename[MAX_PATH];
+    UINT ckeys;
+    HKEY ahkey[16];
+
+    TRACE("(%p)->(wnd=%p)\n", This, hwnd);
+
+    ckeys = HCR_GetExtensionsKeysForPidl(This->apidl[0],ahkey);
+    _ILSimpleGetTextW(This->apidl[0], wszFilename, MAX_PATH);
+    /* Get a suitable DataObject for accessing the files */
+    IShellFolder_GetUIObjectOf(This->pSFParent, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
+                               &IID_IDataObject, NULL, (LPVOID *)&lpDo);
+    SHOpenPropSheetW(wszFilename,ahkey,ckeys,NULL,lpDo,NULL,NULL);
 }
 
 /**************************************************************************

From: Jay Yang <jkelleyy at gmail.com>
Subject: [PATCH 5/5] shell32: Implement a default property sheet for file system objects
Message-Id: <4E68F621.8070106 at gmail.com>
Date: Thu, 08 Sep 2011 13:06:41 -0400

---
 dlls/shell32/propsheet.c         |  449 ++++++++++++++++++++++++++++++++++++++
 dlls/shell32/shell32.rc          |    2 +
 dlls/shell32/shell32_En.rc       |   39 ++++
 dlls/shell32/shell32_classes.idl |    6 +
 dlls/shell32/shell32_main.h      |    2 +
 dlls/shell32/shellole.c          |    1 +
 dlls/shell32/shresdef.h          |   15 ++
 dlls/shell32/shv_item_cmenu.c    |    2 +-
 8 files changed, 515 insertions(+), 1 deletions(-)

diff --git a/dlls/shell32/propsheet.c b/dlls/shell32/propsheet.c
index a0371e5..5d63b8d 100644
--- a/dlls/shell32/propsheet.c
+++ b/dlls/shell32/propsheet.c
@@ -26,10 +26,20 @@
 
 #include "windef.h"
 #include "winbase.h"
+#include "winreg.h"
 #include "winnls.h"
 #include "wine/debug.h"
+
 #include "shellapi.h"
+#include "shlobj.h"
+#include "shobjidl.h"
+#include "shlwapi.h"
+
 #include "debughlp.h"
+#include "shell32_main.h"
+#include "pidl.h"
+#include "shresdef.h"
+#include "initguid.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
@@ -122,3 +132,442 @@ BOOL WINAPI SHOpenPropSheetW(LPCWSTR pszCaption, HKEY *ahkey, UINT ckeys, const
     else
         return FALSE;
 }
+
+DEFINE_GUID( CLSID_DefaultPropSheet, 0x21b22460, 0x3aea, 0x1069, 0xa2, 0xdc, 0x08, 0x00, 0x2b, 0x30, 0x30, 0x9d );
+
+typedef struct
+{
+    IShellPropSheetExt IShellPropSheetExt_iface;
+    IShellExtInit IShellExtInit_iface;
+    LPITEMIDLIST folder_pidl;
+    UINT cidl;
+    LPITEMIDLIST *apidl;
+    LONG refCount;
+}DefaultPropSheet;
+
+static const IShellPropSheetExtVtbl shellPropSheetExtVtbl;
+static const IShellExtInitVtbl shellExtInitVtbl;
+
+static inline DefaultPropSheet *impl_from_IShellPropSheetExt(IShellPropSheetExt *iface)
+{
+    return CONTAINING_RECORD(iface, DefaultPropSheet, IShellPropSheetExt_iface);
+}
+
+static inline DefaultPropSheet *impl_from_IShellExtInit(IShellExtInit *iface)
+{
+    return CONTAINING_RECORD(iface, DefaultPropSheet, IShellExtInit_iface);
+}
+
+HRESULT WINAPI DefaultPropSheet_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
+{
+    DefaultPropSheet *This;
+    HRESULT ret;
+    if(pUnkOuter)
+        return CLASS_E_NOAGGREGATION;
+    This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DefaultPropSheet));
+    This->refCount = 1;
+    This->IShellPropSheetExt_iface.lpVtbl = &shellPropSheetExtVtbl;
+    This->IShellExtInit_iface.lpVtbl = &shellExtInitVtbl;
+    ret = IShellPropSheetExt_QueryInterface(&This->IShellPropSheetExt_iface,riid,ppv);
+    IShellPropSheetExt_Release(&This->IShellPropSheetExt_iface);
+    return ret;
+}
+
+static HRESULT WINAPI DefaultPropSheet_QueryInterface(IShellPropSheetExt *iface, REFIID riid, void **ppv)
+{
+    DefaultPropSheet *This = impl_from_IShellPropSheetExt(iface);
+    *ppv = NULL;
+    if(IsEqualIID(riid,&IID_IShellPropSheetExt) || IsEqualIID(riid,&IID_IUnknown))
+        *ppv = iface;
+    else if(IsEqualIID(riid,&IID_IShellExtInit))
+        *ppv = &This->IShellExtInit_iface;
+    else
+        return E_NOINTERFACE;
+    IShellPropSheetExt_AddRef(iface);
+    return S_OK;
+}
+
+static ULONG WINAPI DefaultPropSheet_AddRef(IShellPropSheetExt *iface)
+{
+    DefaultPropSheet *This = impl_from_IShellPropSheetExt(iface);
+    return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI DefaultPropSheet_Release(IShellPropSheetExt *iface)
+{
+    DefaultPropSheet *This = impl_from_IShellPropSheetExt(iface);
+    if(!InterlockedDecrement(&This->refCount))
+    {
+        ILFree(This->folder_pidl);
+        _ILFreeaPidl(This->apidl,This->cidl);
+        HeapFree(GetProcessHeap(),0,This);
+        return 0;
+    }
+    return This->refCount;
+}
+
+static LPWSTR format_system_time(const SYSTEMTIME *systime)
+{
+    UINT date_length,time_length,length;
+    LPWSTR date_time_str;
+    WCHAR comma_str[] = {',',' ','\0'};
+    date_length = GetDateFormatW(LOCALE_USER_DEFAULT,0,systime,NULL,NULL,0);
+    time_length  = GetTimeFormatW(LOCALE_USER_DEFAULT,0,systime,NULL,NULL,0);
+    length=date_length+time_length+strlenW(comma_str)-1;
+    date_time_str= HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*length);
+    GetDateFormatW(LOCALE_USER_DEFAULT,0,systime,NULL,date_time_str,date_length);
+    strcpyW(date_time_str+strlenW(date_time_str),comma_str);
+    GetTimeFormatW(LOCALE_USER_DEFAULT,0,systime,NULL,date_time_str+strlenW(date_time_str),time_length);
+    return date_time_str;
+}
+
+static INT_PTR DefaultPropSheet_OnInitDialog(HWND hwndDlg, PROPSHEETPAGEW *page)
+{
+    /*this is arbitrary*/
+    static const FILE_TYPE_LENGTH=64;
+    DefaultPropSheet *propsheet = (DefaultPropSheet*)page->lParam;
+    BOOL readonly_differs = FALSE, hidden_differs = FALSE;
+    DWORD attributes;
+    char file_type[FILE_TYPE_LENGTH];
+    WCHAR file_path[MAX_PATH];
+    WCHAR file_name[MAX_PATH];
+    WIN32_FILE_ATTRIBUTE_DATA file_data;
+    LPITEMIDLIST pidl,pidl_simple;
+    UINT folder_count=0,file_count=0;
+    pidl = ILCombine(propsheet->folder_pidl,propsheet->apidl[0]);
+    pidl_simple = ILFindLastID(pidl);
+    _ILGetFileType(pidl_simple,file_type,sizeof(file_type));
+    if(_ILIsValue(pidl))
+        file_count++;
+    else
+        folder_count++;
+    _ILSimpleGetTextW(pidl_simple,file_name,sizeof(file_name)/sizeof(WCHAR));
+    SHGetPathFromIDListW(pidl,file_path);
+    GetFileAttributesExW(file_path,GetFileExInfoStandard,&file_data);
+    attributes = file_data.dwFileAttributes;
+    ILFree(pidl);
+    if(propsheet->cidl>1)
+    {
+        UINT i,format_len;
+        LPWSTR count_str,count_format;
+        LPCWSTR raw_format;
+        char various_str[FILE_TYPE_LENGTH];
+        LoadStringA(shell32_hInstance,IDS_PROPSHEET_VARIOUS,
+                    various_str,sizeof(various_str));
+        for(i=1;i<propsheet->cidl;i++)
+        {
+            char curr_file_type[FILE_TYPE_LENGTH];
+            DWORD diff;
+            pidl = ILCombine(propsheet->folder_pidl,propsheet->apidl[i]);
+            if(_ILIsValue(pidl))
+                file_count++;
+            else
+                folder_count++;
+            SHGetPathFromIDListW(pidl,file_path);
+            pidl_simple = ILFindLastID(pidl);
+            _ILGetFileType(pidl_simple,curr_file_type,sizeof(file_type));
+            if(strcmp(file_type,curr_file_type)!=0)
+                lstrcpynA(file_type,various_str,sizeof(file_type));
+            SHGetPathFromIDListW(pidl,file_path);
+            GetFileAttributesExW(file_path,GetFileExInfoStandard,&file_data);
+            diff = (attributes^file_data.dwFileAttributes);
+            if(diff&FILE_ATTRIBUTE_READONLY)
+                readonly_differs=TRUE;
+            if(diff&FILE_ATTRIBUTE_HIDDEN)
+                hidden_differs=TRUE;
+            ILFree(pidl);
+        }
+        format_len = LoadStringW(shell32_hInstance,IDS_PROPSHEET_COUNT_FORMAT,
+                                 (LPWSTR)&raw_format,0);
+        count_format = HeapAlloc(GetProcessHeap(),0,(format_len+1)*sizeof(WCHAR));
+        if(count_format)
+        {
+            memcpy(count_format,raw_format,format_len*sizeof(WCHAR));
+            count_format[format_len] = 0;
+            /*
+             *each UINT is formated in decimal, so that is at most
+             *10 digits each, for a total of 20 more characters.
+             *This ignores the characters already taken up by the "%i" sequence
+             */
+            count_str = HeapAlloc(GetProcessHeap(),0,(format_len+20+1)*sizeof(WCHAR));
+            if(count_str)
+            {
+                sprintfW(count_str,count_format,file_count,folder_count);
+                SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_COUNT,count_str);
+                HeapFree(GetProcessHeap(),0,count_str);
+            }
+            HeapFree(GetProcessHeap(),0,count_format);
+        }
+    }
+    else
+    {
+        LPWSTR time;
+        SYSTEMTIME systime;
+        LONGLONG size = file_data.nFileSizeHigh*((LONGLONG)MAXDWORD+1)+file_data.nFileSizeLow;
+        WCHAR size_str[10];
+        SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_NAME,file_name);
+        /*Format times*/
+        FileTimeToSystemTime(&file_data.ftCreationTime,&systime);
+        time = format_system_time(&systime);
+        SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_CREATE_TIME,time);
+        HeapFree(GetProcessHeap(),0,time);
+        FileTimeToSystemTime(&file_data.ftLastAccessTime,&systime);
+        time = format_system_time(&systime);
+        SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_MODIFY_TIME,time);
+        HeapFree(GetProcessHeap(),0,time);
+        FileTimeToSystemTime(&file_data.ftLastWriteTime,&systime);
+        time = format_system_time(&systime);
+        SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_ACCESS_TIME,time);
+        HeapFree(GetProcessHeap(),0,time);
+
+        StrFormatByteSizeW(size,size_str,sizeof(size_str)/sizeof(WCHAR));
+        SetDlgItemTextW(hwndDlg,IDC_PROPSHEET_SIZE,size_str);
+    }
+    /*set items common to both*/
+    SetDlgItemTextA(hwndDlg,IDC_PROPSHEET_TYPE,file_type);
+    if(readonly_differs)
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_READONLY,BST_INDETERMINATE);
+    else if(attributes & FILE_ATTRIBUTE_READONLY)
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_READONLY,BST_CHECKED);
+    else
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_READONLY,BST_UNCHECKED);
+    if(hidden_differs)
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_HIDDEN,BST_INDETERMINATE);
+    else if(attributes & FILE_ATTRIBUTE_HIDDEN)
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_HIDDEN,BST_CHECKED);
+    else
+        CheckDlgButton(hwndDlg,IDC_PROPSHEET_HIDDEN,BST_UNCHECKED);
+    return TRUE;
+}
+
+static INT_PTR DefaultPropSheet_OnCommand(HWND hwndDlg,WPARAM wParam, LPARAM lParam)
+{
+    UINT index;
+
+    switch(LOWORD(wParam))
+    {
+        /*we do handling for the checboxes ourselves*/
+    case IDC_PROPSHEET_READONLY:
+    case IDC_PROPSHEET_HIDDEN:
+        index = LOWORD(wParam);
+        if(IsDlgButtonChecked(hwndDlg,index)==BST_CHECKED)
+            CheckDlgButton(hwndDlg,index,BST_UNCHECKED);
+        else
+            CheckDlgButton(hwndDlg,index,BST_CHECKED);
+        SendMessageW(GetParent(hwndDlg),PSM_CHANGED,(WPARAM)hwndDlg,0);
+        break;
+    case IDC_PROPSHEET_NAME:
+        if(HIWORD(wParam)==EN_UPDATE)
+        {
+            SendMessageW(GetParent(hwndDlg),PSM_CHANGED,(WPARAM)hwndDlg,0);
+            break;
+        }
+    default:
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static INT_PTR DefaultPropSheet_OnNotify(HWND hwndDlg,WPARAM wParam, NMHDR *header)
+{
+    switch(header->code)
+    {
+    case PSN_APPLY:
+        {
+            UINT index;
+            PROPSHEETPAGEW *page;
+            DefaultPropSheet *propsheet;
+            WCHAR name[MAX_PATH];
+            UINT readonly_state, hidden_state;
+            UINT i;
+            index = SendMessageW(GetParent(hwndDlg),PSM_HWNDTOINDEX,(WPARAM)hwndDlg,0);
+            page = (PROPSHEETPAGEW*)SendMessageW(GetParent(hwndDlg),PSM_INDEXTOPAGE,index,0);
+            propsheet = (DefaultPropSheet*)page->lParam;
+
+            /*set name*/
+            if(propsheet->cidl==1)
+            {
+                BOOL is_folder;
+                LPCITEMIDLIST pidl_child;
+                LPITEMIDLIST pidl,pidl_new,pidl_child_new,temp;
+                IShellFolder *folder;
+                WCHAR old_name[MAX_PATH];
+                GetDlgItemTextW(hwndDlg,IDC_PROPSHEET_NAME,name,sizeof(name)/sizeof(WCHAR));
+                pidl = ILCombine(propsheet->folder_pidl,propsheet->apidl[0]);
+                is_folder = _ILIsFolder(pidl);
+                temp = ILClone(pidl);
+                ILRemoveLastID(temp);
+                SHBindToParent(pidl,&IID_IShellFolder,(void**)&folder,&pidl_child);
+                ILGetDisplayNameExW(folder, pidl_child, old_name,SHGDN_NORMAL);
+                if(strcmpW(old_name,name)!=0)
+                {
+                    if(SUCCEEDED(IShellFolder_SetNameOf(folder,hwndDlg,pidl_child,name,SHGDN_NORMAL,&pidl_child_new)))
+                    {
+                        pidl_new = ILCombine(temp,pidl_child_new);
+                        SHChangeNotify(is_folder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM,SHCNF_IDLIST,pidl,pidl_new);
+                        ILFree(pidl_child_new);
+                        ILFree(pidl_new);
+                    }
+                }
+                ILFree(temp);
+                ILFree(pidl);
+                IShellFolder_Release(folder);
+            }
+            /*set readonly/hidden*/
+            readonly_state = IsDlgButtonChecked(hwndDlg,IDC_PROPSHEET_READONLY);
+            hidden_state = IsDlgButtonChecked(hwndDlg,IDC_PROPSHEET_HIDDEN);
+            for(i=0;i<propsheet->cidl;i++)
+            {
+                LPITEMIDLIST pidl;
+                WCHAR path[MAX_PATH];
+                DWORD attributes;
+                pidl = ILCombine(propsheet->folder_pidl,propsheet->apidl[0]);
+                SHGetPathFromIDListW(pidl,path);
+                ILFree(pidl);
+                attributes = GetFileAttributesW(path);
+                switch(readonly_state)
+                {
+                case BST_CHECKED:
+                    attributes |= FILE_ATTRIBUTE_READONLY;
+                    break;
+                case BST_UNCHECKED:
+                    attributes &= ~FILE_ATTRIBUTE_READONLY;
+                    break;
+                }
+                switch(hidden_state)
+                {
+                case BST_CHECKED:
+                    attributes |= FILE_ATTRIBUTE_HIDDEN;
+                    break;
+                case BST_UNCHECKED:
+                    attributes &= ~FILE_ATTRIBUTE_HIDDEN;
+                    break;
+                }
+                SetFileAttributesW(path,attributes);
+            }
+            break;
+        }
+    case PSN_RESET:
+        {
+            UINT index;
+            PROPSHEETPAGEW *page;
+            DefaultPropSheet *propsheet;
+            index = SendMessageW(GetParent(hwndDlg),PSM_HWNDTOINDEX,(WPARAM)hwndDlg,0);
+            page = (PROPSHEETPAGEW*)SendMessageW(GetParent(hwndDlg),PSM_INDEXTOPAGE,index,0);
+            propsheet = ((DefaultPropSheet*)page->lParam);
+            IShellPropSheetExt_Release(&propsheet->IShellPropSheetExt_iface);
+        }
+    default:
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+static INT_PTR CALLBACK DefaultPropSheet_DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    switch(uMsg)
+    {
+    case WM_INITDIALOG:
+        return DefaultPropSheet_OnInitDialog(hwndDlg,(PROPSHEETPAGEW*)lParam);
+    case WM_COMMAND:
+        return DefaultPropSheet_OnCommand(hwndDlg,wParam,lParam);
+    case WM_NOTIFY:
+        return DefaultPropSheet_OnNotify(hwndDlg,wParam,(NMHDR*)lParam);
+    default:
+        return FALSE;
+    }
+}
+
+static HRESULT WINAPI DefaultPropSheet_AddPages(IShellPropSheetExt *iface, LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam)
+{
+    static const WCHAR single_template[]={'S','H','E','L','L','_','S','I','N','G','L','E','_','P','R','O','P','S','H','E','E','T',0};
+    static const WCHAR multiple_template[]={'S','H','E','L','L','_','M','U','L','T','I','P','L','E','_','P','R','O','P','S','H','E','E','T',0};
+    PROPSHEETPAGEW propsheet;
+    HPROPSHEETPAGE hpage;
+    DefaultPropSheet *This = impl_from_IShellPropSheetExt(iface);
+
+    propsheet.dwSize=sizeof(propsheet);
+    propsheet.dwFlags=PSP_DEFAULT;
+    propsheet.hInstance = shell32_hInstance;
+    if(This->cidl>1)
+        propsheet.u.pszTemplate = multiple_template;
+    else
+        propsheet.u.pszTemplate = single_template;
+    propsheet.pfnDlgProc=DefaultPropSheet_DialogProc;
+    IShellPropSheetExt_AddRef(iface);
+    propsheet.lParam=(LPARAM)This;
+    hpage = CreatePropertySheetPageW(&propsheet);
+    if(hpage)
+    {
+        if(!pfnAddPage(hpage,lParam))
+            DestroyPropertySheetPage(hpage);
+        else
+            return E_FAIL;
+    }
+    else
+        return E_FAIL;
+    return S_OK;
+}
+
+static HRESULT WINAPI DefaultPropSheet_ReplacePages(IShellPropSheetExt *iface, UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam)
+{
+    return E_NOTIMPL;
+}
+
+static const IShellPropSheetExtVtbl shellPropSheetExtVtbl =
+{
+    DefaultPropSheet_QueryInterface,
+    DefaultPropSheet_AddRef,
+    DefaultPropSheet_Release,
+    DefaultPropSheet_AddPages,
+    DefaultPropSheet_ReplacePages
+};
+
+static HRESULT WINAPI DefaultPropSheet_IShellExtInit_QueryInterface(IShellExtInit *iface, REFIID riid, void **ppv)
+{
+    DefaultPropSheet *This = impl_from_IShellExtInit(iface);
+    return IShellPropSheetExt_QueryInterface(&This->IShellPropSheetExt_iface,riid,ppv);
+}
+
+static ULONG WINAPI DefaultPropSheet_IShellExtInit_AddRef(IShellExtInit* iface)
+{
+    DefaultPropSheet *This = impl_from_IShellExtInit(iface);
+    return IShellPropSheetExt_AddRef(&This->IShellPropSheetExt_iface);
+}
+
+static ULONG WINAPI DefaultPropSheet_IShellExtInit_Release(IShellExtInit* iface)
+{
+    DefaultPropSheet *This = impl_from_IShellExtInit(iface);
+    return IShellPropSheetExt_Release(&This->IShellPropSheetExt_iface);
+}
+
+static HRESULT WINAPI DefaultPropSheet_IShellExtInit_Initialize(IShellExtInit *iface, LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
+{
+    HRESULT hr;
+    CIDA *cida;
+    FORMATETC format;
+    STGMEDIUM medium;
+    CLIPFORMAT cbformat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
+    DefaultPropSheet *This = impl_from_IShellExtInit(iface);
+    InitFormatEtc(format,cbformat,TYMED_HGLOBAL);
+    hr = IDataObject_GetData(pdtobj,&format,&medium);
+    if(FAILED(hr))
+    {
+        WARN("Couldn't get pidl data from the data object\n");
+        return hr;
+    }
+    cida = GlobalLock(medium.u.hGlobal);
+    This->cidl = cida->cidl;
+    This->apidl=_ILCopyCidaToaPidl(&This->folder_pidl,cida);
+    GlobalUnlock(medium.u.hGlobal);
+    return S_OK;
+}
+
+static const IShellExtInitVtbl shellExtInitVtbl=
+{
+    DefaultPropSheet_IShellExtInit_QueryInterface,
+    DefaultPropSheet_IShellExtInit_AddRef,
+    DefaultPropSheet_IShellExtInit_Release,
+    DefaultPropSheet_IShellExtInit_Initialize
+};
diff --git a/dlls/shell32/shell32.rc b/dlls/shell32/shell32.rc
index 9eeaea7..b60a376 100644
--- a/dlls/shell32/shell32.rc
+++ b/dlls/shell32/shell32.rc
@@ -258,6 +258,8 @@ STRINGTABLE
         IDS_RECYCLEBIN_OVERWRITEFILE      "A file already exists at the path %1.\n\nDo you want to replace it?"
         IDS_RECYCLEBIN_OVERWRITEFOLDER      "A folder already exists at the path %1.\n\nDo you want to replace it?"
         IDS_RECYCLEBIN_OVERWRITE_CAPTION    "Confirm overwrite"
+        IDS_PROPSHEET_VARIOUS      "Various"
+        IDS_PROPSHEET_COUNT_FORMAT "%i Files, %i Folders"
 }
 
 STRINGTABLE
diff --git a/dlls/shell32/shell32_En.rc b/dlls/shell32/shell32_En.rc
index 4e0407e..7e950d0 100644
--- a/dlls/shell32/shell32_En.rc
+++ b/dlls/shell32/shell32_En.rc
@@ -94,3 +94,42 @@ FONT 8, "MS Shell Dlg"
  PUSHBUTTON "Cancel", IDCANCEL, 116, 63, 50, 14, WS_TABSTOP
  PUSHBUTTON "&Browse...", IDC_RUNDLG_BROWSE, 170, 63, 50, 14, WS_TABSTOP
 }
+
+SHELL_SINGLE_PROPSHEET DIALOG 0,0,212,188
+STYLE WS_CAPTION | WS_DISABLED | WS_CHILD
+CAPTION "General"
+FONT 8, "MS Shell Dlg"
+{
+ GROUPBOX "" , IDC_PROPSHEET_STATIC ,4, 4, 204, 42
+ LTEXT "Name:" , IDC_PROPSHEET_STATIC , 7, 12, 40, 10
+ EDITTEXT  IDC_PROPSHEET_NAME, 50, 12, 150, 10, WS_VISIBLE | ES_AUTOHSCROLL
+ LTEXT "Size:" , IDC_PROPSHEET_STATIC , 7, 22, 40, 10
+ LTEXT "", IDC_PROPSHEET_SIZE , 50, 22, 150, 10
+ LTEXT "File type:" , IDC_PROPSHEET_STATIC , 7, 32, 40, 10
+ LTEXT "", IDC_PROPSHEET_TYPE , 50, 32, 150, 10
+ GROUPBOX "", IDC_PROPSHEET_STATIC, 4, 46, 204, 42
+ LTEXT "Created:" , IDC_PROPSHEET_STATIC, 7, 54, 40, 10
+ LTEXT "", IDC_PROPSHEET_CREATE_TIME , 50, 54, 150, 10
+ LTEXT "Accessed:" , IDC_PROPSHEET_STATIC, 7, 64, 40, 10
+ LTEXT "", IDC_PROPSHEET_ACCESS_TIME , 50, 64, 150, 10
+ LTEXT "Modified:" , IDC_PROPSHEET_STATIC, 7, 74, 40, 10
+ LTEXT "", IDC_PROPSHEET_MODIFY_TIME , 50, 74, 150, 10
+ GROUPBOX "Attributes" , IDC_PROPSHEET_STATIC ,4, 88, 204, 32
+ CHECKBOX "Read Only" , IDC_PROPSHEET_READONLY, 7, 96, 50, 10
+ CHECKBOX "Hidden" , IDC_PROPSHEET_HIDDEN, 7, 106, 50, 10
+}
+
+SHELL_MULTIPLE_PROPSHEET DIALOG 0,0,212,188
+STYLE WS_CAPTION | WS_DISABLED | WS_CHILD
+CAPTION "General"
+FONT 8, "MS Shell Dlg"
+{
+ GROUPBOX "" , IDC_PROPSHEET_STATIC ,4, 4, 204, 32
+ LTEXT "Count:" , IDC_PROPSHEET_STATIC , 7, 12, 40, 10
+ LTEXT "" , IDC_PROPSHEET_COUNT, 50, 12, 150, 10
+ LTEXT "File types:" , IDC_PROPSHEET_STATIC , 7, 22, 40, 10
+ LTEXT "" , IDC_PROPSHEET_TYPE, 50, 22, 150, 10
+ GROUPBOX "Attributes" , IDC_PROPSHEET_STATIC ,4, 36, 204, 52
+ STATE3 "Read Only" , IDC_PROPSHEET_READONLY, 7, 44, 50, 10
+ STATE3 "Hidden" , IDC_PROPSHEET_HIDDEN, 7, 54, 50, 10
+}
diff --git a/dlls/shell32/shell32_classes.idl b/dlls/shell32/shell32_classes.idl
index ae3e619..5ac2c08 100644
--- a/dlls/shell32/shell32_classes.idl
+++ b/dlls/shell32/shell32_classes.idl
@@ -140,3 +140,9 @@ coclass KnownFolderManager { interface IKnownFolderManager; }
     threading(apartment),
     uuid(53bd6b4e-3780-4693-afc3-7161c2f3ee9c)
 ] coclass MruLongList { }
+
+[
+    helpstring(""),
+    threading(apartment),
+    uuid(21b22460-3aea-1069-a2dc-08002b30309d)
+] coclass DefaultPropSheet { interface IShellPropSheetExt; interface IShellExtInit;}
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index 2ba484c..8985701 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -108,6 +108,7 @@ HRESULT WINAPI CPanel_ExtractIconA(LPITEMIDLIST pidl, LPCSTR pszFile, UINT nIcon
 HRESULT WINAPI CPanel_ExtractIconW(LPITEMIDLIST pidl, LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI IAutoComplete_Constructor(IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv) DECLSPEC_HIDDEN;
+HRESULT WINAPI DefaultPropSheet_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv) DECLSPEC_HIDDEN;
 
 LPEXTRACTICONA	IExtractIconA_Constructor(LPCITEMIDLIST) DECLSPEC_HIDDEN;
 LPEXTRACTICONW	IExtractIconW_Constructor(LPCITEMIDLIST) DECLSPEC_HIDDEN;
@@ -196,6 +197,7 @@ extern WCHAR swShell32Name[MAX_PATH] DECLSPEC_HIDDEN;
 BOOL UNIXFS_is_rooted_at_desktop(void) DECLSPEC_HIDDEN;
 extern const GUID CLSID_UnixFolder DECLSPEC_HIDDEN;
 extern const GUID CLSID_UnixDosFolder DECLSPEC_HIDDEN;
+extern const GUID CLSID_DefaultPropSheet DECLSPEC_HIDDEN;
 
 extern BOOL run_winemenubuilder( const WCHAR *args ) DECLSPEC_HIDDEN;
 
diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c
index 2fac864..a5a56b3 100644
--- a/dlls/shell32/shellole.c
+++ b/dlls/shell32/shellole.c
@@ -82,6 +82,7 @@ static const struct {
 	{&CLSID_ExplorerBrowser,ExplorerBrowser_Constructor},
 	{&CLSID_KnownFolderManager, KnownFolderManager_Constructor},
 	{&CLSID_Shell,          IShellDispatch_Constructor},
+	{&CLSID_DefaultPropSheet, DefaultPropSheet_Constructor},
 	{NULL, NULL}
 };
 
diff --git a/dlls/shell32/shresdef.h b/dlls/shell32/shresdef.h
index 1c3a381..b8e0eb8 100644
--- a/dlls/shell32/shresdef.h
+++ b/dlls/shell32/shresdef.h
@@ -149,6 +149,9 @@
 #define IDS_RECYCLEBIN_OVERWRITEFOLDER   170
 #define IDS_RECYCLEBIN_OVERWRITE_CAPTION 171
 
+#define IDS_PROPSHEET_VARIOUS 172
+#define IDS_PROPSHEET_COUNT_FORMAT 173
+
 
 #define IDS_LICENSE                 256
 #define IDS_LICENSE_CAPTION         257
@@ -247,6 +250,18 @@ FIXME: Need to add them, but for now just let them use the same: searching.avi
 #define IDC_RUNDLG_EDITPATH     12298
 #define IDC_RUNDLG_LABEL        12305
 
+/* property sheets */
+#define IDC_PROPSHEET_STATIC         -1
+#define IDC_PROPSHEET_NAME           100
+#define IDC_PROPSHEET_COUNT          101
+#define IDC_PROPSHEET_SIZE           102
+#define IDC_PROPSHEET_TYPE      103
+#define IDC_PROPSHEET_CREATE_TIME    104
+#define IDC_PROPSHEET_MODIFY_TIME  105
+#define IDC_PROPSHEET_ACCESS_TIME    106
+#define IDC_PROPSHEET_READONLY       107
+#define IDC_PROPSHEET_HIDDEN         108
+
 /* bitmaps */
 /* explorer toolbar icons
  * FIXME: images are hacky and should be re-drawn; also dark and light bitmaps are same for now
diff --git a/dlls/shell32/shv_item_cmenu.c b/dlls/shell32/shv_item_cmenu.c
index 4306537..8f45afb 100644
--- a/dlls/shell32/shv_item_cmenu.c
+++ b/dlls/shell32/shv_item_cmenu.c
@@ -393,7 +393,7 @@ static void DoOpenProperties(ItemCmImpl *This, HWND hwnd)
     /* Get a suitable DataObject for accessing the files */
     IShellFolder_GetUIObjectOf(This->pSFParent, hwnd, This->cidl, (LPCITEMIDLIST*)This->apidl,
                                &IID_IDataObject, NULL, (LPVOID *)&lpDo);
-    SHOpenPropSheetW(wszFilename,ahkey,ckeys,NULL,lpDo,NULL,NULL);
+    SHOpenPropSheetW(wszFilename,ahkey,ckeys,&CLSID_DefaultPropSheet,lpDo,NULL,NULL);
 }
 
 /**************************************************************************



More information about the wine-tests-results mailing list