comctl32/dpa: Check for DPA_LoadStream() presence. Merge original test function with...
[wine] / dlls / comctl32 / tests / listview.c
1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdio.h>
23 #include <windows.h>
24 #include <commctrl.h>
25
26 #include "wine/test.h"
27 #include "v6util.h"
28 #include "msg.h"
29
30 #define PARENT_SEQ_INDEX       0
31 #define PARENT_FULL_SEQ_INDEX  1
32 #define LISTVIEW_SEQ_INDEX     2
33 #define EDITBOX_SEQ_INDEX      3
34 #define NUM_MSG_SEQUENCES      4
35
36 #define LISTVIEW_ID 0
37 #define HEADER_ID   1
38
39 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
40 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
41        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
42
43 static const WCHAR testparentclassW[] =
44     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
45
46 HWND hwndparent, hwndparentW;
47 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
48 BOOL blockEdit;
49 /* dumps LVN_ITEMCHANGED message data */
50 static BOOL g_dump_itemchanged;
51 /* format reported to control:
52    -1 falls to defproc, anything else returned */
53 INT  notifyFormat;
54 /* indicates we're running < 5.80 version */
55 BOOL g_is_below_5;
56
57 static HWND subclass_editbox(HWND hwndListview);
58
59 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
60
61 static const struct message create_ownerdrawfixed_parent_seq[] = {
62     { WM_NOTIFYFORMAT, sent },
63     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
64     { WM_MEASUREITEM, sent },
65     { WM_PARENTNOTIFY, sent },
66     { 0 }
67 };
68
69 static const struct message redraw_listview_seq[] = {
70     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
71     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
72     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
73     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
74     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
75     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
77     { 0 }
78 };
79
80 static const struct message listview_icon_spacing_seq[] = {
81     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
84     { 0 }
85 };
86
87 static const struct message listview_color_seq[] = {
88     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
89     { LVM_GETBKCOLOR,     sent },
90     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
91     { LVM_GETTEXTCOLOR,   sent },
92     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
93     { LVM_GETTEXTBKCOLOR, sent },
94
95     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
96     { LVM_GETBKCOLOR,     sent },
97     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
98     { LVM_GETTEXTCOLOR,   sent },
99     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
100     { LVM_GETTEXTBKCOLOR, sent },
101
102     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
103     { LVM_GETBKCOLOR,     sent },
104     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
105     { LVM_GETTEXTCOLOR,   sent },
106     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
107     { LVM_GETTEXTBKCOLOR, sent },
108
109     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
110     { LVM_GETBKCOLOR,     sent },
111     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
112     { LVM_GETTEXTCOLOR,   sent },
113     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
114     { LVM_GETTEXTBKCOLOR, sent },
115     { 0 }
116 };
117
118 static const struct message listview_item_count_seq[] = {
119     { LVM_GETITEMCOUNT,   sent },
120     { LVM_INSERTITEM,     sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_GETITEMCOUNT,   sent },
124     { LVM_DELETEITEM,     sent|wparam, 2 },
125     { WM_NCPAINT,         sent|optional },
126     { WM_ERASEBKGND,      sent|optional },
127     { LVM_GETITEMCOUNT,   sent },
128     { LVM_DELETEALLITEMS, sent },
129     { LVM_GETITEMCOUNT,   sent },
130     { LVM_INSERTITEM,     sent },
131     { LVM_INSERTITEM,     sent },
132     { LVM_GETITEMCOUNT,   sent },
133     { LVM_INSERTITEM,     sent },
134     { LVM_GETITEMCOUNT,   sent },
135     { 0 }
136 };
137
138 static const struct message listview_itempos_seq[] = {
139     { LVM_INSERTITEM,      sent },
140     { LVM_INSERTITEM,      sent },
141     { LVM_INSERTITEM,      sent },
142     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
143     { WM_NCPAINT,          sent|optional },
144     { WM_ERASEBKGND,       sent|optional },
145     { LVM_GETITEMPOSITION, sent|wparam,        1 },
146     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
147     { LVM_GETITEMPOSITION, sent|wparam,        2 },
148     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
149     { LVM_GETITEMPOSITION, sent|wparam,        0 },
150     { 0 }
151 };
152
153 static const struct message listview_ownerdata_switchto_seq[] = {
154     { WM_STYLECHANGING,    sent },
155     { WM_STYLECHANGED,     sent },
156     { 0 }
157 };
158
159 static const struct message listview_getorderarray_seq[] = {
160     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
161     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
162     { 0 }
163 };
164
165 static const struct message empty_seq[] = {
166     { 0 }
167 };
168
169 static const struct message forward_erasebkgnd_parent_seq[] = {
170     { WM_ERASEBKGND, sent },
171     { 0 }
172 };
173
174 static const struct message ownderdata_select_focus_parent_seq[] = {
175     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
176     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
177     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
178     { 0 }
179 };
180
181 static const struct message ownerdata_setstate_all_parent_seq[] = {
182     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
183     { 0 }
184 };
185
186 static const struct message ownerdata_defocus_all_parent_seq[] = {
187     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
188     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
189     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
190     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
191     { 0 }
192 };
193
194 static const struct message ownerdata_deselect_all_parent_seq[] = {
195     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
196     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
197     { 0 }
198 };
199
200 static const struct message select_all_parent_seq[] = {
201     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
202     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
203
204     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
205     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
206
207     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
208     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
209
210     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
211     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
212
213     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
214     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
215     { 0 }
216 };
217
218 static const struct message textcallback_set_again_parent_seq[] = {
219     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
220     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
221     { 0 }
222 };
223
224 static const struct message single_getdispinfo_parent_seq[] = {
225     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
226     { 0 }
227 };
228
229 static const struct message getitemposition_seq1[] = {
230     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
231     { 0 }
232 };
233
234 static const struct message getitemposition_seq2[] = {
235     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
236     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
237     { 0 }
238 };
239
240 static const struct message editbox_create_pos[] = {
241     /* sequence sent after LVN_BEGINLABELEDIT */
242     /* next two are 4.7x specific */
243     { WM_WINDOWPOSCHANGING, sent },
244     { WM_WINDOWPOSCHANGED, sent|optional },
245
246     { WM_WINDOWPOSCHANGING, sent|optional },
247     { WM_NCCALCSIZE, sent },
248     { WM_WINDOWPOSCHANGED, sent },
249     { WM_MOVE, sent|defwinproc },
250     { WM_SIZE, sent|defwinproc },
251     /* the rest is todo, skipped in 4.7x */
252     { WM_WINDOWPOSCHANGING, sent|optional },
253     { WM_WINDOWPOSCHANGED, sent|optional },
254     { 0 }
255 };
256
257 static const struct message scroll_parent_seq[] = {
258     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
259     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
260     { 0 }
261 };
262
263 static const struct message setredraw_seq[] = {
264     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
265     { 0 }
266 };
267
268 static const struct message lvs_ex_transparentbkgnd_seq[] = {
269     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
270     { 0 }
271 };
272
273 struct subclass_info
274 {
275     WNDPROC oldproc;
276 };
277
278 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
279 {
280     static LONG defwndproc_counter = 0;
281     LRESULT ret;
282     struct message msg;
283
284     msg.message = message;
285     msg.flags = sent|wparam|lparam;
286     if (defwndproc_counter) msg.flags |= defwinproc;
287     msg.wParam = wParam;
288     msg.lParam = lParam;
289     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
290
291     /* log system messages, except for painting */
292     if (message < WM_USER &&
293         message != WM_PAINT &&
294         message != WM_ERASEBKGND &&
295         message != WM_NCPAINT &&
296         message != WM_NCHITTEST &&
297         message != WM_GETTEXT &&
298         message != WM_GETICON &&
299         message != WM_DEVICECHANGE)
300     {
301         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
302
303         add_message(sequences, PARENT_SEQ_INDEX, &msg);
304     }
305     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
306
307     switch (message)
308     {
309       case WM_NOTIFY:
310       {
311           switch (((NMHDR*)lParam)->code)
312           {
313           case LVN_BEGINLABELEDIT:
314               /* subclass edit box */
315               if (!blockEdit)
316                   subclass_editbox(((NMHDR*)lParam)->hwndFrom);
317
318               return blockEdit;
319
320           case LVN_ENDLABELEDIT:
321               /* always accept new item text */
322               return TRUE;
323           case LVN_BEGINSCROLL:
324           case LVN_ENDSCROLL:
325               {
326               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
327
328               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
329                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
330               }
331               break;
332           case LVN_ITEMCHANGED:
333               if (g_dump_itemchanged)
334               {
335                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
336                   trace("LVN_ITEMCHANGED: item=%d,new=%x,old=%x,changed=%x\n",
337                          nmlv->iItem, nmlv->uNewState, nmlv->uOldState, nmlv->uChanged);
338               }
339               break;
340           }
341           break;
342       }
343       case WM_NOTIFYFORMAT:
344       {
345           /* force to return format */
346           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
347           break;
348       }
349     }
350
351     defwndproc_counter++;
352     ret = DefWindowProcA(hwnd, message, wParam, lParam);
353     defwndproc_counter--;
354
355     return ret;
356 }
357
358 static BOOL register_parent_wnd_class(BOOL Unicode)
359 {
360     WNDCLASSA clsA;
361     WNDCLASSW clsW;
362
363     if (Unicode)
364     {
365         clsW.style = 0;
366         clsW.lpfnWndProc = parent_wnd_proc;
367         clsW.cbClsExtra = 0;
368         clsW.cbWndExtra = 0;
369         clsW.hInstance = GetModuleHandleW(NULL);
370         clsW.hIcon = 0;
371         clsW.hCursor = LoadCursorA(0, IDC_ARROW);
372         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
373         clsW.lpszMenuName = NULL;
374         clsW.lpszClassName = testparentclassW;
375     }
376     else
377     {
378         clsA.style = 0;
379         clsA.lpfnWndProc = parent_wnd_proc;
380         clsA.cbClsExtra = 0;
381         clsA.cbWndExtra = 0;
382         clsA.hInstance = GetModuleHandleA(NULL);
383         clsA.hIcon = 0;
384         clsA.hCursor = LoadCursorA(0, IDC_ARROW);
385         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
386         clsA.lpszMenuName = NULL;
387         clsA.lpszClassName = "Listview test parent class";
388     }
389
390     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
391 }
392
393 static HWND create_parent_window(BOOL Unicode)
394 {
395     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
396     HWND hwnd;
397
398     if (!register_parent_wnd_class(Unicode))
399         return NULL;
400
401     blockEdit = FALSE;
402     notifyFormat = -1;
403
404     if (Unicode)
405         hwnd = CreateWindowExW(0, testparentclassW, nameW,
406                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
407                                WS_MAXIMIZEBOX | WS_VISIBLE,
408                                0, 0, 100, 100,
409                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
410     else
411         hwnd = CreateWindowExA(0, "Listview test parent class",
412                                "Listview test parent window",
413                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
414                                WS_MAXIMIZEBOX | WS_VISIBLE,
415                                0, 0, 100, 100,
416                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
417     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
418     return hwnd;
419 }
420
421 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
422 {
423     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
424     static LONG defwndproc_counter = 0;
425     LRESULT ret;
426     struct message msg;
427
428     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
429
430     /* some debug output for style changing */
431     if ((message == WM_STYLECHANGING ||
432          message == WM_STYLECHANGED) && lParam)
433     {
434         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
435         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
436     }
437
438     msg.message = message;
439     msg.flags = sent|wparam|lparam;
440     if (defwndproc_counter) msg.flags |= defwinproc;
441     msg.wParam = wParam;
442     msg.lParam = lParam;
443     msg.id = LISTVIEW_ID;
444     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
445
446     defwndproc_counter++;
447     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
448     defwndproc_counter--;
449     return ret;
450 }
451
452 static HWND create_listview_control(DWORD style)
453 {
454     struct subclass_info *info;
455     HWND hwnd;
456     RECT rect;
457
458     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
459     if (!info)
460         return NULL;
461
462     GetClientRect(hwndparent, &rect);
463     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
464                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
465                            0, 0, rect.right, rect.bottom,
466                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
467     ok(hwnd != NULL, "gle=%d\n", GetLastError());
468
469     if (!hwnd)
470     {
471         HeapFree(GetProcessHeap(), 0, info);
472         return NULL;
473     }
474
475     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
476                                             (LONG_PTR)listview_subclass_proc);
477     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
478
479     return hwnd;
480 }
481
482 /* unicode listview window with specified parent */
483 static HWND create_listview_controlW(DWORD style, HWND parent)
484 {
485     struct subclass_info *info;
486     HWND hwnd;
487     RECT rect;
488     static const WCHAR nameW[] = {'f','o','o',0};
489
490     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
491     if (!info)
492         return NULL;
493
494     GetClientRect(parent, &rect);
495     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
496                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
497                            0, 0, rect.right, rect.bottom,
498                            parent, NULL, GetModuleHandleW(NULL), NULL);
499     ok(hwnd != NULL, "gle=%d\n", GetLastError());
500
501     if (!hwnd)
502     {
503         HeapFree(GetProcessHeap(), 0, info);
504         return NULL;
505     }
506
507     info->oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
508                                             (LONG_PTR)listview_subclass_proc);
509     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)info);
510
511     return hwnd;
512 }
513
514 static HWND create_custom_listview_control(DWORD style)
515 {
516     struct subclass_info *info;
517     HWND hwnd;
518     RECT rect;
519
520     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
521     if (!info)
522         return NULL;
523
524     GetClientRect(hwndparent, &rect);
525     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
526                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
527                            0, 0, rect.right, rect.bottom,
528                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
529     ok(hwnd != NULL, "gle=%d\n", GetLastError());
530
531     if (!hwnd)
532     {
533         HeapFree(GetProcessHeap(), 0, info);
534         return NULL;
535     }
536
537     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
538                                             (LONG_PTR)listview_subclass_proc);
539     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
540
541     return hwnd;
542 }
543
544 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
545 {
546     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
547     static LONG defwndproc_counter = 0;
548     LRESULT ret;
549     struct message msg;
550
551     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
552
553     msg.message = message;
554     msg.flags = sent|wparam|lparam;
555     if (defwndproc_counter) msg.flags |= defwinproc;
556     msg.wParam = wParam;
557     msg.lParam = lParam;
558     msg.id = HEADER_ID;
559     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
560
561     defwndproc_counter++;
562     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
563     defwndproc_counter--;
564     return ret;
565 }
566
567 static HWND subclass_header(HWND hwndListview)
568 {
569     struct subclass_info *info;
570     HWND hwnd;
571
572     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
573     if (!info)
574         return NULL;
575
576     hwnd = ListView_GetHeader(hwndListview);
577     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
578                                             (LONG_PTR)header_subclass_proc);
579     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
580
581     return hwnd;
582 }
583
584 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
585 {
586     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
587     static LONG defwndproc_counter = 0;
588     LRESULT ret;
589     struct message msg;
590
591     msg.message = message;
592     msg.flags = sent|wparam|lparam;
593     if (defwndproc_counter) msg.flags |= defwinproc;
594     msg.wParam = wParam;
595     msg.lParam = lParam;
596
597     /* all we need is sizing */
598     if (message == WM_WINDOWPOSCHANGING ||
599         message == WM_NCCALCSIZE ||
600         message == WM_WINDOWPOSCHANGED ||
601         message == WM_MOVE ||
602         message == WM_SIZE)
603     {
604         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
605     }
606
607     defwndproc_counter++;
608     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
609     defwndproc_counter--;
610     return ret;
611 }
612
613 static HWND subclass_editbox(HWND hwndListview)
614 {
615     struct subclass_info *info;
616     HWND hwnd;
617
618     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
619     if (!info)
620         return NULL;
621
622     hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
623     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
624                                             (LONG_PTR)editbox_subclass_proc);
625     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
626
627     return hwnd;
628 }
629
630 /* Performs a single LVM_HITTEST test */
631 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
632                              BOOL todo_item, BOOL todo_flags, int line)
633 {
634     LVHITTESTINFO lpht;
635     DWORD ret;
636
637     lpht.pt.x = x;
638     lpht.pt.y = y;
639     lpht.iSubItem = 10;
640
641     trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
642     ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
643
644     if (todo_item)
645     {
646         todo_wine
647         {
648             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
649             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
650             ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
651         }
652     }
653     else
654     {
655         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
656         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
657         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
658     }
659
660     if (todo_flags)
661     {
662         todo_wine
663             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
664     }
665     else if (broken_flags)
666         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
667                             "Expected flags %x, got %x\n", flags, lpht.flags);
668     else
669         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
670 }
671
672 /* Performs a single LVM_SUBITEMHITTEST test */
673 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
674                                     BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
675 {
676     LVHITTESTINFO lpht;
677     DWORD ret;
678
679     lpht.pt.x = x;
680     lpht.pt.y = y;
681
682     trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
683     ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
684
685     if (todo_item)
686     {
687         todo_wine
688         {
689             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
690             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
691         }
692     }
693     else
694     {
695         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
696         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
697     }
698
699     if (todo_subitem)
700     {
701         todo_wine
702             ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
703     }
704     else
705         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
706
707     if (todo_flags)
708     {
709         todo_wine
710             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
711     }
712     else
713         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
714 }
715
716 static void test_images(void)
717 {
718     HWND hwnd;
719     DWORD r;
720     LVITEM item;
721     HIMAGELIST himl;
722     HBITMAP hbmp;
723     RECT r1, r2;
724     static CHAR hello[] = "hello";
725
726     himl = ImageList_Create(40, 40, 0, 4, 4);
727     ok(himl != NULL, "failed to create imagelist\n");
728
729     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
730     ok(hbmp != NULL, "failed to create bitmap\n");
731
732     r = ImageList_Add(himl, hbmp, 0);
733     ok(r == 0, "should be zero\n");
734
735     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
736                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
737     ok(hwnd != NULL, "failed to create listview window\n");
738
739     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
740                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
741
742     ok(r == 0, "should return zero\n");
743
744     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
745     ok(r == 0, "should return zero\n");
746
747     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
748     /* returns dimensions */
749
750     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
751     ok(r == 0, "should be zero items\n");
752
753     item.mask = LVIF_IMAGE | LVIF_TEXT;
754     item.iItem = 0;
755     item.iSubItem = 1;
756     item.iImage = 0;
757     item.pszText = 0;
758     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
759     ok(r == -1, "should fail\n");
760
761     item.iSubItem = 0;
762     item.pszText = hello;
763     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
764     ok(r == 0, "should not fail\n");
765
766     memset(&r1, 0, sizeof r1);
767     r1.left = LVIR_ICON;
768     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
769
770     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
771     ok(r == TRUE, "should not fail\n");
772
773     item.iSubItem = 0;
774     item.pszText = hello;
775     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
776     ok(r == 0, "should not fail\n");
777
778     memset(&r2, 0, sizeof r2);
779     r2.left = LVIR_ICON;
780     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
781
782     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
783
784     DestroyWindow(hwnd);
785 }
786
787 static void test_checkboxes(void)
788 {
789     HWND hwnd;
790     LVITEMA item;
791     DWORD r;
792     static CHAR text[]  = "Text",
793                 text2[] = "Text2",
794                 text3[] = "Text3";
795
796     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
797                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
798     ok(hwnd != NULL, "failed to create listview window\n");
799
800     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
801     item.mask = LVIF_TEXT | LVIF_STATE;
802     item.stateMask = 0xffff;
803     item.state = 0xfccc;
804     item.iItem = 0;
805     item.iSubItem = 0;
806     item.pszText = text;
807     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
808     ok(r == 0, "ret %d\n", r);
809
810     item.iItem = 0;
811     item.mask = LVIF_STATE;
812     item.stateMask = 0xffff;
813     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
814     ok(item.state == 0xfccc, "state %x\n", item.state);
815
816     /* Don't set LVIF_STATE */
817     item.mask = LVIF_TEXT;
818     item.stateMask = 0xffff;
819     item.state = 0xfccc;
820     item.iItem = 1;
821     item.iSubItem = 0;
822     item.pszText = text;
823     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
824     ok(r == 1, "ret %d\n", r);
825
826     item.iItem = 1;
827     item.mask = LVIF_STATE;
828     item.stateMask = 0xffff;
829     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
830     ok(item.state == 0, "state %x\n", item.state);
831
832     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
833     ok(r == 0, "should return zero\n");
834
835     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
836     item.iItem = 0;
837     item.mask = LVIF_STATE;
838     item.stateMask = 0xffff;
839     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
840     ok(item.state == 0x1ccc, "state %x\n", item.state);
841
842     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
843     item.iItem = 2;
844     item.mask = LVIF_TEXT;
845     item.state = 0;
846     item.pszText = text2;
847     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
848     ok(r == 2, "ret %d\n", r);
849
850     item.iItem = 2;
851     item.mask = LVIF_STATE;
852     item.stateMask = 0xffff;
853     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
854     ok(item.state == 0x1000, "state %x\n", item.state);
855
856     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
857     item.iItem = 3;
858     item.mask = LVIF_TEXT | LVIF_STATE;
859     item.stateMask = 0xffff;
860     item.state = 0x2aaa;
861     item.pszText = text3;
862     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
863     ok(r == 3, "ret %d\n", r);
864
865     item.iItem = 3;
866     item.mask = LVIF_STATE;
867     item.stateMask = 0xffff;
868     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
869     ok(item.state == 0x1aaa, "state %x\n", item.state);
870
871     /* Set an item's state to checked */
872     item.iItem = 3;
873     item.mask = LVIF_STATE;
874     item.stateMask = 0xf000;
875     item.state = 0x2000;
876     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
877
878     item.iItem = 3;
879     item.mask = LVIF_STATE;
880     item.stateMask = 0xffff;
881     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
882     ok(item.state == 0x2aaa, "state %x\n", item.state);
883
884     /* Check that only the bits we asked for are returned,
885      * and that all the others are set to zero
886      */
887     item.iItem = 3;
888     item.mask = LVIF_STATE;
889     item.stateMask = 0xf000;
890     item.state = 0xffff;
891     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
892     ok(item.state == 0x2000, "state %x\n", item.state);
893
894     /* Set the style again and check that doesn't change an item's state */
895     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
896     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
897
898     item.iItem = 3;
899     item.mask = LVIF_STATE;
900     item.stateMask = 0xffff;
901     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
902     ok(item.state == 0x2aaa, "state %x\n", item.state);
903
904     /* Unsetting the checkbox extended style doesn't change an item's state */
905     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
906     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
907
908     item.iItem = 3;
909     item.mask = LVIF_STATE;
910     item.stateMask = 0xffff;
911     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
912     ok(item.state == 0x2aaa, "state %x\n", item.state);
913
914     /* Now setting the style again will change an item's state */
915     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
916     ok(r == 0, "ret %x\n", r);
917
918     item.iItem = 3;
919     item.mask = LVIF_STATE;
920     item.stateMask = 0xffff;
921     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
922     ok(item.state == 0x1aaa, "state %x\n", item.state);
923
924     /* Toggle checkbox tests (bug 9934) */
925     memset (&item, 0xcc, sizeof(item));
926     item.mask = LVIF_STATE;
927     item.iItem = 3;
928     item.iSubItem = 0;
929     item.state = LVIS_FOCUSED;
930     item.stateMask = LVIS_FOCUSED;
931     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
932     expect(1, r);
933
934     item.iItem = 3;
935     item.mask = LVIF_STATE;
936     item.stateMask = 0xffff;
937     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
938     ok(item.state == 0x1aab, "state %x\n", item.state);
939
940     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
941     expect(0, r);
942     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
943     expect(0, r);
944
945     item.iItem = 3;
946     item.mask = LVIF_STATE;
947     item.stateMask = 0xffff;
948     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
949     ok(item.state == 0x2aab, "state %x\n", item.state);
950
951     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
952     expect(0, r);
953     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
954     expect(0, r);
955
956     item.iItem = 3;
957     item.mask = LVIF_STATE;
958     item.stateMask = 0xffff;
959     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
960     ok(item.state == 0x1aab, "state %x\n", item.state);
961
962     DestroyWindow(hwnd);
963 }
964
965 static void insert_column(HWND hwnd, int idx)
966 {
967     LVCOLUMN column;
968     DWORD rc;
969
970     memset(&column, 0xcc, sizeof(column));
971     column.mask = LVCF_SUBITEM;
972     column.iSubItem = idx;
973
974     rc = ListView_InsertColumn(hwnd, idx, &column);
975     expect(idx, rc);
976 }
977
978 static void insert_item(HWND hwnd, int idx)
979 {
980     static CHAR text[] = "foo";
981
982     LVITEMA item;
983     DWORD rc;
984
985     memset(&item, 0xcc, sizeof (item));
986     item.mask = LVIF_TEXT;
987     item.iItem = idx;
988     item.iSubItem = 0;
989     item.pszText = text;
990
991     rc = ListView_InsertItem(hwnd, &item);
992     expect(idx, rc);
993 }
994
995 static void test_items(void)
996 {
997     const LPARAM lparamTest = 0x42;
998     HWND hwnd;
999     LVITEMA item;
1000     DWORD r;
1001     static CHAR text[] = "Text";
1002
1003     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1004                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1005     ok(hwnd != NULL, "failed to create listview window\n");
1006
1007     /*
1008      * Test setting/getting item params
1009      */
1010
1011     /* Set up two columns */
1012     insert_column(hwnd, 0);
1013     insert_column(hwnd, 1);
1014
1015     /* LVIS_SELECTED with zero stateMask */
1016     /* set */
1017     memset (&item, 0, sizeof (item));
1018     item.mask = LVIF_STATE;
1019     item.state = LVIS_SELECTED;
1020     item.stateMask = 0;
1021     item.iItem = 0;
1022     item.iSubItem = 0;
1023     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1024     ok(r == 0, "ret %d\n", r);
1025     /* get */
1026     memset (&item, 0xcc, sizeof (item));
1027     item.mask = LVIF_STATE;
1028     item.stateMask = LVIS_SELECTED;
1029     item.state = 0;
1030     item.iItem = 0;
1031     item.iSubItem = 0;
1032     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1033     ok(r != 0, "ret %d\n", r);
1034     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1035     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1036
1037     /* LVIS_SELECTED with zero stateMask */
1038     /* set */
1039     memset (&item, 0, sizeof (item));
1040     item.mask = LVIF_STATE;
1041     item.state = LVIS_FOCUSED;
1042     item.stateMask = 0;
1043     item.iItem = 0;
1044     item.iSubItem = 0;
1045     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1046     ok(r == 0, "ret %d\n", r);
1047     /* get */
1048     memset (&item, 0xcc, sizeof (item));
1049     item.mask = LVIF_STATE;
1050     item.stateMask = LVIS_FOCUSED;
1051     item.state = 0;
1052     item.iItem = 0;
1053     item.iSubItem = 0;
1054     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1055     ok(r != 0, "ret %d\n", r);
1056     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1057     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1058
1059     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1060     /* set */
1061     memset (&item, 0, sizeof (item));
1062     item.mask = LVIF_STATE;
1063     item.state = LVIS_CUT;
1064     item.stateMask = LVIS_FOCUSED;
1065     item.iItem = 0;
1066     item.iSubItem = 0;
1067     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1068     ok(r == 0, "ret %d\n", r);
1069     /* get */
1070     memset (&item, 0xcc, sizeof (item));
1071     item.mask = LVIF_STATE;
1072     item.stateMask = LVIS_CUT;
1073     item.state = 0;
1074     item.iItem = 0;
1075     item.iSubItem = 0;
1076     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1077     ok(r != 0, "ret %d\n", r);
1078     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1079     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1080
1081     /* Insert an item with just a param */
1082     memset (&item, 0xcc, sizeof (item));
1083     item.mask = LVIF_PARAM;
1084     item.iItem = 0;
1085     item.iSubItem = 0;
1086     item.lParam = lparamTest;
1087     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1088     ok(r == 0, "ret %d\n", r);
1089
1090     /* Test getting of the param */
1091     memset (&item, 0xcc, sizeof (item));
1092     item.mask = LVIF_PARAM;
1093     item.iItem = 0;
1094     item.iSubItem = 0;
1095     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1096     ok(r != 0, "ret %d\n", r);
1097     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1098
1099     /* Set up a subitem */
1100     memset (&item, 0xcc, sizeof (item));
1101     item.mask = LVIF_TEXT;
1102     item.iItem = 0;
1103     item.iSubItem = 1;
1104     item.pszText = text;
1105     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1106     ok(r != 0, "ret %d\n", r);
1107
1108     /* Query param from subitem: returns main item param */
1109     memset (&item, 0xcc, sizeof (item));
1110     item.mask = LVIF_PARAM;
1111     item.iItem = 0;
1112     item.iSubItem = 1;
1113     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1114     ok(r != 0, "ret %d\n", r);
1115     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1116
1117     /* Set up param on first subitem: no effect */
1118     memset (&item, 0xcc, sizeof (item));
1119     item.mask = LVIF_PARAM;
1120     item.iItem = 0;
1121     item.iSubItem = 1;
1122     item.lParam = lparamTest+1;
1123     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1124     ok(r == 0, "ret %d\n", r);
1125
1126     /* Query param from subitem again: should still return main item param */
1127     memset (&item, 0xcc, sizeof (item));
1128     item.mask = LVIF_PARAM;
1129     item.iItem = 0;
1130     item.iSubItem = 1;
1131     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1132     ok(r != 0, "ret %d\n", r);
1133     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1134
1135     /**** Some tests of state highlighting ****/
1136     memset (&item, 0xcc, sizeof (item));
1137     item.mask = LVIF_STATE;
1138     item.iItem = 0;
1139     item.iSubItem = 0;
1140     item.state = LVIS_SELECTED;
1141     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1142     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1143     ok(r != 0, "ret %d\n", r);
1144     item.iSubItem = 1;
1145     item.state = LVIS_DROPHILITED;
1146     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1147     ok(r != 0, "ret %d\n", r);
1148
1149     memset (&item, 0xcc, sizeof (item));
1150     item.mask = LVIF_STATE;
1151     item.iItem = 0;
1152     item.iSubItem = 0;
1153     item.stateMask = -1;
1154     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1155     ok(r != 0, "ret %d\n", r);
1156     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1157     item.iSubItem = 1;
1158     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1159     ok(r != 0, "ret %d\n", r);
1160     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1161
1162     /* some notnull but meaningless masks */
1163     memset (&item, 0, sizeof(item));
1164     item.mask = LVIF_NORECOMPUTE;
1165     item.iItem = 0;
1166     item.iSubItem = 0;
1167     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1168     ok(r != 0, "ret %d\n", r);
1169     memset (&item, 0, sizeof(item));
1170     item.mask = LVIF_DI_SETITEM;
1171     item.iItem = 0;
1172     item.iSubItem = 0;
1173     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1174     ok(r != 0, "ret %d\n", r);
1175
1176     /* set text to callback value already having it */
1177     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1178     expect(TRUE, r);
1179     memset (&item, 0, sizeof (item));
1180     item.mask  = LVIF_TEXT;
1181     item.pszText = LPSTR_TEXTCALLBACK;
1182     item.iItem = 0;
1183     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1184     ok(r == 0, "ret %d\n", r);
1185     memset (&item, 0, sizeof (item));
1186
1187     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1188
1189     item.pszText = LPSTR_TEXTCALLBACK;
1190     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1191     expect(TRUE, r);
1192
1193     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1194                 "check callback text comparison rule", FALSE);
1195
1196     DestroyWindow(hwnd);
1197 }
1198
1199 static void test_columns(void)
1200 {
1201     HWND hwnd, hwndheader;
1202     LVCOLUMN column;
1203     DWORD rc;
1204     INT order[2];
1205
1206     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1207                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1208     ok(hwnd != NULL, "failed to create listview window\n");
1209
1210     /* Add a column with no mask */
1211     memset(&column, 0xcc, sizeof(column));
1212     column.mask = 0;
1213     rc = ListView_InsertColumn(hwnd, 0, &column);
1214     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1215
1216     /* Check its width */
1217     rc = ListView_GetColumnWidth(hwnd, 0);
1218     ok(rc==10 ||
1219        broken(rc==0), /* win9x */
1220        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1221
1222     DestroyWindow(hwnd);
1223
1224     /* LVM_GETCOLUMNORDERARRAY */
1225     hwnd = create_listview_control(0);
1226     hwndheader = subclass_header(hwnd);
1227
1228     memset(&column, 0, sizeof(column));
1229     column.mask = LVCF_WIDTH;
1230     column.cx = 100;
1231     rc = ListView_InsertColumn(hwnd, 0, &column);
1232     ok(rc == 0, "Inserting column failed with %d\n", rc);
1233
1234     column.cx = 200;
1235     rc = ListView_InsertColumn(hwnd, 1, &column);
1236     ok(rc == 1, "Inserting column failed with %d\n", rc);
1237
1238     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1239
1240     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1241     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1242     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1243     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1244
1245     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1246
1247     DestroyWindow(hwnd);
1248 }
1249 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1250 static WNDPROC listviewWndProc;
1251 static HIMAGELIST test_create_imagelist;
1252
1253 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1254 {
1255     LRESULT ret;
1256
1257     if (uMsg == WM_CREATE)
1258     {
1259         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1260         lpcs->style |= LVS_REPORT;
1261     }
1262     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1263     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1264     return ret;
1265 }
1266
1267 static void test_create(void)
1268 {
1269     HWND hList;
1270     HWND hHeader;
1271     LONG_PTR ret;
1272     LONG r;
1273     LVCOLUMNA col;
1274     RECT rect;
1275     WNDCLASSEX cls;
1276     cls.cbSize = sizeof(WNDCLASSEX);
1277     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1278     listviewWndProc = cls.lpfnWndProc;
1279     cls.lpfnWndProc = create_test_wndproc;
1280     cls.lpszClassName = "MyListView32";
1281     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1282
1283     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1284     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1285     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1286     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1287     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1288     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1289     DestroyWindow(hList);
1290
1291     /* header isn't created on LVS_ICON and LVS_LIST styles */
1292     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1293                           GetModuleHandle(NULL), 0);
1294     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1295     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1296     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1297     /* insert column */
1298     memset(&col, 0, sizeof(LVCOLUMNA));
1299     col.mask = LVCF_WIDTH;
1300     col.cx = 100;
1301     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1302     ok(r == 0, "Expected 0 column's inserted\n");
1303     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1304     ok(IsWindow(hHeader), "Header should be created\n");
1305     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1306     DestroyWindow(hList);
1307
1308     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1309                           GetModuleHandle(NULL), 0);
1310     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1311     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1312     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1313     /* insert column */
1314     memset(&col, 0, sizeof(LVCOLUMNA));
1315     col.mask = LVCF_WIDTH;
1316     col.cx = 100;
1317     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1318     ok(r == 0, "Expected 0 column's inserted\n");
1319     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1320     ok(IsWindow(hHeader), "Header should be created\n");
1321     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1322     DestroyWindow(hList);
1323
1324     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1325     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1326                           GetModuleHandle(NULL), 0);
1327     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1328     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1329     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1330     ok(IsWindow(hHeader), "Header should be created\n");
1331     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1332     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1333     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1334     ok(IsWindow(hHeader), "Header should be created\n");
1335     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1336     DestroyWindow(hList);
1337
1338     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1339     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1340                           GetModuleHandle(NULL), 0);
1341     ret = SetWindowLongPtr(hList, GWL_STYLE,
1342                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1343     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1344     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1345     ok(IsWindow(hHeader), "Header should be created\n");
1346     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1347     ret = SetWindowLongPtr(hList, GWL_STYLE,
1348                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1349     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1350     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1351     ok(IsWindow(hHeader), "Header should be created\n");
1352     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1353     DestroyWindow(hList);
1354
1355     /* LVS_REPORT without WS_VISIBLE */
1356     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1357                           GetModuleHandle(NULL), 0);
1358     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1359     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1360     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1361     /* insert column */
1362     memset(&col, 0, sizeof(LVCOLUMNA));
1363     col.mask = LVCF_WIDTH;
1364     col.cx = 100;
1365     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1366     ok(r == 0, "Expected 0 column's inserted\n");
1367     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1368     ok(IsWindow(hHeader), "Header should be created\n");
1369     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1370     DestroyWindow(hList);
1371
1372     /* LVS_REPORT without WS_VISIBLE, try to show it */
1373     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1374                           GetModuleHandle(NULL), 0);
1375     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1376     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1377     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1378     ShowWindow(hList, SW_SHOW);
1379     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1380     ok(IsWindow(hHeader), "Header should be created\n");
1381     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1382     DestroyWindow(hList);
1383
1384     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1385     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1386                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1387     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1388     ok(IsWindow(hHeader), "Header should be created\n");
1389     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1390     /* HDS_DRAGDROP set by default */
1391     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1392     DestroyWindow(hList);
1393
1394     /* setting LVS_EX_HEADERDRAGDROP creates header */
1395     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1396                           GetModuleHandle(NULL), 0);
1397     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1398     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1399     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1400     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1401     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1402     ok(IsWindow(hHeader) ||
1403        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1404        "Header should be created\n");
1405     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1406     DestroyWindow(hList);
1407
1408     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1409     hList = create_custom_listview_control(0);
1410     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1411     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1412     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1413     DestroyWindow(hList);
1414
1415     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1416     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1417                           GetModuleHandle(NULL), 0);
1418     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1419     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1420
1421     rect.left = LVIR_BOUNDS;
1422     rect.top  = 1;
1423     rect.right = rect.bottom = -10;
1424     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1425     ok(r != 0, "Expected not-null LRESULT\n");
1426
1427     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1428     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1429     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1430
1431     DestroyWindow(hList);
1432
1433     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1434     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1435     hList = create_listview_control(LVS_OWNERDRAWFIXED);
1436     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1437                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1438     DestroyWindow(hList);
1439 }
1440
1441 static void test_redraw(void)
1442 {
1443     HWND hwnd, hwndheader;
1444     HDC hdc;
1445     BOOL res;
1446     DWORD r;
1447
1448     hwnd = create_listview_control(0);
1449     hwndheader = subclass_header(hwnd);
1450
1451     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1452
1453     trace("invalidate & update\n");
1454     InvalidateRect(hwnd, NULL, TRUE);
1455     UpdateWindow(hwnd);
1456     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1457
1458     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1459
1460     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1461     /* 1. Without backbuffer */
1462     res = ListView_SetBkColor(hwnd, CLR_NONE);
1463     expect(TRUE, res);
1464
1465     hdc = GetWindowDC(hwndparent);
1466
1467     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1468     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1469     ok(r != 0, "Expected not zero result\n");
1470     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1471                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1472
1473     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1474     expect(TRUE, res);
1475
1476     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1477     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1478     ok(r != 0, "Expected not zero result\n");
1479     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1480                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1481
1482     /* 2. With backbuffer */
1483     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1484                                                      LVS_EX_DOUBLEBUFFER);
1485     res = ListView_SetBkColor(hwnd, CLR_NONE);
1486     expect(TRUE, res);
1487
1488     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1489     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1490     ok(r != 0, "Expected not zero result\n");
1491     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1492                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1493
1494     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1495     expect(TRUE, res);
1496
1497     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1498     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1499     todo_wine ok(r != 0, "Expected not zero result\n");
1500     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1501                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1502
1503     ReleaseDC(hwndparent, hdc);
1504
1505     DestroyWindow(hwnd);
1506 }
1507
1508 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1509 {
1510     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1511
1512     if(msg == WM_NOTIFY) {
1513         NMHDR *nmhdr = (PVOID)lp;
1514         if(nmhdr->code == NM_CUSTOMDRAW) {
1515             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1516             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1517             switch(nmlvcd->nmcd.dwDrawStage) {
1518             case CDDS_PREPAINT:
1519                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1520                 return CDRF_NOTIFYITEMDRAW;
1521             case CDDS_ITEMPREPAINT:
1522                 nmlvcd->clrTextBk = CLR_DEFAULT;
1523                 return CDRF_NOTIFYSUBITEMDRAW;
1524             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1525                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1526                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1527                 return CDRF_NOTIFYPOSTPAINT;
1528             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1529                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1530                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1531                 return CDRF_DODEFAULT;
1532             }
1533             return CDRF_DODEFAULT;
1534         }
1535     }
1536
1537     return DefWindowProcA(hwnd, msg, wp, lp);
1538 }
1539
1540 static void test_customdraw(void)
1541 {
1542     HWND hwnd;
1543     WNDPROC oldwndproc;
1544
1545     hwnd = create_listview_control(0);
1546
1547     insert_column(hwnd, 0);
1548     insert_column(hwnd, 1);
1549     insert_item(hwnd, 0);
1550
1551     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1552                                            (LONG_PTR)cd_wndproc);
1553
1554     InvalidateRect(hwnd, NULL, TRUE);
1555     UpdateWindow(hwnd);
1556
1557     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1558
1559     DestroyWindow(hwnd);
1560 }
1561
1562 static void test_icon_spacing(void)
1563 {
1564     /* LVM_SETICONSPACING */
1565     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1566
1567     HWND hwnd;
1568     WORD w, h;
1569     DWORD r;
1570
1571     hwnd = create_custom_listview_control(LVS_ICON);
1572     ok(hwnd != NULL, "failed to create a listview window\n");
1573
1574     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1575     expect(NFR_ANSI, r);
1576
1577     /* reset the icon spacing to defaults */
1578     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1579
1580     /* now we can request what the defaults are */
1581     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1582     w = LOWORD(r);
1583     h = HIWORD(r);
1584
1585     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1586
1587     trace("test icon spacing\n");
1588
1589     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1590     ok(r == MAKELONG(w, h) ||
1591        broken(r == MAKELONG(w, w)), /* win98 */
1592        "Expected %d, got %d\n", MAKELONG(w, h), r);
1593
1594     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1595     expect(MAKELONG(20,30), r);
1596
1597     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1598     expect(MAKELONG(25,35), r);
1599
1600     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1601
1602     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1603     DestroyWindow(hwnd);
1604 }
1605
1606 static void test_color(void)
1607 {
1608     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1609
1610     HWND hwnd;
1611     DWORD r;
1612     int i;
1613
1614     COLORREF color;
1615     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1616
1617     hwnd = create_listview_control(0);
1618     ok(hwnd != NULL, "failed to create a listview window\n");
1619
1620     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1621
1622     trace("test color seq\n");
1623     for (i = 0; i < 4; i++)
1624     {
1625         color = colors[i];
1626
1627         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1628         expect(TRUE, r);
1629         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1630         expect(color, r);
1631
1632         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1633         expect (TRUE, r);
1634         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1635         expect(color, r);
1636
1637         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1638         expect(TRUE, r);
1639         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1640         expect(color, r);
1641     }
1642
1643     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1644
1645     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1646     DestroyWindow(hwnd);
1647 }
1648
1649 static void test_item_count(void)
1650 {
1651     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1652
1653     HWND hwnd;
1654     DWORD r;
1655     HDC hdc;
1656     HFONT hOldFont;
1657     TEXTMETRICA tm;
1658     RECT rect;
1659     INT height;
1660
1661     LVITEM item0;
1662     LVITEM item1;
1663     LVITEM item2;
1664     static CHAR item0text[] = "item0";
1665     static CHAR item1text[] = "item1";
1666     static CHAR item2text[] = "item2";
1667
1668     hwnd = create_listview_control(0);
1669     ok(hwnd != NULL, "failed to create a listview window\n");
1670
1671     /* resize in dpiaware manner to fit all 3 items added */
1672     hdc = GetDC(0);
1673     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1674     GetTextMetricsA(hdc, &tm);
1675     /* 2 extra pixels for bounds and header border */
1676     height = tm.tmHeight + 2;
1677     SelectObject(hdc, hOldFont);
1678     ReleaseDC(0, hdc);
1679
1680     GetWindowRect(hwnd, &rect);
1681     /* 3 items + 1 header + 1 to be sure */
1682     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1683
1684     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1685
1686     trace("test item count\n");
1687
1688     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1689     expect(0, r);
1690
1691     /* [item0] */
1692     item0.mask = LVIF_TEXT;
1693     item0.iItem = 0;
1694     item0.iSubItem = 0;
1695     item0.pszText = item0text;
1696     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1697     expect(0, r);
1698
1699     /* [item0, item1] */
1700     item1.mask = LVIF_TEXT;
1701     item1.iItem = 1;
1702     item1.iSubItem = 0;
1703     item1.pszText = item1text;
1704     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1705     expect(1, r);
1706
1707     /* [item0, item1, item2] */
1708     item2.mask = LVIF_TEXT;
1709     item2.iItem = 2;
1710     item2.iSubItem = 0;
1711     item2.pszText = item2text;
1712     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1713     expect(2, r);
1714
1715     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1716     expect(3, r);
1717
1718     /* [item0, item1] */
1719     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1720     expect(TRUE, r);
1721
1722     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1723     expect(2, r);
1724
1725     /* [] */
1726     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1727     expect(TRUE, r);
1728
1729     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1730     expect(0, r);
1731
1732     /* [item0] */
1733     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1734     expect(0, r);
1735
1736     /* [item0, item1] */
1737     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1738     expect(1, r);
1739
1740     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1741     expect(2, r);
1742
1743     /* [item0, item1, item2] */
1744     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1745     expect(2, r);
1746
1747     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1748     expect(3, r);
1749
1750     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1751
1752     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1753     DestroyWindow(hwnd);
1754 }
1755
1756 static void test_item_position(void)
1757 {
1758     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1759
1760     HWND hwnd;
1761     DWORD r;
1762     POINT position;
1763
1764     LVITEM item0;
1765     LVITEM item1;
1766     LVITEM item2;
1767     static CHAR item0text[] = "item0";
1768     static CHAR item1text[] = "item1";
1769     static CHAR item2text[] = "item2";
1770
1771     hwnd = create_custom_listview_control(LVS_ICON);
1772     ok(hwnd != NULL, "failed to create a listview window\n");
1773
1774     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1775
1776     trace("test item position\n");
1777
1778     /* [item0] */
1779     item0.mask = LVIF_TEXT;
1780     item0.iItem = 0;
1781     item0.iSubItem = 0;
1782     item0.pszText = item0text;
1783     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1784     expect(0, r);
1785
1786     /* [item0, item1] */
1787     item1.mask = LVIF_TEXT;
1788     item1.iItem = 1;
1789     item1.iSubItem = 0;
1790     item1.pszText = item1text;
1791     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1792     expect(1, r);
1793
1794     /* [item0, item1, item2] */
1795     item2.mask = LVIF_TEXT;
1796     item2.iItem = 2;
1797     item2.iSubItem = 0;
1798     item2.pszText = item2text;
1799     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1800     expect(2, r);
1801
1802     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1803     expect(TRUE, r);
1804     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1805     expect(TRUE, r);
1806     expect2(10, 5, position.x, position.y);
1807
1808     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1809     expect(TRUE, r);
1810     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1811     expect(TRUE, r);
1812     expect2(0, 0, position.x, position.y);
1813
1814     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1815     expect(TRUE, r);
1816     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1817     expect(TRUE, r);
1818     expect2(20, 20, position.x, position.y);
1819
1820     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1821
1822     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1823     DestroyWindow(hwnd);
1824 }
1825
1826 static void test_getorigin(void)
1827 {
1828     /* LVM_GETORIGIN */
1829
1830     HWND hwnd;
1831     DWORD r;
1832     POINT position;
1833
1834     position.x = position.y = 0;
1835
1836     hwnd = create_custom_listview_control(LVS_ICON);
1837     ok(hwnd != NULL, "failed to create a listview window\n");
1838     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1839     trace("test get origin results\n");
1840     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1841     expect(TRUE, r);
1842     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1843     DestroyWindow(hwnd);
1844
1845     hwnd = create_custom_listview_control(LVS_SMALLICON);
1846     ok(hwnd != NULL, "failed to create a listview window\n");
1847     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1848     trace("test get origin results\n");
1849     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1850     expect(TRUE, r);
1851     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1852     DestroyWindow(hwnd);
1853
1854     hwnd = create_custom_listview_control(LVS_LIST);
1855     ok(hwnd != NULL, "failed to create a listview window\n");
1856     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1857     trace("test get origin results\n");
1858     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1859     expect(FALSE, r);
1860     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1861     DestroyWindow(hwnd);
1862
1863     hwnd = create_custom_listview_control(LVS_REPORT);
1864     ok(hwnd != NULL, "failed to create a listview window\n");
1865     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1866     trace("test get origin results\n");
1867     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1868     expect(FALSE, r);
1869     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1870     DestroyWindow(hwnd);
1871
1872 }
1873
1874 static void test_multiselect(void)
1875 {
1876     typedef struct t_select_task
1877     {
1878         const char *descr;
1879         int initPos;
1880         int loopVK;
1881         int count;
1882         int result;
1883     } select_task;
1884
1885     HWND hwnd;
1886     DWORD r;
1887     int i,j,item_count,selected_count;
1888     static const int items=5;
1889     BYTE kstate[256];
1890     select_task task;
1891     LONG_PTR style;
1892     LVITEMA item;
1893
1894     static struct t_select_task task_list[] = {
1895         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1896         { "using VK_UP", -1, VK_UP, -1, -1 },
1897         { "using VK_END", 0, VK_END, 1, -1 },
1898         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1899     };
1900
1901
1902     hwnd = create_listview_control(0);
1903
1904     for (i=0;i<items;i++) {
1905             insert_item(hwnd, 0);
1906     }
1907
1908     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1909
1910     expect(items,item_count);
1911
1912     for (i=0;i<4;i++) {
1913         task = task_list[i];
1914
1915         /* deselect all items */
1916         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1917         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1918
1919         /* set initial position */
1920         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1921         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1922
1923         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1924
1925         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1926
1927         /* Set SHIFT key pressed */
1928         GetKeyboardState(kstate);
1929         kstate[VK_SHIFT]=0x80;
1930         SetKeyboardState(kstate);
1931
1932         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1933             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1934             expect(0,r);
1935             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1936             expect(0,r);
1937         }
1938
1939         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1940
1941         ok((task.result == -1 ? item_count : task.result) == selected_count, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task.descr, item_count, selected_count);
1942
1943         /* Set SHIFT key released */
1944         GetKeyboardState(kstate);
1945         kstate[VK_SHIFT]=0x00;
1946         SetKeyboardState(kstate);
1947     }
1948     DestroyWindow(hwnd);
1949
1950     /* make multiple selection, then switch to LVS_SINGLESEL */
1951     hwnd = create_listview_control(0);
1952     for (i=0;i<items;i++) {
1953             insert_item(hwnd, 0);
1954     }
1955     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1956     expect(items,item_count);
1957
1958     /* try with NULL pointer */
1959     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)NULL);
1960     expect(FALSE, r);
1961
1962     /* select all, check notifications */
1963     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1964
1965     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1966
1967     item.stateMask = LVIS_SELECTED;
1968     item.state     = LVIS_SELECTED;
1969     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1970     expect(TRUE, r);
1971
1972     ok_sequence(sequences, PARENT_SEQ_INDEX, select_all_parent_seq,
1973                 "select all notification", FALSE);
1974
1975     /* deselect all items */
1976     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1977     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1978     for (i=0;i<3;i++) {
1979         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1980     }
1981
1982     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1983     expect(3, r);
1984     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1985     expect(-1, r);
1986
1987     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1988     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1989     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1990     /* check that style is accepted */
1991     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1992     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1993
1994     for (i=0;i<3;i++) {
1995         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1996         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1997     }
1998     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1999     expect(3, r);
2000     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2001     expect(3, r);
2002
2003     /* select one more */
2004     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
2005
2006     for (i=0;i<3;i++) {
2007         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
2008         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
2009     }
2010     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
2011     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2012
2013     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2014     expect(1, r);
2015     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2016     expect(-1, r);
2017
2018     /* try to select all on LVS_SINGLESEL */
2019     memset(&item, 0, sizeof(item));
2020     item.stateMask = LVIS_SELECTED;
2021     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2022     expect(TRUE, r);
2023     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2024
2025     item.stateMask = LVIS_SELECTED;
2026     item.state     = LVIS_SELECTED;
2027     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2028     expect(FALSE, r);
2029
2030     r = ListView_GetSelectedCount(hwnd);
2031     expect(0, r);
2032     r = ListView_GetSelectionMark(hwnd);
2033     expect(-1, r);
2034
2035     /* try to deselect all on LVS_SINGLESEL */
2036     item.stateMask = LVIS_SELECTED;
2037     item.state     = LVIS_SELECTED;
2038     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2039     expect(TRUE, r);
2040
2041     item.stateMask = LVIS_SELECTED;
2042     item.state     = 0;
2043     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2044     expect(TRUE, r);
2045     r = ListView_GetSelectedCount(hwnd);
2046     expect(0, r);
2047
2048     DestroyWindow(hwnd);
2049 }
2050
2051 static void test_subitem_rect(void)
2052 {
2053     HWND hwnd;
2054     DWORD r;
2055     LVCOLUMN col;
2056     RECT rect;
2057
2058     /* test LVM_GETSUBITEMRECT for header */
2059     hwnd = create_listview_control(0);
2060     ok(hwnd != NULL, "failed to create a listview window\n");
2061     /* add some columns */
2062     memset(&col, 0, sizeof(LVCOLUMN));
2063     col.mask = LVCF_WIDTH;
2064     col.cx = 100;
2065     r = -1;
2066     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2067     expect(0, r);
2068     col.cx = 150;
2069     r = -1;
2070     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2071     expect(1, r);
2072     col.cx = 200;
2073     r = -1;
2074     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2075     expect(2, r);
2076     /* item = -1 means header, subitem index is 1 based */
2077     rect.left = LVIR_BOUNDS;
2078     rect.top  = 0;
2079     rect.right = rect.bottom = 0;
2080     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2081     expect(0, r);
2082
2083     rect.left = LVIR_BOUNDS;
2084     rect.top  = 1;
2085     rect.right = rect.bottom = 0;
2086     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2087
2088     ok(r != 0, "Expected not-null LRESULT\n");
2089     expect(100, rect.left);
2090     expect(250, rect.right);
2091 todo_wine
2092     expect(3, rect.top);
2093
2094     rect.left = LVIR_BOUNDS;
2095     rect.top  = 2;
2096     rect.right = rect.bottom = 0;
2097     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2098
2099     ok(r != 0, "Expected not-null LRESULT\n");
2100     expect(250, rect.left);
2101     expect(450, rect.right);
2102 todo_wine
2103     expect(3, rect.top);
2104
2105     /* item LVS_REPORT padding isn't applied to subitems */
2106     insert_item(hwnd, 0);
2107
2108     rect.left = LVIR_BOUNDS;
2109     rect.top  = 1;
2110     rect.right = rect.bottom = 0;
2111     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2112     ok(r != 0, "Expected not-null LRESULT\n");
2113     expect(100, rect.left);
2114     expect(250, rect.right);
2115
2116     rect.left = LVIR_ICON;
2117     rect.top  = 1;
2118     rect.right = rect.bottom = 0;
2119     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2120     ok(r != 0, "Expected not-null LRESULT\n");
2121     /* no icon attached - zero width rectangle, with no left padding */
2122     expect(100, rect.left);
2123     expect(100, rect.right);
2124
2125     rect.left = LVIR_LABEL;
2126     rect.top  = 1;
2127     rect.right = rect.bottom = 0;
2128     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2129     ok(r != 0, "Expected not-null LRESULT\n");
2130     /* same as full LVIR_BOUNDS */
2131     expect(100, rect.left);
2132     expect(250, rect.right);
2133
2134     DestroyWindow(hwnd);
2135
2136     /* try it for non LVS_REPORT style */
2137     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2138                          GetModuleHandle(NULL), 0);
2139     rect.left = LVIR_BOUNDS;
2140     rect.top  = 1;
2141     rect.right = rect.bottom = -10;
2142     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2143     ok(r == 0, "Expected not-null LRESULT\n");
2144     /* rect is unchanged */
2145     expect(0, rect.left);
2146     expect(-10, rect.right);
2147     expect(1, rect.top);
2148     expect(-10, rect.bottom);
2149     DestroyWindow(hwnd);
2150 }
2151
2152 /* comparison callback for test_sorting */
2153 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2154 {
2155     if (first == second) return 0;
2156     return (first > second ? 1 : -1);
2157 }
2158
2159 static void test_sorting(void)
2160 {
2161     HWND hwnd;
2162     LVITEMA item = {0};
2163     DWORD r;
2164     LONG_PTR style;
2165     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2166     CHAR buff[10];
2167
2168     hwnd = create_listview_control(0);
2169     ok(hwnd != NULL, "failed to create a listview window\n");
2170
2171     /* insert some items */
2172     item.mask = LVIF_PARAM | LVIF_STATE;
2173     item.state = LVIS_SELECTED;
2174     item.iItem = 0;
2175     item.iSubItem = 0;
2176     item.lParam = 3;
2177     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2178     expect(0, r);
2179
2180     item.mask = LVIF_PARAM;
2181     item.iItem = 1;
2182     item.iSubItem = 0;
2183     item.lParam = 2;
2184     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2185     expect(1, r);
2186
2187     item.mask = LVIF_STATE | LVIF_PARAM;
2188     item.state = LVIS_SELECTED;
2189     item.iItem = 2;
2190     item.iSubItem = 0;
2191     item.lParam = 4;
2192     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2193     expect(2, r);
2194
2195     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2196     expect(-1, r);
2197
2198     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2199     expect(2, r);
2200
2201     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2202     expect(TRUE, r);
2203
2204     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2205     expect(2, r);
2206     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2207     expect(-1, r);
2208     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2209     expect(0, r);
2210     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2211     expect(LVIS_SELECTED, r);
2212     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2213     expect(LVIS_SELECTED, r);
2214
2215     DestroyWindow(hwnd);
2216
2217     /* switch to LVS_SORTASCENDING when some items added */
2218     hwnd = create_listview_control(0);
2219     ok(hwnd != NULL, "failed to create a listview window\n");
2220
2221     item.mask = LVIF_TEXT;
2222     item.iItem = 0;
2223     item.iSubItem = 0;
2224     item.pszText = names[1];
2225     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2226     expect(0, r);
2227
2228     item.mask = LVIF_TEXT;
2229     item.iItem = 1;
2230     item.iSubItem = 0;
2231     item.pszText = names[2];
2232     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2233     expect(1, r);
2234
2235     item.mask = LVIF_TEXT;
2236     item.iItem = 2;
2237     item.iSubItem = 0;
2238     item.pszText = names[0];
2239     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2240     expect(2, r);
2241
2242     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2243     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2244     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2245     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2246
2247     /* no sorting performed when switched to LVS_SORTASCENDING */
2248     item.mask = LVIF_TEXT;
2249     item.iItem = 0;
2250     item.pszText = buff;
2251     item.cchTextMax = sizeof(buff);
2252     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2253     expect(TRUE, r);
2254     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2255
2256     item.iItem = 1;
2257     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2258     expect(TRUE, r);
2259     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2260
2261     item.iItem = 2;
2262     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2263     expect(TRUE, r);
2264     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2265
2266     /* adding new item doesn't resort list */
2267     item.mask = LVIF_TEXT;
2268     item.iItem = 3;
2269     item.iSubItem = 0;
2270     item.pszText = names[3];
2271     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2272     expect(3, r);
2273
2274     item.mask = LVIF_TEXT;
2275     item.iItem = 0;
2276     item.pszText = buff;
2277     item.cchTextMax = sizeof(buff);
2278     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2279     expect(TRUE, r);
2280     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2281
2282     item.iItem = 1;
2283     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2284     expect(TRUE, r);
2285     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2286
2287     item.iItem = 2;
2288     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2289     expect(TRUE, r);
2290     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2291
2292     item.iItem = 3;
2293     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2294     expect(TRUE, r);
2295     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2296
2297     /* corner case - item should be placed at first position */
2298     item.mask = LVIF_TEXT;
2299     item.iItem = 4;
2300     item.iSubItem = 0;
2301     item.pszText = names[4];
2302     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2303     expect(0, r);
2304
2305     item.iItem = 0;
2306     item.pszText = buff;
2307     item.cchTextMax = sizeof(buff);
2308     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2309     expect(TRUE, r);
2310     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2311
2312     item.iItem = 1;
2313     item.pszText = buff;
2314     item.cchTextMax = sizeof(buff);
2315     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2316     expect(TRUE, r);
2317     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2318
2319     item.iItem = 2;
2320     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2321     expect(TRUE, r);
2322     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2323
2324     item.iItem = 3;
2325     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2326     expect(TRUE, r);
2327     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2328
2329     item.iItem = 4;
2330     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2331     expect(TRUE, r);
2332     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2333
2334     DestroyWindow(hwnd);
2335 }
2336
2337 static void test_ownerdata(void)
2338 {
2339     HWND hwnd;
2340     LONG_PTR style, ret;
2341     DWORD res;
2342     LVITEMA item;
2343
2344     /* it isn't possible to set LVS_OWNERDATA after creation */
2345     if (g_is_below_5)
2346     {
2347         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2348     }
2349     else
2350     {
2351         hwnd = create_listview_control(0);
2352         ok(hwnd != NULL, "failed to create a listview window\n");
2353         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2354         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2355
2356         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2357
2358         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2359         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2360         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2361                 "try to switch to LVS_OWNERDATA seq", FALSE);
2362
2363         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2364         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2365         DestroyWindow(hwnd);
2366     }
2367
2368     /* try to set LVS_OWNERDATA after creation just having it */
2369     hwnd = create_listview_control(LVS_OWNERDATA);
2370     ok(hwnd != NULL, "failed to create a listview window\n");
2371     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2372     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2373
2374     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2375
2376     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2377     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2378     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2379                 "try to switch to LVS_OWNERDATA seq", FALSE);
2380     DestroyWindow(hwnd);
2381
2382     /* try to remove LVS_OWNERDATA after creation just having it */
2383     if (g_is_below_5)
2384     {
2385         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2386     }
2387     else
2388     {
2389         hwnd = create_listview_control(LVS_OWNERDATA);
2390         ok(hwnd != NULL, "failed to create a listview window\n");
2391         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2392         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2393
2394         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2395
2396         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2397         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2398         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2399                 "try to switch to LVS_OWNERDATA seq", FALSE);
2400         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2401         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2402         DestroyWindow(hwnd);
2403     }
2404
2405     /* try select an item */
2406     hwnd = create_listview_control(LVS_OWNERDATA);
2407     ok(hwnd != NULL, "failed to create a listview window\n");
2408     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2409     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2410     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2411     expect(0, res);
2412     memset(&item, 0, sizeof(item));
2413     item.stateMask = LVIS_SELECTED;
2414     item.state     = LVIS_SELECTED;
2415     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2416     expect(TRUE, res);
2417     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2418     expect(1, res);
2419     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2420     expect(1, res);
2421     DestroyWindow(hwnd);
2422
2423     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2424     hwnd = create_listview_control(LVS_OWNERDATA);
2425     ok(hwnd != NULL, "failed to create a listview window\n");
2426     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2427     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2428     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2429     expect(1, res);
2430     memset(&item, 0, sizeof(item));
2431     item.mask = LVIF_STATE;
2432     item.iItem = 0;
2433     item.stateMask = LVIS_SELECTED;
2434     item.state     = LVIS_SELECTED;
2435     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2436     expect(FALSE, res);
2437     DestroyWindow(hwnd);
2438
2439     /* check notifications after focused/selected changed */
2440     hwnd = create_listview_control(LVS_OWNERDATA);
2441     ok(hwnd != NULL, "failed to create a listview window\n");
2442     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
2443     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2444
2445     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2446
2447     memset(&item, 0, sizeof(item));
2448     item.stateMask = LVIS_SELECTED;
2449     item.state     = LVIS_SELECTED;
2450     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2451     expect(TRUE, res);
2452
2453     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2454                 "ownerdata select notification", TRUE);
2455
2456     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2457
2458     memset(&item, 0, sizeof(item));
2459     item.stateMask = LVIS_FOCUSED;
2460     item.state     = LVIS_FOCUSED;
2461     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2462     expect(TRUE, res);
2463
2464     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2465                 "ownerdata focus notification", TRUE);
2466
2467     /* select all, check notifications */
2468     item.stateMask = LVIS_SELECTED;
2469     item.state     = 0;
2470     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2471     expect(TRUE, res);
2472
2473     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2474
2475     item.stateMask = LVIS_SELECTED;
2476     item.state     = LVIS_SELECTED;
2477
2478     g_dump_itemchanged = TRUE;
2479     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2480     expect(TRUE, res);
2481     g_dump_itemchanged = FALSE;
2482
2483     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2484                 "ownerdata select all notification", TRUE);
2485
2486     /* select all again, note that all items are selected already */
2487     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2488     item.stateMask = LVIS_SELECTED;
2489     item.state     = LVIS_SELECTED;
2490     g_dump_itemchanged = TRUE;
2491     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2492     expect(TRUE, res);
2493     g_dump_itemchanged = FALSE;
2494     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2495                 "ownerdata select all notification", TRUE);
2496     /* deselect all */
2497     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2498     item.stateMask = LVIS_SELECTED;
2499     item.state     = 0;
2500     g_dump_itemchanged = TRUE;
2501     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2502     expect(TRUE, res);
2503     g_dump_itemchanged = FALSE;
2504     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2505                 "ownerdata deselect all notification", TRUE);
2506
2507     /* select one, then deselect all */
2508     item.stateMask = LVIS_SELECTED;
2509     item.state     = LVIS_SELECTED;
2510     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2511     expect(TRUE, res);
2512     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2513     item.stateMask = LVIS_SELECTED;
2514     item.state     = 0;
2515     g_dump_itemchanged = TRUE;
2516     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2517     expect(TRUE, res);
2518     g_dump_itemchanged = FALSE;
2519     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2520                 "ownerdata select all notification", TRUE);
2521
2522     /* remove focused, try to focus all */
2523     item.stateMask = LVIS_FOCUSED;
2524     item.state     = LVIS_FOCUSED;
2525     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2526     expect(TRUE, res);
2527     item.stateMask = LVIS_FOCUSED;
2528     item.state     = 0;
2529     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2530     expect(TRUE, res);
2531     item.stateMask = LVIS_FOCUSED;
2532     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
2533     expect(0, res);
2534     /* setting all to focused returns failure value */
2535     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2536     item.stateMask = LVIS_FOCUSED;
2537     item.state     = LVIS_FOCUSED;
2538     g_dump_itemchanged = TRUE;
2539     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2540     expect(FALSE, res);
2541     g_dump_itemchanged = FALSE;
2542     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2543                 "ownerdata focus all notification", FALSE);
2544     /* focus single item, remove all */
2545     item.stateMask = LVIS_FOCUSED;
2546     item.state     = LVIS_FOCUSED;
2547     res = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2548     expect(TRUE, res);
2549     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2550     item.stateMask = LVIS_FOCUSED;
2551     item.state     = 0;
2552     g_dump_itemchanged = TRUE;
2553     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2554     expect(TRUE, res);
2555     g_dump_itemchanged = FALSE;
2556     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
2557                 "ownerdata remove focus all notification", TRUE);
2558     /* set all cut */
2559     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2560     item.stateMask = LVIS_CUT;
2561     item.state     = LVIS_CUT;
2562     g_dump_itemchanged = TRUE;
2563     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2564     expect(TRUE, res);
2565     g_dump_itemchanged = FALSE;
2566     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2567                 "ownerdata cut all notification", TRUE);
2568     /* all marked cut, try again */
2569     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2570     item.stateMask = LVIS_CUT;
2571     item.state     = LVIS_CUT;
2572     g_dump_itemchanged = TRUE;
2573     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2574     expect(TRUE, res);
2575     g_dump_itemchanged = FALSE;
2576     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2577                 "ownerdata cut all notification #2", TRUE);
2578
2579     DestroyWindow(hwnd);
2580
2581     /* check notifications on LVM_GETITEM */
2582     /* zero callback mask */
2583     hwnd = create_listview_control(LVS_OWNERDATA);
2584     ok(hwnd != NULL, "failed to create a listview window\n");
2585     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2586     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2587
2588     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2589
2590     memset(&item, 0, sizeof(item));
2591     item.stateMask = LVIS_SELECTED;
2592     item.mask      = LVIF_STATE;
2593     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2594     expect(TRUE, res);
2595
2596     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2597                 "ownerdata getitem selected state 1", FALSE);
2598
2599     /* non zero callback mask but not we asking for */
2600     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2601     expect(TRUE, res);
2602
2603     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2604
2605     memset(&item, 0, sizeof(item));
2606     item.stateMask = LVIS_SELECTED;
2607     item.mask      = LVIF_STATE;
2608     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2609     expect(TRUE, res);
2610
2611     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2612                 "ownerdata getitem selected state 2", FALSE);
2613
2614     /* LVIS_OVERLAYMASK callback mask, asking for index */
2615     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2616
2617     memset(&item, 0, sizeof(item));
2618     item.stateMask = LVIS_OVERLAYMASK;
2619     item.mask      = LVIF_STATE;
2620     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2621     expect(TRUE, res);
2622
2623     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2624                 "ownerdata getitem selected state 2", FALSE);
2625
2626     DestroyWindow(hwnd);
2627
2628     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2629     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2630     ok(hwnd != NULL, "failed to create a listview window\n");
2631     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2632     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2633     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2634     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2635     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2636     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2637     DestroyWindow(hwnd);
2638     /* apparently it's allowed to switch these style on after creation */
2639     hwnd = create_listview_control(LVS_OWNERDATA);
2640     ok(hwnd != NULL, "failed to create a listview window\n");
2641     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2642     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2643     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2644     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2645     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2646     DestroyWindow(hwnd);
2647
2648     hwnd = create_listview_control(LVS_OWNERDATA);
2649     ok(hwnd != NULL, "failed to create a listview window\n");
2650     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2651     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2652     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
2653     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2654     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2655     DestroyWindow(hwnd);
2656 }
2657
2658 static void test_norecompute(void)
2659 {
2660     static CHAR testA[] = "test";
2661     CHAR buff[10];
2662     LVITEMA item;
2663     HWND hwnd;
2664     DWORD res;
2665
2666     /* self containing control */
2667     hwnd = create_listview_control(0);
2668     ok(hwnd != NULL, "failed to create a listview window\n");
2669     memset(&item, 0, sizeof(item));
2670     item.mask = LVIF_TEXT | LVIF_STATE;
2671     item.iItem = 0;
2672     item.stateMask = LVIS_SELECTED;
2673     item.state     = LVIS_SELECTED;
2674     item.pszText   = testA;
2675     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2676     expect(0, res);
2677     /* retrieve with LVIF_NORECOMPUTE */
2678     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2679     item.iItem = 0;
2680     item.pszText    = buff;
2681     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2682     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2683     expect(TRUE, res);
2684     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2685
2686     item.mask = LVIF_TEXT;
2687     item.iItem = 1;
2688     item.pszText = LPSTR_TEXTCALLBACK;
2689     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2690     expect(1, res);
2691
2692     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2693     item.iItem = 1;
2694     item.pszText    = buff;
2695     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2696
2697     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2698     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2699     expect(TRUE, res);
2700     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2701        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2702     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2703
2704     DestroyWindow(hwnd);
2705
2706     /* LVS_OWNERDATA */
2707     hwnd = create_listview_control(LVS_OWNERDATA);
2708     ok(hwnd != NULL, "failed to create a listview window\n");
2709
2710     item.mask = LVIF_STATE;
2711     item.stateMask = LVIS_SELECTED;
2712     item.state     = LVIS_SELECTED;
2713     item.iItem = 0;
2714     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2715     expect(0, res);
2716
2717     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2718     item.iItem = 0;
2719     item.pszText    = buff;
2720     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2721     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2722     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2723     expect(TRUE, res);
2724     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2725        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2726     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2727
2728     DestroyWindow(hwnd);
2729 }
2730
2731 static void test_nosortheader(void)
2732 {
2733     HWND hwnd, header;
2734     LONG_PTR style;
2735
2736     hwnd = create_listview_control(0);
2737     ok(hwnd != NULL, "failed to create a listview window\n");
2738
2739     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2740     ok(IsWindow(header), "header expected\n");
2741
2742     style = GetWindowLongPtr(header, GWL_STYLE);
2743     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2744
2745     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2746     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2747     /* HDS_BUTTONS retained */
2748     style = GetWindowLongPtr(header, GWL_STYLE);
2749     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2750
2751     DestroyWindow(hwnd);
2752
2753     /* create with LVS_NOSORTHEADER */
2754     hwnd = create_listview_control(LVS_NOSORTHEADER);
2755     ok(hwnd != NULL, "failed to create a listview window\n");
2756
2757     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2758     ok(IsWindow(header), "header expected\n");
2759
2760     style = GetWindowLongPtr(header, GWL_STYLE);
2761     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2762
2763     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2764     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2765     /* not changed here */
2766     style = GetWindowLongPtr(header, GWL_STYLE);
2767     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2768
2769     DestroyWindow(hwnd);
2770 }
2771
2772 static void test_setredraw(void)
2773 {
2774     HWND hwnd;
2775     DWORD_PTR style;
2776     DWORD ret;
2777     HDC hdc;
2778     RECT rect;
2779
2780     hwnd = create_listview_control(LVS_OWNERDATA);
2781     ok(hwnd != NULL, "failed to create a listview window\n");
2782
2783     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2784        ListView seems to handle it internally without DefWinProc */
2785
2786     /* default value first */
2787     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2788     expect(0, ret);
2789     /* disable */
2790     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2791     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2792     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2793     expect(0, ret);
2794     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2795     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2796     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2797     expect(0, ret);
2798
2799     /* check update rect after redrawing */
2800     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2801     expect(0, ret);
2802     InvalidateRect(hwnd, NULL, FALSE);
2803     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
2804     rect.right = rect.bottom = 1;
2805     GetUpdateRect(hwnd, &rect, FALSE);
2806     expect(0, rect.right);
2807     expect(0, rect.bottom);
2808
2809     /* WM_ERASEBKGND */
2810     hdc = GetWindowDC(hwndparent);
2811     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2812     expect(TRUE, ret);
2813     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2814     expect(0, ret);
2815     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2816     expect(TRUE, ret);
2817     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2818     expect(0, ret);
2819     ReleaseDC(hwndparent, hdc);
2820
2821     /* check notification messages to show that repainting is disabled */
2822     ret = SendMessage(hwnd, LVM_SETITEMCOUNT, 1, 0);
2823     expect(TRUE, ret);
2824     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2825     expect(0, ret);
2826     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2827
2828     InvalidateRect(hwnd, NULL, TRUE);
2829     UpdateWindow(hwnd);
2830     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2831                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
2832
2833     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
2834     expect(TRUE, ret);
2835     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2836     InvalidateRect(hwnd, NULL, TRUE);
2837     UpdateWindow(hwnd);
2838     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2839                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
2840
2841     /* message isn't forwarded to header */
2842     subclass_header(hwnd);
2843     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2844     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2845     expect(0, ret);
2846     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
2847                 "WM_SETREDRAW: not forwarded to header", FALSE);
2848
2849     DestroyWindow(hwnd);
2850 }
2851
2852 static void test_hittest(void)
2853 {
2854     HWND hwnd;
2855     DWORD r;
2856     RECT bounds;
2857     LVITEMA item;
2858     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2859     POINT pos;
2860     INT x, y;
2861     HIMAGELIST himl, himl2;
2862     HBITMAP hbmp;
2863
2864     hwnd = create_listview_control(0);
2865     ok(hwnd != NULL, "failed to create a listview window\n");
2866
2867     /* LVS_REPORT with a single subitem (2 columns) */
2868     insert_column(hwnd, 0);
2869     insert_column(hwnd, 1);
2870     insert_item(hwnd, 0);
2871
2872     item.iSubItem = 0;
2873     /* the only purpose of that line is to be as long as a half item rect */
2874     item.pszText  = text;
2875     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2876     expect(TRUE, r);
2877
2878     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2879     expect(TRUE, r);
2880     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2881     expect(TRUE, r);
2882
2883     memset(&bounds, 0, sizeof(bounds));
2884     bounds.left = LVIR_BOUNDS;
2885     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2886     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2887     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2888     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2889     expect(TRUE, r);
2890
2891     /* LVS_EX_FULLROWSELECT not set, no icons attached */
2892     x = pos.x + 50; /* column half width */
2893     y = pos.y + (bounds.bottom - bounds.top) / 2;
2894     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE, __LINE__);
2895     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2896     x = pos.x + 150; /* outside column */
2897     y = pos.y + (bounds.bottom - bounds.top) / 2;
2898     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2899     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2900     y = (bounds.bottom - bounds.top) / 2;
2901     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2902     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2903     /* outside possible client rectangle (to right) */
2904     x = pos.x + 500;
2905     y = pos.y + (bounds.bottom - bounds.top) / 2;
2906     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2907     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2908     y = (bounds.bottom - bounds.top) / 2;
2909     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2910     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2911     /* subitem returned with -1 item too */
2912     x = pos.x + 150;
2913     y = -10;
2914     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2915     /* parent client area is 100x100 by default */
2916     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2917     x = pos.x + 150; /* outside column */
2918     y = pos.y + (bounds.bottom - bounds.top) / 2;
2919     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE, __LINE__);
2920     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2921     y = (bounds.bottom - bounds.top) / 2;
2922     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE, __LINE__);
2923     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2924     /* the same with LVS_EX_FULLROWSELECT */
2925     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2926     x = pos.x + 150; /* outside column */
2927     y = pos.y + (bounds.bottom - bounds.top) / 2;
2928     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2929     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2930     y = (bounds.bottom - bounds.top) / 2;
2931     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2932     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2933     x = pos.x + 150; /* outside column */
2934     y = pos.y + (bounds.bottom - bounds.top) / 2;
2935     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2936     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2937     y = (bounds.bottom - bounds.top) / 2;
2938     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2939     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2940     /* outside possible client rectangle (to right) */
2941     x = pos.x + 500;
2942     y = pos.y + (bounds.bottom - bounds.top) / 2;
2943     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2944     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2945     y = (bounds.bottom - bounds.top) / 2;
2946     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2947     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2948     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2949     himl = ImageList_Create(16, 16, 0, 4, 4);
2950     ok(himl != NULL, "failed to create imagelist\n");
2951     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2952     ok(hbmp != NULL, "failed to create bitmap\n");
2953     r = ImageList_Add(himl, hbmp, 0);
2954     ok(r == 0, "should be zero\n");
2955     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2956     ok(hbmp != NULL, "failed to create bitmap\n");
2957     r = ImageList_Add(himl, hbmp, 0);
2958     ok(r == 1, "should be one\n");
2959
2960     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2961     ok(r == 0, "should return zero\n");
2962
2963     item.mask = LVIF_IMAGE;
2964     item.iImage = 0;
2965     item.iItem = 0;
2966     item.iSubItem = 0;
2967     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2968     expect(TRUE, r);
2969     /* on state icon */
2970     x = pos.x + 8;
2971     y = pos.y + (bounds.bottom - bounds.top) / 2;
2972     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2973     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2974     y = (bounds.bottom - bounds.top) / 2;
2975     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2976
2977     /* state icons indices are 1 based, check with valid index */
2978     item.mask = LVIF_STATE;
2979     item.state = INDEXTOSTATEIMAGEMASK(1);
2980     item.stateMask = LVIS_STATEIMAGEMASK;
2981     item.iItem = 0;
2982     item.iSubItem = 0;
2983     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2984     expect(TRUE, r);
2985     /* on state icon */
2986     x = pos.x + 8;
2987     y = pos.y + (bounds.bottom - bounds.top) / 2;
2988     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2989     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2990     y = (bounds.bottom - bounds.top) / 2;
2991     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2992
2993     himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
2994     ok(himl2 == himl, "should return handle\n");
2995
2996     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
2997     ok(r == 0, "should return zero\n");
2998     /* on item icon */
2999     x = pos.x + 8;
3000     y = pos.y + (bounds.bottom - bounds.top) / 2;
3001     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE, __LINE__);
3002     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
3003     y = (bounds.bottom - bounds.top) / 2;
3004     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
3005
3006     DestroyWindow(hwnd);
3007 }
3008
3009 static void test_getviewrect(void)
3010 {
3011     HWND hwnd;
3012     DWORD r;
3013     RECT rect;
3014     LVITEMA item;
3015
3016     hwnd = create_listview_control(0);
3017     ok(hwnd != NULL, "failed to create a listview window\n");
3018
3019     /* empty */
3020     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3021     expect(TRUE, r);
3022
3023     insert_column(hwnd, 0);
3024     insert_column(hwnd, 1);
3025
3026     memset(&item, 0, sizeof(item));
3027     item.iItem = 0;
3028     item.iSubItem = 0;
3029     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3030
3031     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3032     expect(TRUE, r);
3033     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3034     expect(TRUE, r);
3035
3036     rect.left = rect.right = rect.top = rect.bottom = -1;
3037     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3038     expect(TRUE, r);
3039     /* left is set to (2e31-1) - XP SP2 */
3040     expect(0, rect.right);
3041     expect(0, rect.top);
3042     expect(0, rect.bottom);
3043
3044     /* switch to LVS_ICON */
3045     SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
3046
3047     rect.left = rect.right = rect.top = rect.bottom = -1;
3048     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3049     expect(TRUE, r);
3050     expect(0, rect.left);
3051     expect(0, rect.top);
3052     /* precise value differs for 2k, XP and Vista */
3053     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3054     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3055
3056     DestroyWindow(hwnd);
3057 }
3058
3059 static void test_getitemposition(void)
3060 {
3061     HWND hwnd, header;
3062     DWORD r;
3063     POINT pt;
3064     RECT rect;
3065
3066     hwnd = create_listview_control(0);
3067     ok(hwnd != NULL, "failed to create a listview window\n");
3068     header = subclass_header(hwnd);
3069
3070     /* LVS_REPORT, single item, no columns added */
3071     insert_item(hwnd, 0);
3072
3073     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3074
3075     pt.x = pt.y = -1;
3076     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3077     expect(TRUE, r);
3078     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3079
3080     /* LVS_REPORT, single item, single column */
3081     insert_column(hwnd, 0);
3082
3083     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3084
3085     pt.x = pt.y = -1;
3086     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3087     expect(TRUE, r);
3088     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3089
3090     memset(&rect, 0, sizeof(rect));
3091     SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3092     /* some padding? */
3093     expect(2, pt.x);
3094     /* offset by header height */
3095     expect(rect.bottom - rect.top, pt.y);
3096
3097     DestroyWindow(hwnd);
3098 }
3099
3100 static void test_columnscreation(void)
3101 {
3102     HWND hwnd, header;
3103     DWORD r;
3104
3105     hwnd = create_listview_control(0);
3106     ok(hwnd != NULL, "failed to create a listview window\n");
3107
3108     insert_item(hwnd, 0);
3109
3110     /* headers columns aren't created automatically */
3111     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3112     ok(IsWindow(header), "Expected header handle\n");
3113     r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
3114     expect(0, r);
3115
3116     DestroyWindow(hwnd);
3117 }
3118
3119 static void test_getitemrect(void)
3120 {
3121     HWND hwnd;
3122     HIMAGELIST himl;
3123     HBITMAP hbm;
3124     RECT rect;
3125     DWORD r;
3126     LVITEMA item;
3127     LVCOLUMNA col;
3128     INT order[2];
3129     POINT pt;
3130
3131     hwnd = create_listview_control(0);
3132     ok(hwnd != NULL, "failed to create a listview window\n");
3133
3134     /* empty item */
3135     memset(&item, 0, sizeof(item));
3136     item.iItem = 0;
3137     item.iSubItem = 0;
3138     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3139     expect(0, r);
3140
3141     rect.left = LVIR_BOUNDS;
3142     rect.right = rect.top = rect.bottom = -1;
3143     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3144     expect(TRUE, r);
3145
3146     /* zero width rectangle with no padding */
3147     expect(0, rect.left);
3148     expect(0, rect.right);
3149
3150     insert_column(hwnd, 0);
3151     insert_column(hwnd, 1);
3152
3153     col.mask = LVCF_WIDTH;
3154     col.cx   = 50;
3155     r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
3156     expect(TRUE, r);
3157
3158     col.mask = LVCF_WIDTH;
3159     col.cx   = 100;
3160     r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
3161     expect(TRUE, r);
3162
3163     rect.left = LVIR_BOUNDS;
3164     rect.right = rect.top = rect.bottom = -1;
3165     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3166     expect(TRUE, r);
3167
3168     /* still no left padding */
3169     expect(0, rect.left);
3170     expect(150, rect.right);
3171
3172     rect.left = LVIR_SELECTBOUNDS;
3173     rect.right = rect.top = rect.bottom = -1;
3174     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3175     expect(TRUE, r);
3176     /* padding */
3177     expect(2, rect.left);
3178
3179     rect.left = LVIR_LABEL;
3180     rect.right = rect.top = rect.bottom = -1;
3181     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3182     expect(TRUE, r);
3183     /* padding, column width */
3184     expect(2, rect.left);
3185     expect(50, rect.right);
3186
3187     /* no icons attached */
3188     rect.left = LVIR_ICON;
3189     rect.right = rect.top = rect.bottom = -1;
3190     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3191     expect(TRUE, r);
3192     /* padding */
3193     expect(2, rect.left);
3194     expect(2, rect.right);
3195
3196     /* change order */
3197     order[0] = 1; order[1] = 0;
3198     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3199     expect(TRUE, r);
3200     pt.x = -1;
3201     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3202     expect(TRUE, r);
3203     /* 1 indexed column width + padding */
3204     expect(102, pt.x);
3205     /* rect is at zero too */
3206     rect.left = LVIR_BOUNDS;
3207     rect.right = rect.top = rect.bottom = -1;
3208     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3209     expect(TRUE, r);
3210     expect(0, rect.left);
3211     /* just width sum */
3212     expect(150, rect.right);
3213
3214     rect.left = LVIR_SELECTBOUNDS;
3215     rect.right = rect.top = rect.bottom = -1;
3216     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3217     expect(TRUE, r);
3218     /* column width + padding */
3219     expect(102, rect.left);
3220
3221     /* back to initial order */
3222     order[0] = 0; order[1] = 1;
3223     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3224     expect(TRUE, r);
3225
3226     /* state icons */
3227     himl = ImageList_Create(16, 16, 0, 2, 2);
3228     ok(himl != NULL, "failed to create imagelist\n");
3229     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3230     ok(hbm != NULL, "failed to create bitmap\n");
3231     r = ImageList_Add(himl, hbm, 0);
3232     ok(r == 0, "should be zero\n");
3233     hbm = CreateBitmap(16, 16, 1, 1, NULL);
3234     ok(hbm != NULL, "failed to create bitmap\n");
3235     r = ImageList_Add(himl, hbm, 0);
3236     ok(r == 1, "should be one\n");
3237
3238     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3239     ok(r == 0, "should return zero\n");
3240
3241     item.mask = LVIF_STATE;
3242     item.state = INDEXTOSTATEIMAGEMASK(1);
3243     item.stateMask = LVIS_STATEIMAGEMASK;
3244     item.iItem = 0;
3245     item.iSubItem = 0;
3246     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3247     expect(TRUE, r);
3248
3249     /* icon bounds */
3250     rect.left = LVIR_ICON;
3251     rect.right = rect.top = rect.bottom = -1;
3252     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3253     expect(TRUE, r);
3254     /* padding + stateicon width */
3255     expect(18, rect.left);
3256     expect(18, rect.right);
3257     /* label bounds */
3258     rect.left = LVIR_LABEL;
3259     rect.right = rect.top = rect.bottom = -1;
3260     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3261     expect(TRUE, r);
3262     /* padding + stateicon width -> column width */
3263     expect(18, rect.left);
3264     expect(50, rect.right);
3265
3266     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
3267     ok(r != 0, "should return current list handle\n");
3268
3269     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3270     ok(r == 0, "should return zero\n");
3271
3272     item.mask = LVIF_STATE | LVIF_IMAGE;
3273     item.iImage = 1;
3274     item.state = 0;
3275     item.stateMask = ~0;
3276     item.iItem = 0;
3277     item.iSubItem = 0;
3278     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3279     expect(TRUE, r);
3280
3281     /* icon bounds */
3282     rect.left = LVIR_ICON;
3283     rect.right = rect.top = rect.bottom = -1;
3284     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3285     expect(TRUE, r);
3286     /* padding, icon width */
3287     expect(2, rect.left);
3288     expect(18, rect.right);
3289     /* label bounds */
3290     rect.left = LVIR_LABEL;
3291     rect.right = rect.top = rect.bottom = -1;
3292     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3293     expect(TRUE, r);
3294     /* padding + icon width -> column width */
3295     expect(18, rect.left);
3296     expect(50, rect.right);
3297
3298     /* select bounds */
3299     rect.left = LVIR_SELECTBOUNDS;
3300     rect.right = rect.top = rect.bottom = -1;
3301     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3302     expect(TRUE, r);
3303     /* padding, column width */
3304     expect(2, rect.left);
3305     expect(50, rect.right);
3306
3307     /* try with indentation */
3308     item.mask = LVIF_INDENT;
3309     item.iIndent = 1;
3310     item.iItem = 0;
3311     item.iSubItem = 0;
3312     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
3313     expect(TRUE, r);
3314
3315     /* bounds */
3316     rect.left = LVIR_BOUNDS;
3317     rect.right = rect.top = rect.bottom = -1;
3318     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3319     expect(TRUE, r);
3320     /* padding + 1 icon width, column width */
3321     expect(0, rect.left);
3322     expect(150, rect.right);
3323
3324     /* select bounds */
3325     rect.left = LVIR_SELECTBOUNDS;
3326     rect.right = rect.top = rect.bottom = -1;
3327     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3328     expect(TRUE, r);
3329     /* padding + 1 icon width, column width */
3330     expect(2 + 16, rect.left);
3331     expect(50, rect.right);
3332
3333     /* label bounds */
3334     rect.left = LVIR_LABEL;
3335     rect.right = rect.top = rect.bottom = -1;
3336     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3337     expect(TRUE, r);
3338     /* padding + 2 icon widths, column width */
3339     expect(2 + 16*2, rect.left);
3340     expect(50, rect.right);
3341
3342     /* icon bounds */
3343     rect.left = LVIR_ICON;
3344     rect.right = rect.top = rect.bottom = -1;
3345     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3346     expect(TRUE, r);
3347     /* padding + 1 icon width indentation, icon width */
3348     expect(2 + 16, rect.left);
3349     expect(34, rect.right);
3350
3351
3352     DestroyWindow(hwnd);
3353 }
3354
3355 static void test_editbox(void)
3356 {
3357     HWND hwnd, hwndedit, hwndedit2;
3358     LVITEMA item;
3359     DWORD r;
3360     static CHAR testitemA[]  = "testitem";
3361     static CHAR testitem1A[] = "testitem1";
3362     static CHAR buffer[10];
3363
3364     hwnd = create_listview_control(LVS_EDITLABELS);
3365     ok(hwnd != NULL, "failed to create a listview window\n");
3366
3367     insert_column(hwnd, 0);
3368
3369     memset(&item, 0, sizeof(item));
3370     item.mask = LVIF_TEXT;
3371     item.pszText = testitemA;
3372     item.iItem = 0;
3373     item.iSubItem = 0;
3374     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3375     expect(0, r);
3376
3377     /* setting focus is necessary */
3378     SetFocus(hwnd);
3379     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3380     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3381
3382     /* modify initial string */
3383     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3384     expect(TRUE, r);
3385     /* return focus to listview */
3386     SetFocus(hwnd);
3387
3388     memset(&item, 0, sizeof(item));
3389     item.mask = LVIF_TEXT;
3390     item.pszText = buffer;
3391     item.cchTextMax = 10;
3392     item.iItem = 0;
3393     item.iSubItem = 0;
3394     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3395     expect(TRUE, r);
3396
3397     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3398
3399     /* send LVM_EDITLABEL on already created edit */
3400     SetFocus(hwnd);
3401     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3402     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3403     /* focus will be set to edit */
3404     ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
3405     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3406     ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
3407
3408     /* creating label disabled when control isn't focused */
3409     SetFocus(0);
3410     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3411     todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3412
3413     /* check EN_KILLFOCUS handling */
3414     memset(&item, 0, sizeof(item));
3415     item.pszText = testitemA;
3416     item.iItem = 0;
3417     item.iSubItem = 0;
3418     r = SendMessage(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3419     expect(TRUE, r);
3420
3421     SetFocus(hwnd);
3422     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3423     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3424     /* modify edit and notify control that it lost focus */
3425     r = SendMessage(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
3426     expect(TRUE, r);
3427     r = SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
3428     expect(0, r);
3429     memset(&item, 0, sizeof(item));
3430     item.pszText = buffer;
3431     item.cchTextMax = 10;
3432     item.iItem = 0;
3433     item.iSubItem = 0;
3434     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3435     expect(lstrlen(item.pszText), r);
3436     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3437     /* end edit without saving */
3438     r = SendMessage(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
3439     expect(0, r);
3440     memset(&item, 0, sizeof(item));
3441     item.pszText = buffer;
3442     item.cchTextMax = 10;
3443     item.iItem = 0;
3444     item.iSubItem = 0;
3445     r = SendMessage(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
3446     expect(lstrlen(item.pszText), r);
3447     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
3448
3449     /* LVM_EDITLABEL with -1 destroys current edit */
3450     hwndedit = (HWND)SendMessage(hwnd, LVM_GETEDITCONTROL, 0, 0);
3451     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3452     /* no edit present */
3453     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3454     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
3455     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3456     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3457     /* edit present */
3458     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3459     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -1, 0);
3460     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3461     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3462     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3463     /* check another negative value */
3464     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3465     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3466     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3467     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, -2, 0);
3468     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3469     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3470     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3471     /* and value greater than max item index */
3472     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3473     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3474     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
3475     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
3476     hwndedit2 = (HWND)SendMessage(hwnd, LVM_EDITLABEL, r, 0);
3477     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
3478     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
3479     ok(GetFocus() == hwnd, "Expected List to be focused\n");
3480
3481     /* messaging tests */
3482     SetFocus(hwnd);
3483     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3484     blockEdit = FALSE;
3485     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3486     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
3487     /* testing only sizing messages */
3488     ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
3489                 "edit box create - sizing", FALSE);
3490
3491     DestroyWindow(hwnd);
3492 }
3493
3494 static void test_notifyformat(void)
3495 {
3496     HWND hwnd, header;
3497     DWORD r;
3498
3499     hwnd = create_listview_control(0);
3500     ok(hwnd != NULL, "failed to create a listview window\n");
3501
3502     /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
3503        CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
3504     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3505     expect(0, r);
3506     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3507     /* set */
3508     r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
3509     expect(0, r);
3510     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3511     if (r == 1)
3512     {
3513         r = SendMessage(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
3514         expect(1, r);
3515         r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3516         expect(0, r);
3517     }
3518     else
3519     {
3520         win_skip("LVM_GETUNICODEFORMAT is unsupported\n");
3521         DestroyWindow(hwnd);
3522         return;
3523     }
3524
3525     DestroyWindow(hwnd);
3526
3527     /* test failure in parent WM_NOTIFYFORMAT  */
3528     notifyFormat = 0;
3529     hwnd = create_listview_control(0);
3530     ok(hwnd != NULL, "failed to create a listview window\n");
3531     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3532     ok(IsWindow(header), "expected header to be created\n");
3533     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3534     expect(0, r);
3535     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3536     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3537     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
3538     ok(r != 0, "Expected valid format\n");
3539
3540     notifyFormat = NFR_UNICODE;
3541     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3542     expect(NFR_UNICODE, r);
3543     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3544     expect(1, r);
3545     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3546     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3547
3548     notifyFormat = NFR_ANSI;
3549     r = SendMessage(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
3550     expect(NFR_ANSI, r);
3551     r = SendMessage(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3552     expect(0, r);
3553     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3554     ok( r == 1 || broken(r == 0), /* win9x */ "Expected 1, got %d\n", r );
3555
3556     DestroyWindow(hwnd);
3557
3558     /* try different unicode window combination and defaults */
3559     if (!GetModuleHandleW(NULL))
3560     {
3561         win_skip("Additional notify format tests are incompatible with Win9x\n");
3562         return;
3563     }
3564
3565     hwndparentW = create_parent_window(TRUE);
3566     ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
3567     if (!IsWindow(hwndparentW))  return;
3568
3569     notifyFormat = -1;
3570     hwnd = create_listview_controlW(0, hwndparentW);
3571     ok(hwnd != NULL, "failed to create a listview window\n");
3572     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3573     ok(IsWindow(header), "expected header to be created\n");
3574     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3575     expect(1, r);
3576     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3577     expect(1, r);
3578     DestroyWindow(hwnd);
3579     /* receiving error code defaulting to ansi */
3580     notifyFormat = 0;
3581     hwnd = create_listview_controlW(0, hwndparentW);
3582     ok(hwnd != NULL, "failed to create a listview window\n");
3583     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3584     ok(IsWindow(header), "expected header to be created\n");
3585     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3586     expect(0, r);
3587     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3588     expect(1, r);
3589     DestroyWindow(hwnd);
3590     /* receiving ansi code from unicode window, use it */
3591     notifyFormat = NFR_ANSI;
3592     hwnd = create_listview_controlW(0, hwndparentW);
3593     ok(hwnd != NULL, "failed to create a listview window\n");
3594     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3595     ok(IsWindow(header), "expected header to be created\n");
3596     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3597     expect(0, r);
3598     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3599     expect(1, r);
3600     DestroyWindow(hwnd);
3601     /* unicode listview with ansi parent window */
3602     notifyFormat = -1;
3603     hwnd = create_listview_controlW(0, hwndparent);
3604     ok(hwnd != NULL, "failed to create a listview window\n");
3605     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3606     ok(IsWindow(header), "expected header to be created\n");
3607     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3608     expect(0, r);
3609     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3610     expect(1, r);
3611     DestroyWindow(hwnd);
3612     /* unicode listview with ansi parent window, return error code */
3613     notifyFormat = 0;
3614     hwnd = create_listview_controlW(0, hwndparent);
3615     ok(hwnd != NULL, "failed to create a listview window\n");
3616     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3617     ok(IsWindow(header), "expected header to be created\n");
3618     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
3619     expect(0, r);
3620     r = SendMessage(header, HDM_GETUNICODEFORMAT, 0, 0);
3621     expect(1, r);
3622     DestroyWindow(hwnd);
3623
3624     DestroyWindow(hwndparentW);
3625 }
3626
3627 static void test_indentation(void)
3628 {
3629     HWND hwnd;
3630     LVITEMA item;
3631     DWORD r;
3632
3633     hwnd = create_listview_control(0);
3634     ok(hwnd != NULL, "failed to create a listview window\n");
3635
3636     memset(&item, 0, sizeof(item));
3637     item.mask = LVIF_INDENT;
3638     item.iItem = 0;
3639     item.iIndent = I_INDENTCALLBACK;
3640     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3641     expect(0, r);
3642
3643     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3644
3645     item.iItem = 0;
3646     item.mask = LVIF_INDENT;
3647     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
3648     expect(TRUE, r);
3649
3650     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3651                 "get indent dispinfo", FALSE);
3652
3653     DestroyWindow(hwnd);
3654 }
3655
3656 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
3657 {
3658     return 0;
3659 }
3660
3661 static BOOL is_below_comctl_5(void)
3662 {
3663     HWND hwnd;
3664     BOOL ret;
3665
3666     hwnd = create_listview_control(0);
3667     ok(hwnd != NULL, "failed to create a listview window\n");
3668     insert_item(hwnd, 0);
3669
3670     ret = SendMessage(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
3671
3672     DestroyWindow(hwnd);
3673
3674     return !ret;
3675 }
3676
3677 static void test_get_set_view(void)
3678 {
3679     HWND hwnd;
3680     DWORD ret;
3681     DWORD_PTR style;
3682
3683     /* test style->view mapping */
3684     hwnd = create_listview_control(0);
3685     ok(hwnd != NULL, "failed to create a listview window\n");
3686
3687     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3688     expect(LV_VIEW_DETAILS, ret);
3689
3690     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3691     /* LVS_ICON == 0 */
3692     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_REPORT);
3693     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3694     expect(LV_VIEW_ICON, ret);
3695
3696     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3697     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_SMALLICON);
3698     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3699     expect(LV_VIEW_SMALLICON, ret);
3700
3701     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3702     SetWindowLongPtr(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
3703     ret = SendMessage(hwnd, LVM_GETVIEW, 0, 0);
3704     expect(LV_VIEW_LIST, ret);
3705
3706     /* switching view doesn't touch window style */
3707     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
3708     expect(1, ret);
3709     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3710     ok(style & LVS_LIST, "Expected style to be preserved\n");
3711     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
3712     expect(1, ret);
3713     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3714     ok(style & LVS_LIST, "Expected style to be preserved\n");
3715     ret = SendMessage(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
3716     expect(1, ret);
3717     style = GetWindowLongPtr(hwnd, GWL_STYLE);
3718     ok(style & LVS_LIST, "Expected style to be preserved\n");
3719
3720     DestroyWindow(hwnd);
3721 }
3722
3723 static void test_canceleditlabel(void)
3724 {
3725     HWND hwnd, hwndedit;
3726     DWORD ret;
3727     CHAR buff[10];
3728     LVITEMA itema;
3729     static CHAR test[] = "test";
3730     static const CHAR test1[] = "test1";
3731
3732     hwnd = create_listview_control(LVS_EDITLABELS);
3733     ok(hwnd != NULL, "failed to create a listview window\n");
3734
3735     insert_item(hwnd, 0);
3736
3737     /* try without edit created */
3738     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3739     expect(TRUE, ret);
3740
3741     /* cancel without data change */
3742     SetFocus(hwnd);
3743     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3744     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3745     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3746     expect(TRUE, ret);
3747     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3748
3749     /* cancel after data change */
3750     memset(&itema, 0, sizeof(itema));
3751     itema.pszText = test;
3752     ret = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&itema);
3753     expect(TRUE, ret);
3754     SetFocus(hwnd);
3755     hwndedit = (HWND)SendMessage(hwnd, LVM_EDITLABEL, 0, 0);
3756     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
3757     ret = SetWindowText(hwndedit, test1);
3758     ok(ret != 0, "Expected edit text to change\n");
3759     ret = SendMessage(hwnd, LVM_CANCELEDITLABEL, 0, 0);
3760     expect(TRUE, ret);
3761     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
3762     memset(&itema, 0, sizeof(itema));
3763     itema.pszText = buff;
3764     itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
3765     ret = SendMessage(hwnd, LVM_GETITEMTEXT, 0, (LPARAM)&itema);
3766     expect(5, ret);
3767     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
3768
3769     DestroyWindow(hwnd);
3770 }
3771
3772 static void test_mapidindex(void)
3773 {
3774     HWND hwnd;
3775     DWORD ret;
3776
3777     /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
3778     hwnd = create_listview_control(LVS_OWNERDATA);
3779     ok(hwnd != NULL, "failed to create a listview window\n");
3780     insert_item(hwnd, 0);
3781     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3782     expect(-1, ret);
3783     DestroyWindow(hwnd);
3784
3785     hwnd = create_listview_control(0);
3786     ok(hwnd != NULL, "failed to create a listview window\n");
3787
3788     /* LVM_MAPINDEXTOID with invalid index */
3789     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3790     expect(-1, ret);
3791
3792     insert_item(hwnd, 0);
3793     insert_item(hwnd, 1);
3794
3795     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, -1, 0);
3796     expect(-1, ret);
3797     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 2, 0);
3798     expect(-1, ret);
3799
3800     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3801     expect(0, ret);
3802     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3803     expect(1, ret);
3804     /* remove 0 indexed item, id retained */
3805     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
3806     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 0, 0);
3807     expect(1, ret);
3808     /* new id starts from previous value */
3809     insert_item(hwnd, 1);
3810     ret = SendMessage(hwnd, LVM_MAPINDEXTOID, 1, 0);
3811     expect(2, ret);
3812
3813     /* get index by id */
3814     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, -1, 0);
3815     expect(-1, ret);
3816     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 0, 0);
3817     expect(-1, ret);
3818     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 1, 0);
3819     expect(0, ret);
3820     ret = SendMessage(hwnd, LVM_MAPIDTOINDEX, 2, 0);
3821     expect(1, ret);
3822
3823     DestroyWindow(hwnd);
3824 }
3825
3826 static void test_getitemspacing(void)
3827 {
3828     HWND hwnd;
3829     DWORD ret;
3830     INT cx, cy;
3831     HIMAGELIST himl;
3832     HBITMAP hbmp;
3833     LVITEMA itema;
3834
3835     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
3836     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
3837
3838     /* LVS_ICON */
3839     hwnd = create_custom_listview_control(0);
3840     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3841 todo_wine {
3842     expect(cx, LOWORD(ret));
3843     expect(cy, HIWORD(ret));
3844 }
3845     /* now try with icons */
3846     himl = ImageList_Create(40, 40, 0, 4, 4);
3847     ok(himl != NULL, "failed to create imagelist\n");
3848     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
3849     ok(hbmp != NULL, "failed to create bitmap\n");
3850     ret = ImageList_Add(himl, hbmp, 0);
3851     expect(0, ret);
3852     ret = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
3853     expect(0, ret);
3854
3855     itema.mask = LVIF_IMAGE;
3856     itema.iImage = 0;
3857     itema.iItem = 0;
3858     itema.iSubItem = 0;
3859     ret = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM)&itema);
3860     expect(0, ret);
3861     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3862 todo_wine {
3863     /* spacing + icon size returned */
3864     expect(cx + 40, LOWORD(ret));
3865     expect(cy + 40, HIWORD(ret));
3866 }
3867     DestroyWindow(hwnd);
3868     /* LVS_SMALLICON */
3869     hwnd = create_custom_listview_control(LVS_SMALLICON);
3870     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3871 todo_wine {
3872     expect(cx, LOWORD(ret));
3873     expect(cy, HIWORD(ret));
3874 }
3875     DestroyWindow(hwnd);
3876     /* LVS_REPORT */
3877     hwnd = create_custom_listview_control(LVS_REPORT);
3878     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3879 todo_wine {
3880     expect(cx, LOWORD(ret));
3881     expect(cy, HIWORD(ret));
3882 }
3883     DestroyWindow(hwnd);
3884     /* LVS_LIST */
3885     hwnd = create_custom_listview_control(LVS_LIST);
3886     ret = SendMessage(hwnd, LVM_GETITEMSPACING, FALSE, 0);
3887 todo_wine {
3888     expect(cx, LOWORD(ret));
3889     expect(cy, HIWORD(ret));
3890 }
3891     DestroyWindow(hwnd);
3892 }
3893
3894 static void test_getcolumnwidth(void)
3895 {
3896     HWND hwnd;
3897     DWORD ret;
3898     DWORD_PTR style;
3899     LVCOLUMNA col;
3900
3901     /* default column width */
3902     hwnd = create_custom_listview_control(0);
3903     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3904     expect(0, ret);
3905     style = GetWindowLong(hwnd, GWL_STYLE);
3906     SetWindowLong(hwnd, GWL_STYLE, style | LVS_LIST);
3907     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3908     todo_wine expect(8, ret);
3909     style = GetWindowLong(hwnd, GWL_STYLE) & ~LVS_LIST;
3910     SetWindowLong(hwnd, GWL_STYLE, style | LVS_REPORT);
3911     col.mask = 0;
3912     ret = SendMessage(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
3913     expect(0, ret);
3914     ret = SendMessage(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
3915     expect(10, ret);
3916     DestroyWindow(hwnd);
3917 }
3918
3919 static void test_scrollnotify(void)
3920 {
3921     HWND hwnd;
3922     DWORD ret;
3923
3924     hwnd = create_listview_control(0);
3925
3926     insert_column(hwnd, 0);
3927     insert_column(hwnd, 1);
3928     insert_item(hwnd, 0);
3929
3930     /* make it scrollable - resize */
3931     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3932     expect(TRUE, ret);
3933     ret = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3934     expect(TRUE, ret);
3935
3936     /* try with dummy call */
3937     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3938     ret = SendMessage(hwnd, LVM_SCROLL, 0, 0);
3939     expect(TRUE, ret);
3940     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3941                 "scroll notify 1", TRUE);
3942
3943     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3944     ret = SendMessage(hwnd, LVM_SCROLL, 1, 0);
3945     expect(TRUE, ret);
3946     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3947                 "scroll notify 2", TRUE);
3948
3949     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3950     ret = SendMessage(hwnd, LVM_SCROLL, 1, 1);
3951     expect(TRUE, ret);
3952     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
3953                 "scroll notify 3", TRUE);
3954
3955     DestroyWindow(hwnd);
3956 }
3957
3958 static void test_LVS_EX_TRANSPARENTBKGND(void)
3959 {
3960     HWND hwnd;
3961     DWORD ret;
3962     HDC hdc;
3963
3964     hwnd = create_listview_control(0);
3965
3966     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
3967     expect(TRUE, ret);
3968
3969     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
3970                                                     LVS_EX_TRANSPARENTBKGND);
3971
3972     ret = SendMessage(hwnd, LVM_GETBKCOLOR, 0, 0);
3973     if (ret != CLR_NONE)
3974     {
3975         win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
3976         DestroyWindow(hwnd);
3977         return;
3978     }
3979
3980     /* try to set some back color and check this style bit */
3981     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
3982     expect(TRUE, ret);
3983     ret = SendMessage(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
3984     ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
3985
3986     /* now test what this style actually does */
3987     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
3988                                                     LVS_EX_TRANSPARENTBKGND);
3989
3990     hdc = GetWindowDC(hwndparent);
3991
3992     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3993     SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
3994     ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
3995                 "LVS_EX_TRANSPARENTBKGND parent", FALSE);
3996
3997     ReleaseDC(hwndparent, hdc);
3998
3999     DestroyWindow(hwnd);
4000 }
4001
4002 START_TEST(listview)
4003 {
4004     HMODULE hComctl32;
4005     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
4006
4007     ULONG_PTR ctx_cookie;
4008     HWND hwnd;
4009
4010     hComctl32 = GetModuleHandleA("comctl32.dll");
4011     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
4012     if (pInitCommonControlsEx)
4013     {
4014         INITCOMMONCONTROLSEX iccex;
4015         iccex.dwSize = sizeof(iccex);
4016         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
4017         pInitCommonControlsEx(&iccex);
4018     }
4019     else
4020         InitCommonControls();
4021
4022     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
4023
4024     hwndparent = create_parent_window(FALSE);
4025     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4026
4027     g_is_below_5 = is_below_comctl_5();
4028
4029     test_images();
4030     test_checkboxes();
4031     test_items();
4032     test_create();
4033     test_redraw();
4034     test_customdraw();
4035     test_icon_spacing();
4036     test_color();
4037     test_item_count();
4038     test_item_position();
4039     test_columns();
4040     test_getorigin();
4041     test_multiselect();
4042     test_getitemrect();
4043     test_subitem_rect();
4044     test_sorting();
4045     test_ownerdata();
4046     test_norecompute();
4047     test_nosortheader();
4048     test_setredraw();
4049     test_hittest();
4050     test_getviewrect();
4051     test_getitemposition();
4052     test_columnscreation();
4053     test_editbox();
4054     test_notifyformat();
4055     test_indentation();
4056     test_getitemspacing();
4057     test_getcolumnwidth();
4058
4059     if (!load_v6_module(&ctx_cookie))
4060     {
4061         DestroyWindow(hwndparent);
4062         return;
4063     }
4064
4065     /* this is a XP SP3 failure workaround */
4066     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
4067                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT,
4068                            0, 0, 100, 100,
4069                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
4070     if (!IsWindow(hwnd))
4071     {
4072         win_skip("FIXME: failed to create ListView window.\n");
4073         unload_v6_module(ctx_cookie);
4074         DestroyWindow(hwndparent);
4075         return;
4076     }
4077     else
4078         DestroyWindow(hwnd);
4079
4080     /* comctl32 version 6 tests start here */
4081     test_get_set_view();
4082     test_canceleditlabel();
4083     test_mapidindex();
4084     test_scrollnotify();
4085     test_LVS_EX_TRANSPARENTBKGND();
4086
4087     unload_v6_module(ctx_cookie);
4088
4089     DestroyWindow(hwndparent);
4090 }