[PATCH 3/3] comctl32/listview: Sort using duplicated items pointer array to preserve original order.

Nikolay Sivov nsivov at codeweavers.com
Mon Mar 8 08:44:39 CST 2021


Issue reported by Haoyang Chen.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/comctl32/listview.c | 17 ++++++++++-------
 include/commctrl.h       |  1 +
 2 files changed, 11 insertions(+), 7 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index ee67193ff27..799ec509f33 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -9230,7 +9230,7 @@ static INT LISTVIEW_SetView(LISTVIEW_INFO *infoPtr, DWORD nView)
 
 struct sorting_context
 {
-    LISTVIEW_INFO *infoPtr;
+    HDPA items;
     PFNLVCOMPARE compare_func;
     LPARAM lParam;
 };
@@ -9249,8 +9249,8 @@ static INT WINAPI LISTVIEW_CallBackCompare(LPVOID first, LPVOID second, LPARAM l
 static INT WINAPI LISTVIEW_CallBackCompareEx(LPVOID first, LPVOID second, LPARAM lParam)
 {
     struct sorting_context *context = (struct sorting_context *)lParam;
-    INT first_idx  = DPA_GetPtrIndex( context->infoPtr->hdpaItems, first  );
-    INT second_idx = DPA_GetPtrIndex( context->infoPtr->hdpaItems, second );
+    INT first_idx  = DPA_GetPtrIndex( context->items, first  );
+    INT second_idx = DPA_GetPtrIndex( context->items, second );
 
     return context->compare_func(first_idx, second_idx, context->lParam);
 }
@@ -9272,7 +9272,7 @@ static INT WINAPI LISTVIEW_CallBackCompareEx(LPVOID first, LPVOID second, LPARAM
 static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare,
                                LPARAM lParamSort, BOOL IsEx)
 {
-    HDPA hdpaSubItems;
+    HDPA hdpaSubItems, hdpaItems;
     ITEM_INFO *lpItem;
     LPVOID selectionMarkItem = NULL;
     LPVOID focusedItem = NULL;
@@ -9288,6 +9288,7 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare,
 
     /* if there are 0 or 1 items, there is no need to sort */
     if (infoPtr->nItemCount < 2) return TRUE;
+    if (!(hdpaItems = DPA_Clone(infoPtr->hdpaItems, NULL))) return FALSE;
 
     /* clear selection */
     ranges_clear(infoPtr->selectionRanges);
@@ -9298,13 +9299,15 @@ static BOOL LISTVIEW_SortItems(LISTVIEW_INFO *infoPtr, PFNLVCOMPARE pfnCompare,
     if (infoPtr->nFocusedItem >= 0)
         focusedItem = DPA_GetPtr(infoPtr->hdpaItems, infoPtr->nFocusedItem);
 
-    context.infoPtr = infoPtr;
+    context.items = hdpaItems;
     context.compare_func = pfnCompare;
     context.lParam = lParamSort;
     if (IsEx)
-        DPA_Sort(infoPtr->hdpaItems, LISTVIEW_CallBackCompareEx, (LPARAM)&context);
+        DPA_Sort(hdpaItems, LISTVIEW_CallBackCompareEx, (LPARAM)&context);
     else
-        DPA_Sort(infoPtr->hdpaItems, LISTVIEW_CallBackCompare, (LPARAM)&context);
+        DPA_Sort(hdpaItems, LISTVIEW_CallBackCompare, (LPARAM)&context);
+    DPA_Destroy(infoPtr->hdpaItems);
+    infoPtr->hdpaItems = hdpaItems;
 
     /* restore selection ranges */
     for (i=0; i < infoPtr->nItemCount; i++)
diff --git a/include/commctrl.h b/include/commctrl.h
index 97e2fcc4df0..5614f64a979 100644
--- a/include/commctrl.h
+++ b/include/commctrl.h
@@ -5165,6 +5165,7 @@ typedef PVOID (CALLBACK *PFNDPAMERGE)(UINT,PVOID,PVOID,LPARAM);
 #define DPAM_UNION      0x00000004
 #define DPAM_INTERSECT  0x00000008
 
+HDPA   WINAPI DPA_Clone(const HDPA, HDPA);
 HDPA   WINAPI DPA_Create(INT);
 BOOL   WINAPI DPA_Destroy(HDPA);
 LPVOID WINAPI DPA_DeletePtr(HDPA, INT);
-- 
2.30.1




More information about the wine-devel mailing list