[COMCTL32_WINETEST] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / modules / rostests / winetests / comctl32 / listview.c
index 90fce74..45f2b60 100644 (file)
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "precomp.h"
+#include <stdio.h>
+#include <windows.h>
+#include <commctrl.h>
+
+#include "wine/test.h"
+#include "v6util.h"
+#include "msg.h"
+
+static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
+static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
+static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
+static BOOL (WINAPI *p_TrackMouseEvent)(TRACKMOUSEEVENT *);
 
 enum seq_index {
     PARENT_SEQ_INDEX,
@@ -64,9 +75,23 @@ static BOOL g_disp_A_to_W;
 static NMLVDISPINFOA g_editbox_disp_info;
 /* when this is set focus will be tested on LVN_DELETEITEM */
 static BOOL g_focus_test_LVN_DELETEITEM;
+/* Whether to send WM_KILLFOCUS to the edit control during LVN_ENDLABELEDIT */
+static BOOL g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT;
 
 static HWND subclass_editbox(HWND hwndListview);
 
+static void init_functions(void)
+{
+    HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
+
+#define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
+    X(ImageList_Create);
+    X(ImageList_Destroy);
+    X(ImageList_Add);
+    X(_TrackMouseEvent);
+#undef X
+}
+
 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
 
 static const struct message create_ownerdrawfixed_parent_seq[] = {
@@ -422,6 +447,25 @@ static const struct message parent_list_cd_seq[] = {
     { 0 }
 };
 
+static const struct message listview_end_label_edit[] = {
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ENDLABELEDITA },
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ITEMCHANGING},
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ITEMCHANGED },
+    { WM_NOTIFY,  sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+    { WM_NOTIFY,  sent|id, 0, 0, NM_SETFOCUS },
+    { 0 }
+};
+
+static const struct message listview_end_label_edit_kill_focus[] = {
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ENDLABELEDITA },
+    { WM_COMMAND, sent|id|optional, 0, 0, EN_KILLFOCUS }, /* todo: not sent by wine yet */
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ITEMCHANGING },
+    { WM_NOTIFY,  sent|id, 0, 0, LVN_ITEMCHANGED },
+    { WM_NOTIFY,  sent|id|optional, 0, 0, NM_CUSTOMDRAW }, /* XP */
+    { WM_NOTIFY,  sent|id, 0, 0, NM_SETFOCUS },
+    { 0 }
+};
+
 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
     static LONG defwndproc_counter = 0;
@@ -434,6 +478,7 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
     msg.wParam = wParam;
     msg.lParam = lParam;
     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
+    if (message == WM_COMMAND) msg.id = HIWORD(wParam);
 
     /* log system messages, except for painting */
     if (message < WM_USER &&
@@ -480,24 +525,17 @@ static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LP
               /* always accept new item text */
               NMLVDISPINFOA *di = (NMLVDISPINFOA*)lParam;
               g_editbox_disp_info = *di;
-              trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText ? di->item.pszText : "(null)");
 
               /* edit control still available from this notification */
               edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETEDITCONTROL, 0, 0);
               ok(IsWindow(edit), "expected valid edit control handle\n");
               ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
 
-              return TRUE;
-              }
-          case LVN_BEGINSCROLL:
-          case LVN_ENDSCROLL:
-              {
-              NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
+              if (g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT)
+                  SendMessageA(edit, WM_KILLFOCUS, 0, 0);
 
-              trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
-                                               "BEGIN" : "END", pScroll->dx, pScroll->dy);
+              return TRUE;
               }
-              break;
           case LVN_ITEMCHANGING:
               {
                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
@@ -695,6 +733,21 @@ static HWND create_listview_controlW(DWORD style, HWND parent)
     return hwnd;
 }
 
+static BOOL is_win_xp(void)
+{
+    HWND hwnd, header;
+    BOOL ret;
+
+    hwnd = create_listview_control(LVS_ICON);
+    SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS);
+    header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
+    ret = !IsWindow(header);
+
+    DestroyWindow(hwnd);
+
+    return ret;
+}
+
 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
@@ -842,16 +895,16 @@ static void test_images(void)
     RECT r1, r2;
     static CHAR hello[] = "hello";
 
-    himl = ImageList_Create(40, 40, 0, 4, 4);
+    himl = pImageList_Create(40, 40, 0, 4, 4);
     ok(himl != NULL, "failed to create imagelist\n");
 
     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
     ok(hbmp != NULL, "failed to create bitmap\n");
 
-    r = ImageList_Add(himl, hbmp, 0);
+    r = pImageList_Add(himl, hbmp, 0);
     ok(r == 0, "should be zero\n");
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_OWNERDRAWFIXED,
                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
 
@@ -914,7 +967,7 @@ static void test_checkboxes(void)
                 text2[] = "Text2",
                 text3[] = "Text3";
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
 
@@ -1141,7 +1194,7 @@ static void test_items(void)
     LVITEMA item;
     DWORD r;
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
 
@@ -1398,7 +1451,7 @@ static void test_columns(void)
     CHAR buff[5];
     DWORD rc;
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_LIST,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_LIST,
                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
 
@@ -1413,7 +1466,7 @@ static void test_columns(void)
 
     DestroyWindow(hwnd);
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", LVS_REPORT,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
 
@@ -1513,7 +1566,28 @@ static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam,
     return ret;
 }
 
-static void test_create(void)
+/* Header creation is delayed in classic implementation. */
+#define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__)
+#define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__)
+#define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__)
+static void test_header_presence_(HWND hwnd, BOOL present, int line)
+{
+    HWND header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
+
+    if (present)
+    {
+        ok_(__FILE__, line)(IsWindow(header), "Header should have been created.\n");
+        if (header) /* FIXME: remove when todo's are fixed */
+            ok_(__FILE__, line)(header == GetDlgItem(hwnd, 0), "Dialog item expected.\n");
+    }
+    else
+    {
+        ok_(__FILE__, line)(!IsWindow(header), "Header shouldn't be created.\n");
+        ok_(__FILE__, line)(NULL == GetDlgItem(hwnd, 0), "NULL dialog item expected.\n");
+    }
+}
+
+static void test_create(BOOL is_version_6)
 {
     static const WCHAR testtextW[] = {'t','e','s','t',' ','t','e','x','t',0};
     char buff[16];
@@ -1525,15 +1599,24 @@ static void test_create(void)
     RECT rect;
     WNDCLASSEXA cls;
     DWORD style;
+    ATOM class;
+
+    if (is_win_xp() && is_version_6)
+    {
+        win_skip("Skipping some tests on XP.\n");
+        return;
+    }
 
     cls.cbSize = sizeof(WNDCLASSEXA);
-    ok(GetClassInfoExA(GetModuleHandleA(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
+    r = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls);
+    ok(r, "Failed to get class info.\n");
     listviewWndProc = cls.lpfnWndProc;
     cls.lpfnWndProc = create_test_wndproc;
     cls.lpszClassName = "MyListView32";
-    ok(RegisterClassExA(&cls), "RegisterClassEx failed\n");
+    class = RegisterClassExA(&cls);
+    ok(class, "Failed to register class.\n");
 
-    test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
+    test_create_imagelist = pImageList_Create(16, 16, 0, 5, 10);
     hList = CreateWindowA("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
     ok((HIMAGELIST)SendMessageA(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
@@ -1542,150 +1625,118 @@ static void test_create(void)
     DestroyWindow(hList);
 
     /* header isn't created on LVS_ICON and LVS_LIST styles */
-    hList = CreateWindowA("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
-                           GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
+    TEST_NO_HEADER(hList);
+
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
     col.cx = 100;
     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
     expect(0, r);
+    TEST_HEADER_EXPECTED(hList);
     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
     style = GetWindowLongA(hHeader, GWL_STYLE);
     ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n");
     DestroyWindow(hList);
 
-    hList = CreateWindowA("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
                            GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+    TEST_NO_HEADER(hList);
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
     col.cx = 100;
     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
     expect(0, r);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
-    hList = CreateWindowA("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
                            GetModuleHandleA(NULL), 0);
     ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongPtrA(hList, GWL_STYLE) | LVS_REPORT);
     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
+    TEST_HEADER_EXPECTED(hList);
     ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongA(hList, GWL_STYLE) & ~LVS_REPORT);
     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
-    hList = CreateWindowA("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
                            GetModuleHandleA(NULL), 0);
     ret = SetWindowLongPtrA(hList, GWL_STYLE,
                            (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
-    ret = SetWindowLongPtrA(hList, GWL_STYLE,
-                           (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
+    TEST_HEADER_EXPECTED(hList);
+    ret = SetWindowLongPtrA(hList, GWL_STYLE, (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* LVS_REPORT without WS_VISIBLE */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
+
     /* insert column */
     memset(&col, 0, sizeof(LVCOLUMNA));
     col.mask = LVCF_WIDTH;
     col.cx = 100;
     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
     expect(0, r);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* LVS_REPORT without WS_VISIBLE, try to show it */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
+
     ShowWindow(hList, SW_SHOW);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
                           0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
+    TEST_HEADER_EXPECTED(hList);
     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader), "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
     /* HDS_DRAGDROP set by default */
     ok(GetWindowLongPtrA(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
     DestroyWindow(hList);
 
     /* setting LVS_EX_HEADERDRAGDROP creates header */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
+
     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader) ||
-       broken(!IsWindow(hHeader)), /* 4.7x common controls */
-       "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* setting LVS_EX_GRIDLINES creates header */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
+
     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader) ||
-       broken(!IsWindow(hHeader)), /* 4.7x common controls */
-       "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* setting LVS_EX_FULLROWSELECT creates header */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(IsWindow(hHeader) ||
-       broken(!IsWindow(hHeader)), /* 4.7x common controls */
-       "Header should be created\n");
-    ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
+    TEST_HEADER_EXPECTED(hList);
     DestroyWindow(hList);
 
     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
@@ -1696,21 +1747,19 @@ static void test_create(void)
     DestroyWindow(hList);
 
     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
-    hList = CreateWindowA("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
+    hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
                           GetModuleHandleA(NULL), 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
 
     SetRect(&rect, LVIR_BOUNDS, 1, -10, -10);
     r = SendMessageA(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
+    ok(r == 1, "Unexpected ret value %d.\n", r);
     /* right value contains garbage, probably because header columns are not set up */
-    expect(0, rect.bottom);
-    expect(1, r);
-
-    hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
-    ok(!IsWindow(hHeader), "Header shouldn't be created\n");
-    ok(GetDlgItem(hList, 0) == NULL, "NULL dialog item expected\n");
+    ok(rect.bottom >= 0, "Unexpected rectangle.\n");
 
+todo_wine_if(is_version_6)
+    TEST_NO_HEADER2(hList, is_version_6);
     DestroyWindow(hList);
 
     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
@@ -1736,6 +1785,9 @@ static void test_create(void)
     GetWindowTextA(hList, buff, sizeof(buff));
     ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff);
     DestroyWindow(hList);
+
+    r = UnregisterClassA("MyListView32", NULL);
+    ok(r, "Failed to unregister test class.\n");
 }
 
 static void test_redraw(void)
@@ -1744,6 +1796,7 @@ static void test_redraw(void)
     HDC hdc;
     BOOL res;
     DWORD r;
+    RECT rect;
 
     hwnd = create_listview_control(LVS_REPORT);
     subclass_header(hwnd);
@@ -1801,6 +1854,13 @@ static void test_redraw(void)
 
     ReleaseDC(hwndparent, hdc);
 
+    /* test setting the window style to what it already was */
+    UpdateWindow(hwnd);
+    SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE));
+    GetUpdateRect(hwnd, &rect, FALSE);
+    ok(rect.left == 0 && rect.top == 0 && rect.right == 0 && rect.bottom == 0,
+       "Expected empty update rect, got %s\n", wine_dbgstr_rect(&rect));
+
     DestroyWindow(hwnd);
 }
 
@@ -1834,12 +1894,16 @@ static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM
                 clr = GetBkColor(nmlvcd->nmcd.hdc);
                 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk);
                 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText);
-                todo_wine_if(nmlvcd->iSubItem)
-                    ok(clr == c0ffee, "clr=%.8x\n", clr);
+                if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS))
+                {
+                    todo_wine_if(nmlvcd->iSubItem)
+                        ok(clr == c0ffee, "clr=%.8x\n", clr);
+                }
                 return CDRF_NOTIFYPOSTPAINT;
             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
                 clr = GetBkColor(nmlvcd->nmcd.hdc);
-                todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
+                if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS))
+                    todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
                 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk);
                 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText);
                 return CDRF_DODEFAULT;
@@ -1855,6 +1919,7 @@ static void test_customdraw(void)
 {
     HWND hwnd;
     WNDPROC oldwndproc;
+    LVITEMA item;
 
     hwnd = create_listview_control(LVS_REPORT);
 
@@ -1874,6 +1939,18 @@ static void test_customdraw(void)
     UpdateWindow(hwnd);
     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE);
 
+    /* check colors when item is selected */
+    SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS);
+    item.mask = LVIF_STATE;
+    item.stateMask = LVIS_SELECTED;
+    item.state = LVIS_SELECTED;
+    SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+    ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT, selection", FALSE);
+
     DestroyWindow(hwnd);
 
     hwnd = create_listview_control(LVS_LIST);
@@ -2283,7 +2360,7 @@ static void test_multiselect(void)
     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
     ok(r == 0, "got %d\n", r);
 
-    for (i = 0; i < sizeof(task_list)/sizeof(task_list[0]); i++) {
+    for (i = 0; i < ARRAY_SIZE(task_list); i++) {
         DWORD selected_count;
         LVITEMA item;
 
@@ -2797,7 +2874,7 @@ static void test_subitem_rect(void)
     DestroyWindow(hwnd);
 
     /* try it for non LVS_REPORT style */
-    hwnd = CreateWindowA("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
+    hwnd = CreateWindowA(WC_LISTVIEWA, "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
                          GetModuleHandleA(NULL), 0);
     SetRect(&rect, LVIR_BOUNDS, 1, -10, -10);
     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
@@ -3436,7 +3513,7 @@ static void test_norecompute(void)
     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
     item.iItem = 0;
     item.pszText    = buff;
-    item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+    item.cchTextMax = ARRAY_SIZE(buff);
     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
     expect(TRUE, res);
     ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
@@ -3450,7 +3527,7 @@ static void test_norecompute(void)
     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
     item.iItem = 1;
     item.pszText    = buff;
-    item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+    item.cchTextMax = ARRAY_SIZE(buff);
 
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
@@ -3475,7 +3552,7 @@ static void test_norecompute(void)
     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
     item.iItem = 0;
     item.pszText    = buff;
-    item.cchTextMax = sizeof(buff)/sizeof(CHAR);
+    item.cchTextMax = ARRAY_SIZE(buff);
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
     expect(TRUE, res);
@@ -3726,15 +3803,15 @@ static void test_hittest(void)
     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
-    himl = ImageList_Create(16, 16, 0, 4, 4);
+    himl = pImageList_Create(16, 16, 0, 4, 4);
     ok(himl != NULL, "failed to create imagelist\n");
     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
     ok(hbmp != NULL, "failed to create bitmap\n");
-    r = ImageList_Add(himl, hbmp, 0);
+    r = pImageList_Add(himl, hbmp, 0);
     ok(r == 0, "should be zero\n");
     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
     ok(hbmp != NULL, "failed to create bitmap\n");
-    r = ImageList_Add(himl, hbmp, 0);
+    r = pImageList_Add(himl, hbmp, 0);
     ok(r == 1, "should be one\n");
 
     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
@@ -4016,15 +4093,15 @@ todo_wine
     expect(TRUE, r);
 
     /* state icons */
-    himl = ImageList_Create(16, 16, 0, 2, 2);
+    himl = pImageList_Create(16, 16, 0, 2, 2);
     ok(himl != NULL, "failed to create imagelist\n");
     hbm = CreateBitmap(16, 16, 1, 1, NULL);
     ok(hbm != NULL, "failed to create bitmap\n");
-    r = ImageList_Add(himl, hbm, 0);
+    r = pImageList_Add(himl, hbm, 0);
     expect(0, r);
     hbm = CreateBitmap(16, 16, 1, 1, NULL);
     ok(hbm != NULL, "failed to create bitmap\n");
-    r = ImageList_Add(himl, hbm, 0);
+    r = pImageList_Add(himl, hbm, 0);
     expect(1, r);
 
     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
@@ -4164,7 +4241,7 @@ static void test_editbox(void)
     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
                 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE);
     /* same thing but with valid window */
-    hwndedit = CreateWindowA("Edit", "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20,
+    hwndedit = CreateWindowA(WC_EDITA, "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20,
                 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0);
     flush_sequences(sequences, NUM_MSG_SEQUENCES);
     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit);
@@ -4617,7 +4694,7 @@ static void test_canceleditlabel(void)
     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
     memset(&itema, 0, sizeof(itema));
     itema.pszText = buff;
-    itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
+    itema.cchTextMax = ARRAY_SIZE(buff);
     ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema);
     expect(5, ret);
     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
@@ -4696,9 +4773,9 @@ static void test_getitemspacing(void)
     expect(cy, HIWORD(ret));
 
     /* now try with icons */
-    himl40 = ImageList_Create(40, 40, 0, 4, 4);
+    himl40 = pImageList_Create(40, 40, 0, 4, 4);
     ok(himl40 != NULL, "failed to create imagelist\n");
-    himl80 = ImageList_Create(80, 80, 0, 4, 4);
+    himl80 = pImageList_Create(80, 80, 0, 4, 4);
     ok(himl80 != NULL, "failed to create imagelist\n");
     ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40);
     expect(0, ret);
@@ -4766,7 +4843,7 @@ static void test_getitemspacing(void)
     expect(cy + 40, HIWORD(ret));
 
     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0);
-    ImageList_Destroy(himl80);
+    pImageList_Destroy(himl80);
     DestroyWindow(hwnd);
     /* LVS_SMALLICON */
     hwnd = create_listview_control(LVS_SMALLICON);
@@ -4784,7 +4861,7 @@ static void test_getitemspacing(void)
     expect(cy + 40, HIWORD(ret));
 
     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0);
-    ImageList_Destroy(himl40);
+    pImageList_Destroy(himl40);
     DestroyWindow(hwnd);
     /* LVS_REPORT */
     hwnd = create_listview_control(LVS_REPORT);
@@ -4967,11 +5044,11 @@ static void test_approximate_viewrect(void)
 
     /* LVS_ICON */
     hwnd = create_listview_control(LVS_ICON);
-    himl = ImageList_Create(40, 40, 0, 4, 4);
+    himl = pImageList_Create(40, 40, 0, 4, 4);
     ok(himl != NULL, "failed to create imagelist\n");
     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
     ok(hbmp != NULL, "failed to create bitmap\n");
-    ret = ImageList_Add(himl, hbmp, 0);
+    ret = pImageList_Add(himl, hbmp, 0);
     expect(0, ret);
     ret = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
     expect(0, ret);
@@ -5445,7 +5522,7 @@ static void test_header_notification2(void)
     memset(&itemW, 0, sizeof(itemW));
     itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT;
     itemW.pszText = buffer;
-    itemW.cchTextMax = sizeof(buffer);
+    itemW.cchTextMax = ARRAY_SIZE(buffer);
     ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW);
     expect(1, ret);
 
@@ -5588,7 +5665,7 @@ static void test_createdragimage(void)
 
     himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt);
     ok(himl != NULL, "got %p\n", himl);
-    ImageList_Destroy(himl);
+    pImageList_Destroy(himl);
 
     DestroyWindow(list);
 }
@@ -5613,7 +5690,7 @@ static void test_dispinfo(void)
 
     g_disp_A_to_W = TRUE;
     item.pszText = (char*)buff;
-    item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
+    item.cchTextMax = ARRAY_SIZE(buff);
     ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
     ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
     g_disp_A_to_W = FALSE;
@@ -5703,9 +5780,9 @@ static void test_imagelists(void)
     HIMAGELIST himl1, himl2, himl3;
     LRESULT ret;
 
-    himl1 = ImageList_Create(40, 40, 0, 4, 4);
-    himl2 = ImageList_Create(40, 40, 0, 4, 4);
-    himl3 = ImageList_Create(40, 40, 0, 4, 4);
+    himl1 = pImageList_Create(40, 40, 0, 4, 4);
+    himl2 = pImageList_Create(40, 40, 0, 4, 4);
+    himl3 = pImageList_Create(40, 40, 0, 4, 4);
     ok(himl1 != NULL, "Failed to create imagelist\n");
     ok(himl2 != NULL, "Failed to create imagelist\n");
     ok(himl3 != NULL, "Failed to create imagelist\n");
@@ -5938,7 +6015,7 @@ static void test_oneclickactivate(void)
     INT r;
     POINT orig_pos;
 
-    hwnd = CreateWindowExA(0, "SysListView32", "foo", WS_VISIBLE|WS_CHILD|LVS_LIST,
+    hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", WS_VISIBLE|WS_CHILD|LVS_LIST,
             10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
     ok(hwnd != NULL, "failed to create listview window\n");
     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_ONECLICKACTIVATE);
@@ -5971,7 +6048,7 @@ static void test_oneclickactivate(void)
 
     track.cbSize = sizeof(track);
     track.dwFlags = TME_QUERY;
-    _TrackMouseEvent(&track);
+    p_TrackMouseEvent(&track);
     ok(track.hwndTrack == hwnd, "hwndTrack != hwnd\n");
     ok(track.dwFlags == TME_LEAVE, "dwFlags = %x\n", track.dwFlags);
 
@@ -6132,7 +6209,7 @@ static void test_state_image(void)
     };
     int i;
 
-    for (i = 0; i < sizeof(styles)/sizeof(styles[0]); i++)
+    for (i = 0; i < ARRAY_SIZE(styles); i++)
     {
         static char text[] = "Item";
         static char subtext[] = "Subitem";
@@ -6146,16 +6223,17 @@ static void test_state_image(void)
         insert_column(hwnd, 0);
         insert_column(hwnd, 1);
 
-        item.mask = LVIF_TEXT;
+        item.mask = LVIF_TEXT | LVIF_PARAM;
         item.iItem = 0;
         item.iSubItem = 0;
         item.pszText = text;
+        item.lParam = 123456;
         r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
         ok(r == 0, "Failed to insert an item.\n");
 
         item.mask = LVIF_STATE;
-        item.state = INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED;
-        item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED;
+        item.state = INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED;
+        item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED | LVIS_FOCUSED;
         item.iItem = 0;
         item.iSubItem = 0;
         r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
@@ -6168,27 +6246,49 @@ static void test_state_image(void)
         r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
         ok(r, "Failed to set subitem text.\n");
 
-        item.mask = LVIF_STATE;
-        item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED;
+        item.mask = LVIF_STATE | LVIF_PARAM;
+        item.stateMask = ~0u;
         item.state = 0;
         item.iItem = 0;
         item.iSubItem = 0;
+        item.lParam = 0;
         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
         ok(r, "Failed to get item state.\n");
-        ok(item.state == (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED), "Unexpected item state %#x.\n", item.state);
+        ok(item.state == (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED),
+            "Unexpected item state %#x.\n", item.state);
+        ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
 
-        item.mask = LVIF_STATE;
-        item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED;
+        item.mask = 0;
+        item.stateMask = ~0u;
         item.state = INDEXTOSTATEIMAGEMASK(2);
         item.iItem = 0;
         item.iSubItem = 1;
         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
         ok(r, "Failed to get subitem state.\n");
-    todo_wine
+        ok(item.state == INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item.state);
+
+        item.mask = LVIF_STATE | LVIF_PARAM;
+        item.stateMask = ~0u;
+        item.state = INDEXTOSTATEIMAGEMASK(2);
+        item.iItem = 0;
+        item.iSubItem = 1;
+        item.lParam = 0;
+        r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
+        ok(r, "Failed to get subitem state.\n");
         ok(item.state == 0, "Unexpected state %#x.\n", item.state);
+        ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
 
         item.mask = LVIF_STATE;
-        item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED;
+        item.stateMask = LVIS_FOCUSED;
+        item.state = 0;
+        item.iItem = 0;
+        item.iSubItem = 1;
+        r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
+        ok(r, "Failed to get subitem state.\n");
+        ok(item.state == 0, "Unexpected state %#x.\n", item.state);
+
+        item.mask = LVIF_STATE;
+        item.stateMask = ~0u;
         item.state = INDEXTOSTATEIMAGEMASK(2);
         item.iItem = 0;
         item.iSubItem = 2;
@@ -6210,25 +6310,257 @@ static void test_state_image(void)
     }
 }
 
-START_TEST(listview)
+static void test_LVSCW_AUTOSIZE(void)
 {
-    HMODULE hComctl32;
-    BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
+    int width, width2;
+    HWND hwnd;
+    BOOL ret;
 
-    ULONG_PTR ctx_cookie;
-    HANDLE hCtx;
+    hwnd = create_listview_control(LVS_REPORT);
+    ok(hwnd != NULL, "failed to create a listview window\n");
+
+    insert_column(hwnd, 0);
+    insert_column(hwnd, 1);
+    insert_item(hwnd, 0);
+
+    ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
+    ok(ret, "Failed to set column width.\n");
+
+    width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+    ok(width > 0, "Unexpected column width %d.\n", width);
+
+    /* Turn on checkboxes. */
+    ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
+    ok(ret == 0, "Unexpected previous extended style.\n");
+
+    ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
+    ok(ret, "Failed to set column width.\n");
+
+    width2 = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+    ok(width2 > 0, "Unexpected column width %d.\n", width2);
+    ok(width2 > width, "Expected increased column width.\n");
+
+    /* Turn off checkboxes. */
+    ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
+    ok(ret == LVS_EX_CHECKBOXES, "Unexpected previous extended style.\n");
+
+    ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
+    ok(ret, "Failed to set column width.\n");
+
+    width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
+    ok(width > 0, "Unexpected column width %d.\n", width2);
+    ok(width2 > width, "Expected reduced column width.\n");
+
+    DestroyWindow(hwnd);
+}
+
+static void test_LVN_ENDLABELEDIT(void)
+{
+    WCHAR text[] = {'l','a','l','a',0};
+    HWND hwnd, hwndedit;
+    LVITEMW item = {0};
+    DWORD ret;
+
+    hwnd = create_listview_control(LVS_REPORT | LVS_EDITLABELS);
+
+    insert_column(hwnd, 0);
+
+    item.mask = LVIF_TEXT;
+    item.pszText = text;
+    SendMessageW(hwnd, LVM_INSERTITEMW, 0, (LPARAM)&item);
+
+    /* Test normal editing */
+    SetFocus(hwnd);
+    hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+    ok(hwndedit != NULL, "Failed to get edit control.\n");
+
+    ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test");
+    ok(ret, "Failed to set edit text.\n");
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+    ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+    ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit, "Label edit", FALSE);
+
+    /* Test editing with kill focus */
+    SetFocus(hwnd);
+    hwndedit = (HWND)SendMessageW(hwnd, LVM_EDITLABELW, 0, 0);
+    ok(hwndedit != NULL, "Failed to get edit control.\n");
+
+    ret = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)"test2");
+    ok(ret, "Failed to set edit text.\n");
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+    g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = TRUE;
+    ret = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
+    g_WM_KILLFOCUS_on_LVN_ENDLABELEDIT = FALSE;
+
+    ok_sequence(sequences, PARENT_SEQ_INDEX, listview_end_label_edit_kill_focus,
+            "Label edit, kill focus", FALSE);
+    ok(GetFocus() == hwnd, "Unexpected focused window.\n");
+
+    flush_sequences(sequences, NUM_MSG_SEQUENCES);
+
+    DestroyWindow(hwnd);
+}
+
+static LRESULT CALLBACK create_item_height_wndproc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+    if (msg == WM_CREATE)
+        return 0;
 
-    hComctl32 = GetModuleHandleA("comctl32.dll");
-    pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
-    if (pInitCommonControlsEx)
+    return CallWindowProcA(listviewWndProc, hwnd, msg, wParam, lParam);
+}
+
+static void test_LVM_GETCOUNTPERPAGE(void)
+{
+    static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
+    unsigned int i, j;
+    WNDCLASSEXA cls;
+    ATOM class;
+    HWND hwnd;
+    BOOL ret;
+
+    cls.cbSize = sizeof(WNDCLASSEXA);
+    ret = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls);
+    ok(ret, "Failed to get class info.\n");
+    listviewWndProc = cls.lpfnWndProc;
+    cls.lpfnWndProc = create_item_height_wndproc;
+    cls.lpszClassName = "CountPerPageClass";
+    class = RegisterClassExA(&cls);
+    ok(class, "Failed to register class.\n");
+
+    for (i = 0; i < ARRAY_SIZE(styles); i++)
     {
-        INITCOMMONCONTROLSEX iccex;
-        iccex.dwSize = sizeof(iccex);
-        iccex.dwICC  = ICC_LISTVIEW_CLASSES;
-        pInitCommonControlsEx(&iccex);
+        static char text[] = "item text";
+        LVITEMA item = { 0 };
+        UINT count, count2;
+
+        hwnd = create_listview_control(styles[i]);
+        ok(hwnd != NULL, "Failed to create listview window.\n");
+
+        count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+        if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT)
+            ok(count > 0 || broken(styles[i] == LVS_LIST && count == 0), "%u: unexpected count %u.\n", i, count);
+        else
+            ok(count == 0, "%u: unexpected count %u.\n", i, count);
+
+        for (j = 0; j < 10; j++)
+        {
+            item.mask = LVIF_TEXT;
+            item.pszText = text;
+            SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
+        }
+
+        count2 = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+        if (styles[i] == LVS_LIST || styles[i] == LVS_REPORT)
+            ok(count == count2, "%u: unexpected count %u.\n", i, count2);
+        else
+            ok(count2 == 10, "%u: unexpected count %u.\n", i, count2);
+
+        DestroyWindow(hwnd);
+
+        hwnd = CreateWindowA("CountPerPageClass", "Test", WS_VISIBLE | styles[i], 0, 0, 100, 100, NULL, NULL,
+            GetModuleHandleA(NULL), 0);
+        ok(hwnd != NULL, "Failed to create a window.\n");
+
+        count = SendMessageA(hwnd, LVM_GETCOUNTPERPAGE, 0, 0);
+        ok(count == 0, "%u: unexpected count %u.\n", i, count);
+
+        DestroyWindow(hwnd);
     }
-    else
-        InitCommonControls();
+
+    ret = UnregisterClassA("CountPerPageClass", NULL);
+    ok(ret, "Failed to unregister test class.\n");
+}
+
+static void test_item_state_change(void)
+{
+    static const DWORD styles[] = { LVS_ICON, LVS_LIST, LVS_REPORT, LVS_SMALLICON };
+    LVITEMA item;
+    HWND hwnd;
+    DWORD res;
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(styles); i++)
+    {
+        hwnd = create_listview_control(styles[i]);
+
+        insert_item(hwnd, 0);
+
+        /* LVM_SETITEMSTATE with mask */
+        memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
+        memset(&item, 0, sizeof(item));
+        item.mask = LVIF_STATE;
+        item.stateMask = LVIS_SELECTED;
+        item.state = LVIS_SELECTED;
+        res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
+        ok(res, "Failed to set item state.\n");
+
+        ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
+        ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
+        ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
+        ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
+        ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
+        ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
+
+        /* LVM_SETITEMSTATE 0 mask */
+        memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
+        memset(&item, 0, sizeof(item));
+        item.stateMask = LVIS_SELECTED;
+        item.state = 0;
+        res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
+        ok(res, "Failed to set item state.\n");
+
+        ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
+        ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
+        ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
+        ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
+        ok(g_nmlistview.uOldState == LVIS_SELECTED, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
+        ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
+
+        /* LVM_SETITEM changes state */
+        memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
+        memset(&item, 0, sizeof(item));
+        item.stateMask = LVIS_SELECTED;
+        item.state = LVIS_SELECTED;
+        item.mask = LVIF_STATE;
+        res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
+        ok(res, "Failed to set item.\n");
+
+        ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
+        ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
+        ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
+        ok(g_nmlistview.uNewState == LVIS_SELECTED, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
+        ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
+        ok(g_nmlistview.uChanged == LVIF_STATE, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
+
+        /* LVM_SETITEM no state changes */
+        memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
+        memset(&item, 0, sizeof(item));
+        item.lParam = 11;
+        item.mask = LVIF_PARAM;
+        res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
+        ok(res, "Failed to set item.\n");
+
+        ok(g_nmlistview.iItem == item.iItem, "Unexpected item %d.\n", g_nmlistview.iItem);
+        ok(g_nmlistview.iSubItem == item.iSubItem, "Unexpected subitem %d.\n", g_nmlistview.iSubItem);
+        ok(g_nmlistview.lParam == item.lParam, "Unexpected lParam.\n");
+        ok(g_nmlistview.uNewState == 0, "Unexpected new state %#x.\n", g_nmlistview.uNewState);
+        ok(g_nmlistview.uOldState == 0, "Unexpected old state %#x.\n", g_nmlistview.uOldState);
+        ok(g_nmlistview.uChanged == LVIF_PARAM, "Unexpected change mask %#x.\n", g_nmlistview.uChanged);
+
+        DestroyWindow(hwnd);
+    }
+}
+
+START_TEST(listview)
+{
+    ULONG_PTR ctx_cookie;
+    HANDLE hCtx;
+
+    init_functions();
 
     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
 
@@ -6242,7 +6574,7 @@ START_TEST(listview)
     test_images();
     test_checkboxes();
     test_items();
-    test_create();
+    test_create(FALSE);
     test_redraw();
     test_customdraw();
     test_icon_spacing();
@@ -6283,6 +6615,10 @@ START_TEST(listview)
     test_oneclickactivate();
     test_callback_mask();
     test_state_image();
+    test_LVSCW_AUTOSIZE();
+    test_LVN_ENDLABELEDIT();
+    test_LVM_GETCOUNTPERPAGE();
+    test_item_state_change();
 
     if (!load_v6_module(&ctx_cookie, &hCtx))
     {
@@ -6290,6 +6626,8 @@ START_TEST(listview)
         return;
     }
 
+    init_functions();
+
     /* comctl32 version 6 tests start here */
     test_get_set_view();
     test_canceleditlabel();
@@ -6304,6 +6642,7 @@ START_TEST(listview)
     test_images();
     test_checkboxes();
     test_items();
+    test_create(TRUE);
     test_color();
     test_columns();
     test_sorting();
@@ -6321,6 +6660,10 @@ START_TEST(listview)
     test_LVM_REDRAWITEMS();
     test_oneclickactivate();
     test_state_image();
+    test_LVSCW_AUTOSIZE();
+    test_LVN_ENDLABELEDIT();
+    test_LVM_GETCOUNTPERPAGE();
+    test_item_state_change();
 
     unload_v6_module(ctx_cookie, hCtx);