[SHELL32]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 4 Nov 2016 23:11:29 +0000 (23:11 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Fri, 4 Nov 2016 23:11:29 +0000 (23:11 +0000)
- Implement comparing child items in CompareIDs method of our IShellFolder immplementation in shell32 as this is the expected behaviour according to tests and documentation.
- This was removed after each folder got its own implementation (we used a single one from wine that did handle it).
May fix CORE-12106.

svn path=/trunk/; revision=73128

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 baa8eae..73d13cd 100644 (file)
@@ -358,6 +358,8 @@ HRESULT WINAPI CDrivesFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcRes
 
 HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
 {
+    HRESULT hres;
+
     if (!pidl1 || !pidl2)
     {
         ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam, pidl1, pidl2);
@@ -365,7 +367,7 @@ HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1
     }
 
     if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
-        m_regFolder->CompareIDs(lParam, pidl1, pidl2);
+        return m_regFolder->CompareIDs(lParam, pidl1, pidl2);
 
     if (!_ILIsDrive(pidl1) || !_ILIsDrive(pidl2) || LOWORD(lParam) >= MYCOMPUTERSHELLVIEWCOLUMNS)
         return E_INVALIDARG;
@@ -379,10 +381,12 @@ HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1
         case 0:        /* name */
         {
             result = stricmp(pszDrive1, pszDrive2);
-            return MAKE_COMPARE_HRESULT(result);
+            hres = MAKE_COMPARE_HRESULT(result);
+            break;
         }
         case 1:        /* Type */
         {
+            /* We want to return immediately because SHELL32_CompareDetails also compares children. */
             return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
         }
         case 2:       /* Size */
@@ -406,10 +410,17 @@ HRESULT WINAPI CDrivesFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1
             else /* Size available */
                 Diff.QuadPart = Drive1Available.QuadPart - Drive2Available.QuadPart;
 
-            return MAKE_COMPARE_HRESULT(Diff.QuadPart);
+            hres = MAKE_COMPARE_HRESULT(Diff.QuadPart);
+            break;
         }
+        default:
+            return E_INVALIDARG;
     }
-    return E_INVALIDARG;
+
+    if (HRESULT_CODE(hres) == 0)
+        return SHELL32_CompareChildren(this, lParam, pidl1, pidl2);
+
+    return hres;
 }
 
 /**************************************************************************
index 2406fef..20bc73b 100644 (file)
@@ -344,6 +344,10 @@ HRESULT WINAPI CFSFolder::CompareIDs(LPARAM lParam,
         case 4: /* Attributes */
             return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
     }
+
+    if (result == 0)
+        return SHELL32_CompareChildren(this, lParam, pidl1, pidl2);
+
     return MAKE_COMPARE_HRESULT(result);
 }
 
index df9e1d1..1ef83a4 100644 (file)
@@ -282,21 +282,24 @@ HRESULT WINAPI CRegFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, P
         return E_INVALIDARG;
     }
 
-    BOOL bIsGuidFolder1 = _ILIsSpecialFolder(pidl1);
-    BOOL bIsGuidFolder2 = _ILIsSpecialFolder(pidl2);
+    GUID const *clsid1 = _ILGetGUIDPointer (pidl1);
+    GUID const *clsid2 = _ILGetGUIDPointer (pidl2);
 
-    if (!bIsGuidFolder1 && !bIsGuidFolder2)
+    if (!clsid1 && !clsid2)
     {
         ERR("Got no guid pidl!\n");
         return E_INVALIDARG;
     }
-    else if (bIsGuidFolder1 && bIsGuidFolder2)
+    else if (clsid1 && clsid2)
     {
+        if (memcmp(clsid1, clsid2, sizeof(GUID)) == 0)
+            return SHELL32_CompareChildren(this, lParam, pidl1, pidl2);
+
         return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
     }
 
     /* Guid folders come first compared to everything else */
-    return MAKE_COMPARE_HRESULT(bIsGuidFolder1 ? -1 : 1);
+    return MAKE_COMPARE_HRESULT(clsid1 ? -1 : 1);
 }
 
 HRESULT WINAPI CRegFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
index a8543e6..d43c92a 100644 (file)
@@ -53,6 +53,8 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
 
 HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
 
+HRESULT SHELL32_CompareChildren(IShellFolder2* psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2);
+
 HRESULT SHELL32_CoCreateInitSF (LPCITEMIDLIST pidlRoot, LPCWSTR pathRoot,
                 LPCITEMIDLIST pidlChild, const GUID* clsid, int csidl, REFIID riid, LPVOID *ppvOut);
                 
index cf1987c..be18467 100644 (file)
@@ -435,6 +435,29 @@ HRESULT SHELL32_GetFSItemAttributes(IShellFolder * psf, LPCITEMIDLIST pidl, LPDW
     return S_OK;
 }
 
+HRESULT SHELL32_CompareChildren(IShellFolder2* psf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+{
+    PUIDLIST_RELATIVE nextpidl1 = ILGetNext (pidl1);
+    PUIDLIST_RELATIVE nextpidl2 = ILGetNext (pidl2);
+
+    bool isEmpty1 = _ILIsDesktop(nextpidl1);
+    bool isEmpty2 = _ILIsDesktop(nextpidl2);
+    if (isEmpty1 || isEmpty2)
+        return MAKE_COMPARE_HRESULT(isEmpty2 - isEmpty1);
+
+    PITEMID_CHILD firstpidl = ILCloneFirst (pidl1);
+    if (!firstpidl)
+        return E_OUTOFMEMORY;
+
+    CComPtr<IShellFolder> psf2;
+    HRESULT hr = psf->BindToObject(firstpidl, 0, IID_PPV_ARG(IShellFolder, &psf2));
+    ILFree(firstpidl);
+    if (FAILED(hr))
+        return MAKE_COMPARE_HRESULT(0);
+
+    return psf2->CompareIDs(lParam, nextpidl1, nextpidl2);
+}
+
 HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
 {
     SHELLDETAILS sd;
@@ -458,6 +481,8 @@ HRESULT SHELL32_CompareDetails(IShellFolder2* isf, LPARAM lParam, LPCITEMIDLIST
         return MAKE_COMPARE_HRESULT(1);
 
     int ret = wcsicmp(wszItem1, wszItem2);
+    if (ret == 0)
+        return SHELL32_CompareChildren(isf, lParam, pidl1, pidl2);
 
     return MAKE_COMPARE_HRESULT(ret);
 }