[PATCH] comctl32/listview: Fix the listview sorting error.
Haoyang Chen
chenhaoyang at uniontech.com
Sun Mar 7 21:22:40 CST 2021
The original sequence may be stored in lparam. During the sorting process,
this sequence is out-of-order, but lparam remains unchanged.
Signed-off-by: Haoyang Chen <chenhaoyang at uniontech.com>
---
dlls/comctl32/dpa.c | 13 ++++++--
dlls/comctl32/tests/listview.c | 59 ++++++++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 2 deletions(-)
diff --git a/dlls/comctl32/dpa.c b/dlls/comctl32/dpa.c
index 36b3a422e8c..69e9d0a33bb 100644
--- a/dlls/comctl32/dpa.c
+++ b/dlls/comctl32/dpa.c
@@ -818,8 +818,17 @@ BOOL WINAPI DPA_Sort (HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
- DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
- pfnCompare, lParam);
+ {
+ LPVOID *ptrs = HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
+ hdpa->nItemCount * sizeof(LPVOID));
+ if (!ptrs)
+ return FALSE;
+ memcpy(ptrs, hdpa->ptrs, hdpa->nItemCount * sizeof(LPVOID));
+ DPA_QuickSort (ptrs, 0, hdpa->nItemCount - 1, pfnCompare, lParam);
+
+ memcpy(hdpa->ptrs, ptrs, hdpa->nItemCount * sizeof(LPVOID));
+ HeapFree (hdpa->hHeap, 0, ptrs);
+ }
return TRUE;
}
diff --git a/dlls/comctl32/tests/listview.c b/dlls/comctl32/tests/listview.c
index e95b81f5bb1..7b036a9f6c1 100644
--- a/dlls/comctl32/tests/listview.c
+++ b/dlls/comctl32/tests/listview.c
@@ -2921,6 +2921,28 @@ static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lPara
return (first > second ? 1 : -1);
}
+static INT WINAPI test_CallBackCompare1(LPARAM first, LPARAM second, LPARAM lParam)
+{
+ CHAR str1[5];
+ CHAR str2[5];
+ INT r;
+ HWND hwnd = (HWND)lParam;
+ LV_ITEMA item = {0};
+
+ if (first == second) return 0;
+ item.cchTextMax = 5;
+ item.iSubItem = 0;
+ item.pszText = str1;
+ r = SendMessageA(hwnd, LVM_GETITEMTEXTA, first, (LPARAM)&item);
+ expect(TRUE, r);
+
+ item.pszText = str2;
+ r = SendMessageA(hwnd, LVM_GETITEMTEXTA, second, (LPARAM)&item);
+ expect(TRUE, r);
+
+ return atoi(str1) > atoi(str2) ? 1 : -1;
+}
+
static void test_sorting(void)
{
HWND hwnd;
@@ -2929,6 +2951,9 @@ static void test_sorting(void)
LONG_PTR style;
static CHAR names[][5] = {"A", "B", "C", "D", "0"};
CHAR buff[10];
+ static CHAR before_sort_array[][5] = {"6","3","1","4","2"};
+ static CHAR after_sort_arary[][5] = {"1","2","3","4","6"};
+ INT i;
hwnd = create_listview_control(LVS_REPORT);
ok(hwnd != NULL, "failed to create a listview window\n");
@@ -2979,6 +3004,40 @@ static void test_sorting(void)
DestroyWindow(hwnd);
+ hwnd = create_listview_control(LVS_REPORT);
+ ok(hwnd != NULL, "failed to create a listview window\n");
+
+ item.mask = LVIF_PARAM | LVIF_TEXT;
+ item.iSubItem = 0;
+ item.cchTextMax = 5;
+
+ for (i = 0; i < sizeof(before_sort_array)/5; i++)
+ {
+ item.iItem = i;
+ item.lParam = i;
+ item.pszText = &before_sort_array[i][0];
+ r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+ expect(i, r);
+ }
+
+ r = SendMessageA(hwnd, LVM_SORTITEMS, (WPARAM)(LPARAM)hwnd, (LPARAM)test_CallBackCompare1);
+ expect(TRUE, r);
+
+ for (i = 0; i < sizeof(after_sort_arary)/5; i++)
+ {
+ CHAR str[5];
+ item.iItem = i;
+ item.cchTextMax = 5;
+ item.iSubItem = 0;
+ item.pszText = str;
+ r = SendMessageA(hwnd, LVM_GETITEMTEXTA, i, (LPARAM)&item);
+ expect(TRUE, r);
+
+ expect(0, strcmp(str,&after_sort_arary[i][0]));
+ }
+
+ DestroyWindow(hwnd);
+
/* switch to LVS_SORTASCENDING when some items added */
hwnd = create_listview_control(LVS_REPORT);
ok(hwnd != NULL, "failed to create a listview window\n");
--
2.20.1
More information about the wine-devel
mailing list