[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 15 Nov 2016 20:14:56 +0000 (20:14 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 15 Nov 2016 20:14:56 +0000 (20:14 +0000)
- Implement filling in needed keys passed to CDefFolderMenu_Create2.
- CDefaultContextMenu: Remove the code that filled the array of keys as this is now moved to the implementation of the shell folder.

svn path=/trunk/; revision=73237

reactos/dll/win32/shell32/CDefaultContextMenu.cpp
reactos/dll/win32/shell32/folders/CControlPanelFolder.cpp
reactos/dll/win32/shell32/folders/CDesktopFolder.cpp
reactos/dll/win32/shell32/folders/CDrivesFolder.cpp
reactos/dll/win32/shell32/folders/CFSFolder.cpp
reactos/dll/win32/shell32/folders/CRegFolder.cpp
reactos/dll/win32/shell32/shfldr.h
reactos/dll/win32/shell32/shlfolder.cpp

index 46d71c8..d6b8ba9 100644 (file)
@@ -1571,96 +1571,10 @@ CDefaultContextMenu_CreateInstance(const DEFCONTEXTMENU *pdcm, REFIID riid, void
  *
  */
 
-static void AddClassKey(const WCHAR * szClass, HKEY* buffer, UINT* cKeys)
-{
-    LSTATUS result;
-    HKEY hkey;
-    result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szClass, 0, KEY_READ | KEY_QUERY_VALUE, &hkey);
-    if (result != ERROR_SUCCESS)
-        return;
-
-    buffer[*cKeys] = hkey;
-    *cKeys +=1;
-}
-
-void HackFillKeys(DEFCONTEXTMENU *pdcm, HKEY* buffer)
-{
-    PCUITEMID_CHILD pidl = pdcm->apidl[0];
-    pdcm->cKeys = 0;
-    pdcm->aKeys = buffer;
-
-    if (_ILIsValue(pidl))
-    {
-        FileStructW* pFileData = _ILGetFileStructW(pidl);
-        LPWSTR extension = PathFindExtension(pFileData->wszName);
-
-        if (extension)
-        {
-            AddClassKey(extension, buffer, &pdcm->cKeys);
-
-            WCHAR wszClass[40], wszClass2[40];
-            DWORD dwSize = sizeof(wszClass);
-            if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
-            {
-                swprintf(wszClass2, L"%s//%s", extension, wszClass);
-
-                AddClassKey(wszClass, buffer, &pdcm->cKeys);
-                AddClassKey(wszClass2, buffer, &pdcm->cKeys);
-            }
-
-            swprintf(wszClass2, L"SystemFileAssociations//%s", extension);
-            AddClassKey(wszClass2, buffer, &pdcm->cKeys);
-
-            if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
-            {
-                swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass);
-                AddClassKey(wszClass2, buffer, &pdcm->cKeys);
-            }
-        }
-
-        AddClassKey(L"AllFilesystemObjects", buffer, &pdcm->cKeys);
-        AddClassKey(L"*", buffer, &pdcm->cKeys);
-    }
-    else if (_ILIsSpecialFolder(pidl))
-    {
-        GUID *pGuid = _ILGetGUIDPointer(pidl);
-        if (pGuid)
-        {
-            LPOLESTR pwszCLSID;
-            WCHAR key[60];
-
-            wcscpy(key, L"CLSID\\");
-            HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID);
-            if (hr == S_OK)
-            {
-                wcscpy(&key[6], pwszCLSID);
-                AddClassKey(key, buffer, &pdcm->cKeys);
-            }
-        }
-        AddClassKey(L"Folder", buffer, &pdcm->cKeys);
-    }
-    else if (_ILIsFolder(pidl))
-    {
-        AddClassKey(L"AllFilesystemObjects", buffer, &pdcm->cKeys);
-        AddClassKey(L"Directory", buffer, &pdcm->cKeys);
-        AddClassKey(L"Folder", buffer, &pdcm->cKeys);
-    }
-    else if (_ILIsDrive(pidl))
-    {
-        AddClassKey(L"Drive", buffer, &pdcm->cKeys);
-        AddClassKey(L"Folder", buffer, &pdcm->cKeys);
-    }
-}
-
 HRESULT
 WINAPI
 SHCreateDefaultContextMenu(const DEFCONTEXTMENU *pdcm, REFIID riid, void **ppv)
 {
-   /* HACK: move to the shell folders implementation */
-    HKEY hkeyHack[16];
-    if (!pdcm->aKeys && pdcm->cidl)
-        HackFillKeys((DEFCONTEXTMENU *)pdcm, hkeyHack);
-
     HRESULT hr = CDefaultContextMenu_CreateInstance(pdcm, riid, ppv);
     if (FAILED_UNEXPECTEDLY(hr))
         return hr;
index cadf7c3..e9dba76 100644 (file)
@@ -486,7 +486,7 @@ HRESULT WINAPI CControlPanelFolder::GetUIObjectOf(HWND hwndOwner,
             if (bHasCpl)
                 hr = ShellObjectCreatorInit<CCPLItemMenu>(cidl, apidl, riid, &pObj);
             else
-                hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj);
+                hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
         } else if (IsEqualIID(riid, IID_IDataObject) && (cidl >= 1)) {
             hr = IDataObject_Constructor(hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
         } else if ((IsEqualIID(riid, IID_IExtractIconA) || IsEqualIID(riid, IID_IExtractIconW)) && (cidl == 1)) {
index 0630ea5..6ab512d 100644 (file)
@@ -639,7 +639,21 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
 
     if (IsEqualIID (riid, IID_IContextMenu))
     {
-        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder *)this, NULL, 0, NULL, (IContextMenu **)&pObj);
+        if (_ILIsSpecialFolder(apidl[0]))
+        {
+            hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
+        }
+        else
+        {
+            /* Do not use the context menu of the CFSFolder here. */
+            /* We need to pass a pointer of the CDesktopFolder  so as the data object that the context menu gets is rooted to the desktop */
+            /* Otherwise operations like that involve items from both user and shared desktop will not work */
+            IContextMenu  * pCm = NULL;
+            HKEY hKeys[16];
+            UINT cKeys = 0;
+            AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
+            hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, cKeys, hKeys, &pCm);
+        }
     }
     else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
     {
@@ -817,14 +831,15 @@ HRESULT WINAPI CDesktopFolder::Initialize(LPCITEMIDLIST pidl)
 {
     TRACE ("(%p)->(%p)\n", this, pidl);
 
-    return E_NOTIMPL;
+    return E_INVALIDARG;
 }
 
 HRESULT WINAPI CDesktopFolder::GetCurFolder(LPITEMIDLIST * pidl)
 {
     TRACE ("(%p)->(%p)\n", this, pidl);
 
-    if (!pidl) return E_POINTER;
+    if (!pidl) 
+        return E_INVALIDARG; /* xp doesn't have this check and crashes on NULL */
     *pidl = ILClone (pidlRoot);
     return S_OK;
 }
index 73d13cd..d2008c6 100644 (file)
@@ -39,6 +39,22 @@ CDrivesFolderEnum is only responsible for returning the physical items.
 *   IShellFolder implementation
 */
 
+HRESULT CDrivesContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
+                                          HWND hwnd,
+                                          UINT cidl,
+                                          PCUITEMID_CHILD_ARRAY apidl,
+                                          IShellFolder *psf,
+                                          IContextMenu **ppcm)
+{
+    HKEY hKeys[2];
+    UINT cKeys = 0;
+    AddClassKeyToArray(L"Drive", hKeys, &cKeys);
+    AddClassKeyToArray(L"Folder", hKeys, &cKeys);
+
+    /* TODO: also pass a callback here */
+    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
+}
+
 HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
 {
     CComPtr<IDefaultExtractIconInit> initIcon;
@@ -536,7 +552,10 @@ HRESULT WINAPI CDrivesFolder::GetUIObjectOf(HWND hwndOwner,
 
     if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
     {
-        hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)this, NULL, 0, NULL, (IContextMenu**)&pObj);
+        if (_ILIsDrive(apidl[0]))
+            hr = CDrivesContextMenu_CreateInstance(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
+        else
+            hr = m_regFolder->GetUIObjectOf(hwndOwner, cidl, apidl, riid, prgfInOut, &pObj);
     }
     else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
     {
@@ -812,12 +831,6 @@ HRESULT WINAPI CDrivesFolder::GetClassID(CLSID *lpClassId)
  */
 HRESULT WINAPI CDrivesFolder::Initialize(LPCITEMIDLIST pidl)
 {
-    TRACE ("(%p)->(%p)\n", this, pidl);
-
-    if (pidlRoot)
-        SHFree((LPVOID)pidlRoot);
-
-    pidlRoot = ILClone(pidl);
     return S_OK;
 }
 
@@ -829,7 +842,7 @@ HRESULT WINAPI CDrivesFolder::GetCurFolder(LPITEMIDLIST *pidl)
     TRACE("(%p)->(%p)\n", this, pidl);
 
     if (!pidl)
-        return E_POINTER;
+        return E_INVALIDARG; /* xp doesn't have this check and crashes on NULL */
 
     *pidl = ILClone(pidlRoot);
     return S_OK;
index 20bc73b..19a2d74 100644 (file)
@@ -490,7 +490,10 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner,
         if (IsEqualIID(riid, IID_IContextMenu) && (cidl >= 1))
         {
             IContextMenu  * pCm = NULL;
-            hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, 0, NULL, &pCm);
+            HKEY hKeys[16];
+            UINT cKeys = 0;
+            AddFSClassKeysToArray(apidl[0], hKeys, &cKeys);
+            hr = CDefFolderMenu_Create2(pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), NULL, cKeys, hKeys, &pCm);
             pObj = pCm;
         }
         else if (IsEqualIID (riid, IID_IDataObject))
index a6f9452..e595d37 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL (shell);
 
+HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
+                                            HWND hwnd,
+                                            UINT cidl,
+                                            PCUITEMID_CHILD_ARRAY apidl,
+                                            IShellFolder *psf,
+                                            IContextMenu **ppcm)
+{
+    HKEY hKeys[10];
+    UINT cKeys = 0;
+
+    GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
+    if (pGuid)
+    {
+        LPOLESTR pwszCLSID;
+        WCHAR key[60];
+
+        wcscpy(key, L"CLSID\\");
+        HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID);
+        if (hr == S_OK)
+        {
+            wcscpy(&key[6], pwszCLSID);
+            AddClassKeyToArray(key, hKeys, &cKeys);
+        }
+    }
+    AddClassKeyToArray(L"Folder", hKeys, &cKeys);
+
+    return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
+}
+
 HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
 {
     CComPtr<IDefaultExtractIconInit>    initIcon;
@@ -175,13 +204,26 @@ HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot,
 
 HRESULT CRegFolder::GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
 {
+    DWORD dwAttributes = *pdwAttributes;
+
     /* First try to get them from the registry */
-    if (HCR_GetFolderAttributes(pidl, pdwAttributes) && *pdwAttributes)
+    if (!HCR_GetFolderAttributes(pidl, pdwAttributes))
     {
-        return S_OK;
+        /* We couldn't get anything */
+        *pdwAttributes = 0;
     }
 
-    *pdwAttributes &= SFGAO_CANLINK;
+    /* Items have more attributes when on desktop */
+    if (_ILIsDesktop(m_pidlRoot))
+    {
+        *pdwAttributes |= (dwAttributes & (SFGAO_CANLINK|SFGAO_CANDELETE|SFGAO_CANRENAME|SFGAO_HASPROPSHEET));
+    }
+
+    /* In any case, links can be created */
+    if (*pdwAttributes == NULL)
+    {
+        *pdwAttributes |= (dwAttributes & SFGAO_CANLINK);
+    }
     return S_OK;
 }
 
@@ -346,8 +388,20 @@ HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CH
     {
         hr = CGuidItemExtractIcon_CreateInstance(apidl[0], riid, &pObj);
     }
+    else if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
+    {
+        if (!_ILGetGUIDPointer (apidl[0]))
+        {
+            ERR("Got non guid item!\n");
+            return E_FAIL;
+        }
+
+        hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
+    }
     else
+    {
         hr = E_NOINTERFACE;
+    }
 
     *ppvOut = pObj;
     return hr;
index d43c92a..bc373af 100644 (file)
@@ -61,6 +61,8 @@ HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot,
 extern "C"
 BOOL HCR_RegOpenClassIDKey(REFIID riid, HKEY *hkey);
 
+void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys);
+
 static __inline int SHELL32_GUIDToStringA (REFGUID guid, LPSTR str)
 {
     return sprintf(str, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
index 59b4e05..114504f 100644 (file)
@@ -501,6 +501,52 @@ void AddClassKeyToArray(const WCHAR * szClass, HKEY* array, UINT* cKeys)
     *cKeys += 1;
 }
 
+void AddFSClassKeysToArray(PCUITEMID_CHILD pidl, HKEY* array, UINT* cKeys)
+{
+    if (_ILIsValue(pidl))
+    {
+        FileStructW* pFileData = _ILGetFileStructW(pidl);
+        LPWSTR extension = PathFindExtension(pFileData->wszName);
+
+        if (extension)
+        {
+            AddClassKeyToArray(extension, array, cKeys);
+
+            WCHAR wszClass[40], wszClass2[40];
+            DWORD dwSize = sizeof(wszClass);
+            if (RegGetValueW(HKEY_CLASSES_ROOT, extension, NULL, RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
+            {
+                swprintf(wszClass2, L"%s//%s", extension, wszClass);
+
+                AddClassKeyToArray(wszClass, array, cKeys);
+                AddClassKeyToArray(wszClass2, array, cKeys);
+            }
+
+            swprintf(wszClass2, L"SystemFileAssociations//%s", extension);
+            AddClassKeyToArray(wszClass2, array, cKeys);
+
+            if (RegGetValueW(HKEY_CLASSES_ROOT, extension, L"PerceivedType ", RRF_RT_REG_SZ, NULL, wszClass, &dwSize) == ERROR_SUCCESS)
+            {
+                swprintf(wszClass2, L"SystemFileAssociations//%s", wszClass);
+                AddClassKeyToArray(wszClass2, array, cKeys);
+            }
+        }
+
+        AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
+        AddClassKeyToArray(L"*", array, cKeys);
+    }
+    else if (_ILIsFolder(pidl))
+    {
+        AddClassKeyToArray(L"AllFilesystemObjects", array, cKeys);
+        AddClassKeyToArray(L"Directory", array, cKeys);
+        AddClassKeyToArray(L"Folder", array, cKeys);
+    }
+    else
+    {
+        ERR("Got non FS pidl\n");
+    }
+}
+
 /***********************************************************************
  *  SHCreateLinks
  *