fusion: CompareAssemblyIdentity() and GetAssemblyIdentityFromFile() are unused stubs...
[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 "msg.h"
28
29 #define PARENT_SEQ_INDEX       0
30 #define PARENT_FULL_SEQ_INDEX  1
31 #define LISTVIEW_SEQ_INDEX     2
32 #define NUM_MSG_SEQUENCES      3
33
34 #define LISTVIEW_ID 0
35 #define HEADER_ID   1
36
37 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
38 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
39        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
40
41 HWND hwndparent;
42
43 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
44
45 static const struct message create_parent_wnd_seq[] = {
46     { WM_GETMINMAXINFO,     sent },
47     { WM_NCCREATE,          sent },
48     { WM_NCCALCSIZE,        sent|wparam, 0 },
49     { WM_CREATE,            sent },
50     { WM_SHOWWINDOW,        sent|wparam, 1 },
51     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
52     { WM_QUERYNEWPALETTE,   sent|optional },
53     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
54     { WM_WINDOWPOSCHANGED,  sent|optional },
55     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
56     { WM_ACTIVATEAPP,       sent|wparam, 1 },
57     { WM_NCACTIVATE,        sent|wparam, 1 },
58     { WM_ACTIVATE,          sent|wparam, 1 },
59     { WM_IME_SETCONTEXT,    sent|wparam|defwinproc|optional, 1 },
60     { WM_IME_NOTIFY,        sent|defwinproc|optional },
61     { WM_SETFOCUS,          sent|wparam|defwinproc, 0 },
62     /* Win9x adds SWP_NOZORDER below */
63     { WM_WINDOWPOSCHANGED,  sent, /*|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE*/ },
64     { WM_NCCALCSIZE,        sent|wparam|optional, 1 },
65     { WM_SIZE,              sent },
66     { WM_MOVE,              sent },
67     { 0 }
68 };
69
70 static const struct message redraw_listview_seq[] = {
71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
74     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, HEADER_ID },
75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
77     { WM_ERASEBKGND, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
78     { 0 }
79 };
80
81 static const struct message listview_icon_spacing_seq[] = {
82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
85     { 0 }
86 };
87
88 static const struct message listview_color_seq[] = {
89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
90     { LVM_GETBKCOLOR,     sent },
91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
92     { LVM_GETTEXTCOLOR,   sent },
93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
94     { LVM_GETTEXTBKCOLOR, sent },
95
96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
97     { LVM_GETBKCOLOR,     sent },
98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { LVM_GETITEMCOUNT,   sent },
127     { LVM_DELETEALLITEMS, sent },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_INSERTITEM,     sent },
130     { LVM_INSERTITEM,     sent },
131     { LVM_GETITEMCOUNT,   sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { 0 }
135 };
136
137 static const struct message listview_itempos_seq[] = {
138     { LVM_INSERTITEM,      sent },
139     { LVM_INSERTITEM,      sent },
140     { LVM_INSERTITEM,      sent },
141     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
142     { LVM_GETITEMPOSITION, sent|wparam,        1 },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
144     { LVM_GETITEMPOSITION, sent|wparam,        2 },
145     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
146     { LVM_GETITEMPOSITION, sent|wparam,        0 },
147     { 0 }
148 };
149
150 static const struct message listview_ownerdata_switchto_seq[] = {
151     { WM_STYLECHANGING,    sent },
152     { WM_STYLECHANGED,     sent },
153     { 0 }
154 };
155
156 static const struct message listview_getorderarray_seq[] = {
157     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
158     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
159     { 0 }
160 };
161
162 static const struct message empty_seq[] = {
163     { 0 }
164 };
165
166 static const struct message forward_erasebkgnd_parent_seq[] = {
167     { WM_ERASEBKGND, sent },
168     { 0 }
169 };
170
171 static const struct message ownderdata_select_focus_parent_seq[] = {
172     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
173     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
174     { 0 }
175 };
176
177 static const struct message textcallback_set_again_parent_seq[] = {
178     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
179     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
180     { 0 }
181 };
182
183 static const struct message single_getdispinfo_parent_seq[] = {
184     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
185     { 0 }
186 };
187
188 struct subclass_info
189 {
190     WNDPROC oldproc;
191 };
192
193 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
194 {
195     static LONG defwndproc_counter = 0;
196     LRESULT ret;
197     struct message msg;
198
199     msg.message = message;
200     msg.flags = sent|wparam|lparam;
201     if (defwndproc_counter) msg.flags |= defwinproc;
202     msg.wParam = wParam;
203     msg.lParam = lParam;
204     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
205
206     /* log system messages, except for painting */
207     if (message < WM_USER &&
208         message != WM_PAINT &&
209         message != WM_ERASEBKGND &&
210         message != WM_NCPAINT &&
211         message != WM_NCHITTEST &&
212         message != WM_GETTEXT &&
213         message != WM_GETICON &&
214         message != WM_DEVICECHANGE)
215     {
216         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
217
218         add_message(sequences, PARENT_SEQ_INDEX, &msg);
219     }
220     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
221
222     defwndproc_counter++;
223     ret = DefWindowProcA(hwnd, message, wParam, lParam);
224     defwndproc_counter--;
225
226     return ret;
227 }
228
229 static BOOL register_parent_wnd_class(void)
230 {
231     WNDCLASSA cls;
232
233     cls.style = 0;
234     cls.lpfnWndProc = parent_wnd_proc;
235     cls.cbClsExtra = 0;
236     cls.cbWndExtra = 0;
237     cls.hInstance = GetModuleHandleA(NULL);
238     cls.hIcon = 0;
239     cls.hCursor = LoadCursorA(0, IDC_ARROW);
240     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
241     cls.lpszMenuName = NULL;
242     cls.lpszClassName = "Listview test parent class";
243     return RegisterClassA(&cls);
244 }
245
246 static HWND create_parent_window(void)
247 {
248     if (!register_parent_wnd_class())
249         return NULL;
250
251     return CreateWindowEx(0, "Listview test parent class",
252                           "Listview test parent window",
253                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
254                           WS_MAXIMIZEBOX | WS_VISIBLE,
255                           0, 0, 100, 100,
256                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
257 }
258
259 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
260 {
261     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
262     static LONG defwndproc_counter = 0;
263     LRESULT ret;
264     struct message msg;
265
266     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
267
268     /* some debug output for style changing */
269     if ((message == WM_STYLECHANGING ||
270          message == WM_STYLECHANGED) && lParam)
271     {
272         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
273         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
274     }
275
276     msg.message = message;
277     msg.flags = sent|wparam|lparam;
278     if (defwndproc_counter) msg.flags |= defwinproc;
279     msg.wParam = wParam;
280     msg.lParam = lParam;
281     msg.id = LISTVIEW_ID;
282     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
283
284     defwndproc_counter++;
285     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
286     defwndproc_counter--;
287     return ret;
288 }
289
290 static HWND create_listview_control(DWORD style)
291 {
292     struct subclass_info *info;
293     HWND hwnd;
294     RECT rect;
295
296     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
297     if (!info)
298         return NULL;
299
300     GetClientRect(hwndparent, &rect);
301     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
302                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
303                            0, 0, rect.right, rect.bottom,
304                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
305     ok(hwnd != NULL, "gle=%d\n", GetLastError());
306
307     if (!hwnd)
308     {
309         HeapFree(GetProcessHeap(), 0, info);
310         return NULL;
311     }
312
313     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
314                                             (LONG_PTR)listview_subclass_proc);
315     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
316
317     return hwnd;
318 }
319
320 static HWND create_custom_listview_control(DWORD style)
321 {
322     struct subclass_info *info;
323     HWND hwnd;
324     RECT rect;
325
326     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
327     if (!info)
328         return NULL;
329
330     GetClientRect(hwndparent, &rect);
331     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
332                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
333                            0, 0, rect.right, rect.bottom,
334                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
335     ok(hwnd != NULL, "gle=%d\n", GetLastError());
336
337     if (!hwnd)
338     {
339         HeapFree(GetProcessHeap(), 0, info);
340         return NULL;
341     }
342
343     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
344                                             (LONG_PTR)listview_subclass_proc);
345     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
346
347     return hwnd;
348 }
349
350 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
351 {
352     struct subclass_info *info = (struct subclass_info *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
353     static LONG defwndproc_counter = 0;
354     LRESULT ret;
355     struct message msg;
356
357     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
358
359     msg.message = message;
360     msg.flags = sent|wparam|lparam;
361     if (defwndproc_counter) msg.flags |= defwinproc;
362     msg.wParam = wParam;
363     msg.lParam = lParam;
364     msg.id = HEADER_ID;
365     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
366
367     defwndproc_counter++;
368     ret = CallWindowProcA(info->oldproc, hwnd, message, wParam, lParam);
369     defwndproc_counter--;
370     return ret;
371 }
372
373 static HWND subclass_header(HWND hwndListview)
374 {
375     struct subclass_info *info;
376     HWND hwnd;
377
378     info = HeapAlloc(GetProcessHeap(), 0, sizeof(struct subclass_info));
379     if (!info)
380         return NULL;
381
382     hwnd = ListView_GetHeader(hwndListview);
383     info->oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
384                                             (LONG_PTR)header_subclass_proc);
385     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)info);
386
387     return hwnd;
388 }
389
390 static void test_images(void)
391 {
392     HWND hwnd;
393     DWORD r;
394     LVITEM item;
395     HIMAGELIST himl;
396     HBITMAP hbmp;
397     RECT r1, r2;
398     static CHAR hello[] = "hello";
399
400     himl = ImageList_Create(40, 40, 0, 4, 4);
401     ok(himl != NULL, "failed to create imagelist\n");
402
403     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
404     ok(hbmp != NULL, "failed to create bitmap\n");
405
406     r = ImageList_Add(himl, hbmp, 0);
407     ok(r == 0, "should be zero\n");
408
409     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
410                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
411     ok(hwnd != NULL, "failed to create listview window\n");
412
413     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, 0x940);
414     ok(r == 0, "should return zero\n");
415
416     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
417     ok(r == 0, "should return zero\n");
418
419     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
420     /* returns dimensions */
421
422     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
423     ok(r == 0, "should be zero items\n");
424
425     item.mask = LVIF_IMAGE | LVIF_TEXT;
426     item.iItem = 0;
427     item.iSubItem = 1;
428     item.iImage = 0;
429     item.pszText = 0;
430     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
431     ok(r == -1, "should fail\n");
432
433     item.iSubItem = 0;
434     item.pszText = hello;
435     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
436     ok(r == 0, "should not fail\n");
437
438     memset(&r1, 0, sizeof r1);
439     r1.left = LVIR_ICON;
440     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
441
442     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
443     ok(r == TRUE, "should not fail\n");
444
445     item.iSubItem = 0;
446     item.pszText = hello;
447     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
448     ok(r == 0, "should not fail\n");
449
450     memset(&r2, 0, sizeof r2);
451     r2.left = LVIR_ICON;
452     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
453
454     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
455
456     DestroyWindow(hwnd);
457 }
458
459 static void test_checkboxes(void)
460 {
461     HWND hwnd;
462     LVITEMA item;
463     DWORD r;
464     static CHAR text[]  = "Text",
465                 text2[] = "Text2",
466                 text3[] = "Text3";
467
468     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
469                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
470     ok(hwnd != NULL, "failed to create listview window\n");
471
472     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
473     item.mask = LVIF_TEXT | LVIF_STATE;
474     item.stateMask = 0xffff;
475     item.state = 0xfccc;
476     item.iItem = 0;
477     item.iSubItem = 0;
478     item.pszText = text;
479     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
480     ok(r == 0, "ret %d\n", r);
481
482     item.iItem = 0;
483     item.mask = LVIF_STATE;
484     item.stateMask = 0xffff;
485     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
486     ok(item.state == 0xfccc, "state %x\n", item.state);
487
488     /* Don't set LVIF_STATE */
489     item.mask = LVIF_TEXT;
490     item.stateMask = 0xffff;
491     item.state = 0xfccc;
492     item.iItem = 1;
493     item.iSubItem = 0;
494     item.pszText = text;
495     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
496     ok(r == 1, "ret %d\n", r);
497
498     item.iItem = 1;
499     item.mask = LVIF_STATE;
500     item.stateMask = 0xffff;
501     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
502     ok(item.state == 0, "state %x\n", item.state);
503
504     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
505     ok(r == 0, "should return zero\n");
506
507     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
508     item.iItem = 0;
509     item.mask = LVIF_STATE;
510     item.stateMask = 0xffff;
511     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
512     ok(item.state == 0x1ccc, "state %x\n", item.state);
513
514     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
515     item.iItem = 2;
516     item.mask = LVIF_TEXT;
517     item.state = 0;
518     item.pszText = text2;
519     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
520     ok(r == 2, "ret %d\n", r);
521
522     item.iItem = 2;
523     item.mask = LVIF_STATE;
524     item.stateMask = 0xffff;
525     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
526     ok(item.state == 0x1000, "state %x\n", item.state);
527
528     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
529     item.iItem = 3;
530     item.mask = LVIF_TEXT | LVIF_STATE;
531     item.stateMask = 0xffff;
532     item.state = 0x2aaa;
533     item.pszText = text3;
534     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
535     ok(r == 3, "ret %d\n", r);
536
537     item.iItem = 3;
538     item.mask = LVIF_STATE;
539     item.stateMask = 0xffff;
540     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
541     ok(item.state == 0x1aaa, "state %x\n", item.state);
542
543     /* Set an item's state to checked */
544     item.iItem = 3;
545     item.mask = LVIF_STATE;
546     item.stateMask = 0xf000;
547     item.state = 0x2000;
548     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
549
550     item.iItem = 3;
551     item.mask = LVIF_STATE;
552     item.stateMask = 0xffff;
553     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
554     ok(item.state == 0x2aaa, "state %x\n", item.state);
555
556     /* Check that only the bits we asked for are returned,
557      * and that all the others are set to zero
558      */
559     item.iItem = 3;
560     item.mask = LVIF_STATE;
561     item.stateMask = 0xf000;
562     item.state = 0xffff;
563     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
564     ok(item.state == 0x2000, "state %x\n", item.state);
565
566     /* Set the style again and check that doesn't change an item's state */
567     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
568     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
569
570     item.iItem = 3;
571     item.mask = LVIF_STATE;
572     item.stateMask = 0xffff;
573     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
574     ok(item.state == 0x2aaa, "state %x\n", item.state);
575
576     /* Unsetting the checkbox extended style doesn't change an item's state */
577     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
578     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
579
580     item.iItem = 3;
581     item.mask = LVIF_STATE;
582     item.stateMask = 0xffff;
583     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
584     ok(item.state == 0x2aaa, "state %x\n", item.state);
585
586     /* Now setting the style again will change an item's state */
587     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
588     ok(r == 0, "ret %x\n", r);
589
590     item.iItem = 3;
591     item.mask = LVIF_STATE;
592     item.stateMask = 0xffff;
593     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
594     ok(item.state == 0x1aaa, "state %x\n", item.state);
595
596     /* Toggle checkbox tests (bug 9934) */
597     memset (&item, 0xcc, sizeof(item));
598     item.mask = LVIF_STATE;
599     item.iItem = 3;
600     item.iSubItem = 0;
601     item.state = LVIS_FOCUSED;
602     item.stateMask = LVIS_FOCUSED;
603     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
604     expect(1, r);
605
606     item.iItem = 3;
607     item.mask = LVIF_STATE;
608     item.stateMask = 0xffff;
609     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
610     ok(item.state == 0x1aab, "state %x\n", item.state);
611
612     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
613     expect(0, r);
614     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
615     expect(0, r);
616
617     item.iItem = 3;
618     item.mask = LVIF_STATE;
619     item.stateMask = 0xffff;
620     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
621     ok(item.state == 0x2aab, "state %x\n", item.state);
622
623     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
624     expect(0, r);
625     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
626     expect(0, r);
627
628     item.iItem = 3;
629     item.mask = LVIF_STATE;
630     item.stateMask = 0xffff;
631     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
632     ok(item.state == 0x1aab, "state %x\n", item.state);
633
634     DestroyWindow(hwnd);
635 }
636
637 static void insert_column(HWND hwnd, int idx)
638 {
639     LVCOLUMN column;
640     DWORD rc;
641
642     memset(&column, 0xcc, sizeof(column));
643     column.mask = LVCF_SUBITEM;
644     column.iSubItem = idx;
645
646     rc = ListView_InsertColumn(hwnd, idx, &column);
647     expect(idx, rc);
648 }
649
650 static void insert_item(HWND hwnd, int idx)
651 {
652     static CHAR text[] = "foo";
653
654     LVITEMA item;
655     DWORD rc;
656
657     memset(&item, 0xcc, sizeof (item));
658     item.mask = LVIF_TEXT;
659     item.iItem = idx;
660     item.iSubItem = 0;
661     item.pszText = text;
662
663     rc = ListView_InsertItem(hwnd, &item);
664     expect(idx, rc);
665 }
666
667 static void test_items(void)
668 {
669     const LPARAM lparamTest = 0x42;
670     HWND hwnd;
671     LVITEMA item;
672     DWORD r;
673     static CHAR text[] = "Text";
674
675     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
676                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
677     ok(hwnd != NULL, "failed to create listview window\n");
678
679     /*
680      * Test setting/getting item params
681      */
682
683     /* Set up two columns */
684     insert_column(hwnd, 0);
685     insert_column(hwnd, 1);
686
687     /* LVIS_SELECTED with zero stateMask */
688     /* set */
689     memset (&item, 0, sizeof (item));
690     item.mask = LVIF_STATE;
691     item.state = LVIS_SELECTED;
692     item.stateMask = 0;
693     item.iItem = 0;
694     item.iSubItem = 0;
695     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
696     ok(r == 0, "ret %d\n", r);
697     /* get */
698     memset (&item, 0xcc, sizeof (item));
699     item.mask = LVIF_STATE;
700     item.stateMask = LVIS_SELECTED;
701     item.state = 0;
702     item.iItem = 0;
703     item.iSubItem = 0;
704     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
705     ok(r != 0, "ret %d\n", r);
706     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
707     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
708
709     /* LVIS_SELECTED with zero stateMask */
710     /* set */
711     memset (&item, 0, sizeof (item));
712     item.mask = LVIF_STATE;
713     item.state = LVIS_FOCUSED;
714     item.stateMask = 0;
715     item.iItem = 0;
716     item.iSubItem = 0;
717     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
718     ok(r == 0, "ret %d\n", r);
719     /* get */
720     memset (&item, 0xcc, sizeof (item));
721     item.mask = LVIF_STATE;
722     item.stateMask = LVIS_FOCUSED;
723     item.state = 0;
724     item.iItem = 0;
725     item.iSubItem = 0;
726     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
727     ok(r != 0, "ret %d\n", r);
728     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
729     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
730
731     /* LVIS_CUT with LVIS_FOCUSED stateMask */
732     /* set */
733     memset (&item, 0, sizeof (item));
734     item.mask = LVIF_STATE;
735     item.state = LVIS_CUT;
736     item.stateMask = LVIS_FOCUSED;
737     item.iItem = 0;
738     item.iSubItem = 0;
739     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
740     ok(r == 0, "ret %d\n", r);
741     /* get */
742     memset (&item, 0xcc, sizeof (item));
743     item.mask = LVIF_STATE;
744     item.stateMask = LVIS_CUT;
745     item.state = 0;
746     item.iItem = 0;
747     item.iSubItem = 0;
748     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
749     ok(r != 0, "ret %d\n", r);
750     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
751     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
752
753     /* Insert an item with just a param */
754     memset (&item, 0xcc, sizeof (item));
755     item.mask = LVIF_PARAM;
756     item.iItem = 0;
757     item.iSubItem = 0;
758     item.lParam = lparamTest;
759     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
760     ok(r == 0, "ret %d\n", r);
761
762     /* Test getting of the param */
763     memset (&item, 0xcc, sizeof (item));
764     item.mask = LVIF_PARAM;
765     item.iItem = 0;
766     item.iSubItem = 0;
767     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
768     ok(r != 0, "ret %d\n", r);
769     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
770
771     /* Set up a subitem */
772     memset (&item, 0xcc, sizeof (item));
773     item.mask = LVIF_TEXT;
774     item.iItem = 0;
775     item.iSubItem = 1;
776     item.pszText = text;
777     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
778     ok(r != 0, "ret %d\n", r);
779
780     /* Query param from subitem: returns main item param */
781     memset (&item, 0xcc, sizeof (item));
782     item.mask = LVIF_PARAM;
783     item.iItem = 0;
784     item.iSubItem = 1;
785     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
786     ok(r != 0, "ret %d\n", r);
787     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
788
789     /* Set up param on first subitem: no effect */
790     memset (&item, 0xcc, sizeof (item));
791     item.mask = LVIF_PARAM;
792     item.iItem = 0;
793     item.iSubItem = 1;
794     item.lParam = lparamTest+1;
795     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
796     ok(r == 0, "ret %d\n", r);
797
798     /* Query param from subitem again: should still return main item param */
799     memset (&item, 0xcc, sizeof (item));
800     item.mask = LVIF_PARAM;
801     item.iItem = 0;
802     item.iSubItem = 1;
803     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
804     ok(r != 0, "ret %d\n", r);
805     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
806
807     /**** Some tests of state highlighting ****/
808     memset (&item, 0xcc, sizeof (item));
809     item.mask = LVIF_STATE;
810     item.iItem = 0;
811     item.iSubItem = 0;
812     item.state = LVIS_SELECTED;
813     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
814     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
815     ok(r != 0, "ret %d\n", r);
816     item.iSubItem = 1;
817     item.state = LVIS_DROPHILITED;
818     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
819     ok(r != 0, "ret %d\n", r);
820
821     memset (&item, 0xcc, sizeof (item));
822     item.mask = LVIF_STATE;
823     item.iItem = 0;
824     item.iSubItem = 0;
825     item.stateMask = -1;
826     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
827     ok(r != 0, "ret %d\n", r);
828     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
829     item.iSubItem = 1;
830     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
831     ok(r != 0, "ret %d\n", r);
832     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
833
834     /* some notnull but meaningless masks */
835     memset (&item, 0, sizeof(item));
836     item.mask = LVIF_NORECOMPUTE;
837     item.iItem = 0;
838     item.iSubItem = 0;
839     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
840     ok(r != 0, "ret %d\n", r);
841     memset (&item, 0, sizeof(item));
842     item.mask = LVIF_DI_SETITEM;
843     item.iItem = 0;
844     item.iSubItem = 0;
845     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
846     ok(r != 0, "ret %d\n", r);
847
848     /* set text to callback value already having it */
849     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
850     expect(TRUE, r);
851     memset (&item, 0, sizeof (item));
852     item.mask  = LVIF_TEXT;
853     item.pszText = LPSTR_TEXTCALLBACK;
854     item.iItem = 0;
855     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
856     ok(r == 0, "ret %d\n", r);
857     memset (&item, 0, sizeof (item));
858
859     flush_sequences(sequences, NUM_MSG_SEQUENCES);
860
861     item.pszText = LPSTR_TEXTCALLBACK;
862     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
863     expect(TRUE, r);
864
865     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
866                 "check callback text comparison rule", TRUE);
867
868     DestroyWindow(hwnd);
869 }
870
871 static void test_columns(void)
872 {
873     HWND hwnd, hwndheader;
874     LVCOLUMN column;
875     DWORD rc;
876     INT order[2];
877
878     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
879                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
880     ok(hwnd != NULL, "failed to create listview window\n");
881
882     /* Add a column with no mask */
883     memset(&column, 0xcc, sizeof(column));
884     column.mask = 0;
885     rc = ListView_InsertColumn(hwnd, 0, &column);
886     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
887
888     /* Check its width */
889     rc = ListView_GetColumnWidth(hwnd, 0);
890     ok(rc==10 ||
891        broken(rc==0), /* win9x */
892        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
893
894     DestroyWindow(hwnd);
895
896     /* LVM_GETCOLUMNORDERARRAY */
897     hwnd = create_listview_control(0);
898     hwndheader = subclass_header(hwnd);
899
900     memset(&column, 0, sizeof(column));
901     column.mask = LVCF_WIDTH;
902     column.cx = 100;
903     rc = ListView_InsertColumn(hwnd, 0, &column);
904     ok(rc == 0, "Inserting column failed with %d\n", rc);
905
906     column.cx = 200;
907     rc = ListView_InsertColumn(hwnd, 1, &column);
908     ok(rc == 1, "Inserting column failed with %d\n", rc);
909
910     flush_sequences(sequences, NUM_MSG_SEQUENCES);
911
912     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
913     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
914     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
915     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
916
917     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
918
919     DestroyWindow(hwnd);
920 }
921 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
922 static WNDPROC listviewWndProc;
923 static HIMAGELIST test_create_imagelist;
924
925 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
926 {
927     LRESULT ret;
928
929     if (uMsg == WM_CREATE)
930     {
931         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
932         lpcs->style |= LVS_REPORT;
933     }
934     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
935     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
936     return ret;
937 }
938
939 static void test_create(void)
940 {
941     HWND hList;
942     HWND hHeader;
943     LONG_PTR ret;
944     LONG r;
945     LVCOLUMNA col;
946     RECT rect;
947     WNDCLASSEX cls;
948     cls.cbSize = sizeof(WNDCLASSEX);
949     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
950     listviewWndProc = cls.lpfnWndProc;
951     cls.lpfnWndProc = create_test_wndproc;
952     cls.lpszClassName = "MyListView32";
953     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
954
955     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
956     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
957     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
958     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
959     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
960     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
961     DestroyWindow(hList);
962
963     /* header isn't created on LVS_ICON and LVS_LIST styles */
964     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
965                           GetModuleHandle(NULL), 0);
966     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
967     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
968     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
969     /* insert column */
970     memset(&col, 0, sizeof(LVCOLUMNA));
971     col.mask = LVCF_WIDTH;
972     col.cx = 100;
973     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
974     ok(r == 0, "Expected 0 column's inserted\n");
975     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
976     ok(IsWindow(hHeader), "Header should be created\n");
977     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
978     DestroyWindow(hList);
979
980     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
981                           GetModuleHandle(NULL), 0);
982     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
983     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
984     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
985     /* insert column */
986     memset(&col, 0, sizeof(LVCOLUMNA));
987     col.mask = LVCF_WIDTH;
988     col.cx = 100;
989     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
990     ok(r == 0, "Expected 0 column's inserted\n");
991     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
992     ok(IsWindow(hHeader), "Header should be created\n");
993     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
994     DestroyWindow(hList);
995
996     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
997     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
998                           GetModuleHandle(NULL), 0);
999     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1000     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1001     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1002     ok(IsWindow(hHeader), "Header should be created\n");
1003     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1004     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1005     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1006     ok(IsWindow(hHeader), "Header should be created\n");
1007     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1008     DestroyWindow(hList);
1009
1010     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1011     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1012                           GetModuleHandle(NULL), 0);
1013     ret = SetWindowLongPtr(hList, GWL_STYLE,
1014                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1015     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1016     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1017     ok(IsWindow(hHeader), "Header should be created\n");
1018     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1019     ret = SetWindowLongPtr(hList, GWL_STYLE,
1020                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1021     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1022     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1023     ok(IsWindow(hHeader), "Header should be created\n");
1024     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1025     DestroyWindow(hList);
1026
1027     /* LVS_REPORT without WS_VISIBLE */
1028     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1029                           GetModuleHandle(NULL), 0);
1030     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1031     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1032     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1033     /* insert column */
1034     memset(&col, 0, sizeof(LVCOLUMNA));
1035     col.mask = LVCF_WIDTH;
1036     col.cx = 100;
1037     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1038     ok(r == 0, "Expected 0 column's inserted\n");
1039     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1040     ok(IsWindow(hHeader), "Header should be created\n");
1041     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1042     DestroyWindow(hList);
1043
1044     /* LVS_REPORT without WS_VISIBLE, try to show it */
1045     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1046                           GetModuleHandle(NULL), 0);
1047     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1048     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1049     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1050     ShowWindow(hList, SW_SHOW);
1051     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1052     ok(IsWindow(hHeader), "Header should be created\n");
1053     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1054     DestroyWindow(hList);
1055
1056     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1057     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1058                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1059     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1060     ok(IsWindow(hHeader), "Header should be created\n");
1061     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1062     /* HDS_DRAGDROP set by default */
1063     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1064     DestroyWindow(hList);
1065
1066     /* setting LVS_EX_HEADERDRAGDROP creates header */
1067     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1068                           GetModuleHandle(NULL), 0);
1069     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1070     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1071     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1072     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1073     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1074     ok(IsWindow(hHeader), "Header should be created\n");
1075     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1076     DestroyWindow(hList);
1077
1078     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1079     hList = create_custom_listview_control(0);
1080     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1081     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1082     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1083     DestroyWindow(hList);
1084
1085     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1086     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1087                           GetModuleHandle(NULL), 0);
1088     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1089     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1090
1091     rect.left = LVIR_BOUNDS;
1092     rect.top  = 1;
1093     rect.right = rect.bottom = -10;
1094     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1095     ok(r != 0, "Expected not-null LRESULT\n");
1096
1097     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1098     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1099     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1100
1101     DestroyWindow(hList);
1102 }
1103
1104 static void test_redraw(void)
1105 {
1106     HWND hwnd, hwndheader;
1107     HDC hdc;
1108     BOOL res;
1109     DWORD r;
1110
1111     hwnd = create_listview_control(0);
1112     hwndheader = subclass_header(hwnd);
1113
1114     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1115
1116     trace("invalidate & update\n");
1117     InvalidateRect(hwnd, NULL, TRUE);
1118     UpdateWindow(hwnd);
1119     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1120
1121     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1122
1123     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1124     /* 1. Without backbuffer */
1125     res = ListView_SetBkColor(hwnd, CLR_NONE);
1126     expect(TRUE, res);
1127
1128     hdc = GetWindowDC(hwndparent);
1129
1130     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1131     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1132     ok(r != 0, "Expected not zero result\n");
1133     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1134                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1135
1136     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1137     expect(TRUE, res);
1138
1139     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1140     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1141     ok(r != 0, "Expected not zero result\n");
1142     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1143                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1144
1145     /* 2. With backbuffer */
1146     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1147                                                      LVS_EX_DOUBLEBUFFER);
1148     res = ListView_SetBkColor(hwnd, CLR_NONE);
1149     expect(TRUE, res);
1150
1151     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1152     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1153     ok(r != 0, "Expected not zero result\n");
1154     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1155                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1156
1157     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1158     expect(TRUE, res);
1159
1160     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1161     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1162     todo_wine ok(r != 0, "Expected not zero result\n");
1163     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1164                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1165
1166     ReleaseDC(hwndparent, hdc);
1167
1168     DestroyWindow(hwnd);
1169 }
1170
1171 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1172 {
1173     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1174
1175     if(msg == WM_NOTIFY) {
1176         NMHDR *nmhdr = (PVOID)lp;
1177         if(nmhdr->code == NM_CUSTOMDRAW) {
1178             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1179             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1180             switch(nmlvcd->nmcd.dwDrawStage) {
1181             case CDDS_PREPAINT:
1182                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1183                 return CDRF_NOTIFYITEMDRAW;
1184             case CDDS_ITEMPREPAINT:
1185                 nmlvcd->clrTextBk = CLR_DEFAULT;
1186                 return CDRF_NOTIFYSUBITEMDRAW;
1187             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1188                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1189                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1190                 return CDRF_NOTIFYPOSTPAINT;
1191             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1192                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1193                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1194                 return CDRF_DODEFAULT;
1195             }
1196             return CDRF_DODEFAULT;
1197         }
1198     }
1199
1200     return DefWindowProcA(hwnd, msg, wp, lp);
1201 }
1202
1203 static void test_customdraw(void)
1204 {
1205     HWND hwnd;
1206     WNDPROC oldwndproc;
1207
1208     hwnd = create_listview_control(0);
1209
1210     insert_column(hwnd, 0);
1211     insert_column(hwnd, 1);
1212     insert_item(hwnd, 0);
1213
1214     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1215                                            (LONG_PTR)cd_wndproc);
1216
1217     InvalidateRect(hwnd, NULL, TRUE);
1218     UpdateWindow(hwnd);
1219
1220     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1221
1222     DestroyWindow(hwnd);
1223 }
1224
1225 static void test_icon_spacing(void)
1226 {
1227     /* LVM_SETICONSPACING */
1228     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1229
1230     HWND hwnd;
1231     WORD w, h;
1232     DWORD r;
1233
1234     hwnd = create_custom_listview_control(LVS_ICON);
1235     ok(hwnd != NULL, "failed to create a listview window\n");
1236
1237     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1238     expect(NFR_ANSI, r);
1239
1240     /* reset the icon spacing to defaults */
1241     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1242
1243     /* now we can request what the defaults are */
1244     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1245     w = LOWORD(r);
1246     h = HIWORD(r);
1247
1248     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1249
1250     trace("test icon spacing\n");
1251
1252     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1253     ok(r == MAKELONG(w, h) ||
1254        broken(r == MAKELONG(w, w)), /* win98 */
1255        "Expected %d, got %d\n", MAKELONG(w, h), r);
1256
1257     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1258     expect(MAKELONG(20,30), r);
1259
1260     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1261     expect(MAKELONG(25,35), r);
1262
1263     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1264
1265     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1266     DestroyWindow(hwnd);
1267 }
1268
1269 static void test_color(void)
1270 {
1271     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1272
1273     HWND hwnd;
1274     DWORD r;
1275     int i;
1276
1277     COLORREF color;
1278     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1279
1280     hwnd = create_listview_control(0);
1281     ok(hwnd != NULL, "failed to create a listview window\n");
1282
1283     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1284
1285     trace("test color seq\n");
1286     for (i = 0; i < 4; i++)
1287     {
1288         color = colors[i];
1289
1290         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1291         expect(TRUE, r);
1292         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1293         expect(color, r);
1294
1295         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1296         expect (TRUE, r);
1297         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1298         expect(color, r);
1299
1300         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1301         expect(TRUE, r);
1302         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1303         expect(color, r);
1304     }
1305
1306     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1307
1308     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1309     DestroyWindow(hwnd);
1310 }
1311
1312 static void test_item_count(void)
1313 {
1314     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1315
1316     HWND hwnd;
1317     DWORD r;
1318
1319     LVITEM item0;
1320     LVITEM item1;
1321     LVITEM item2;
1322     static CHAR item0text[] = "item0";
1323     static CHAR item1text[] = "item1";
1324     static CHAR item2text[] = "item2";
1325
1326     hwnd = create_listview_control(0);
1327     ok(hwnd != NULL, "failed to create a listview window\n");
1328
1329     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1330
1331     trace("test item count\n");
1332
1333     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1334     expect(0, r);
1335
1336     /* [item0] */
1337     item0.mask = LVIF_TEXT;
1338     item0.iItem = 0;
1339     item0.iSubItem = 0;
1340     item0.pszText = item0text;
1341     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1342     expect(0, r);
1343
1344     /* [item0, item1] */
1345     item1.mask = LVIF_TEXT;
1346     item1.iItem = 1;
1347     item1.iSubItem = 0;
1348     item1.pszText = item1text;
1349     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1350     expect(1, r);
1351
1352     /* [item0, item1, item2] */
1353     item2.mask = LVIF_TEXT;
1354     item2.iItem = 2;
1355     item2.iSubItem = 0;
1356     item2.pszText = item2text;
1357     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1358     expect(2, r);
1359
1360     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1361     expect(3, r);
1362
1363     /* [item0, item1] */
1364     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1365     expect(TRUE, r);
1366
1367     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1368     expect(2, r);
1369
1370     /* [] */
1371     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1372     expect(TRUE, r);
1373
1374     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1375     expect(0, r);
1376
1377     /* [item0] */
1378     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1379     expect(0, r);
1380
1381     /* [item0, item1] */
1382     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1383     expect(1, r);
1384
1385     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1386     expect(2, r);
1387
1388     /* [item0, item1, item2] */
1389     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1390     expect(2, r);
1391
1392     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1393     expect(3, r);
1394
1395     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1396
1397     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1398     DestroyWindow(hwnd);
1399 }
1400
1401 static void test_item_position(void)
1402 {
1403     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1404
1405     HWND hwnd;
1406     DWORD r;
1407     POINT position;
1408
1409     LVITEM item0;
1410     LVITEM item1;
1411     LVITEM item2;
1412     static CHAR item0text[] = "item0";
1413     static CHAR item1text[] = "item1";
1414     static CHAR item2text[] = "item2";
1415
1416     hwnd = create_custom_listview_control(LVS_ICON);
1417     ok(hwnd != NULL, "failed to create a listview window\n");
1418
1419     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1420
1421     trace("test item position\n");
1422
1423     /* [item0] */
1424     item0.mask = LVIF_TEXT;
1425     item0.iItem = 0;
1426     item0.iSubItem = 0;
1427     item0.pszText = item0text;
1428     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1429     expect(0, r);
1430
1431     /* [item0, item1] */
1432     item1.mask = LVIF_TEXT;
1433     item1.iItem = 1;
1434     item1.iSubItem = 0;
1435     item1.pszText = item1text;
1436     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1437     expect(1, r);
1438
1439     /* [item0, item1, item2] */
1440     item2.mask = LVIF_TEXT;
1441     item2.iItem = 2;
1442     item2.iSubItem = 0;
1443     item2.pszText = item2text;
1444     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1445     expect(2, r);
1446
1447     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1448     expect(TRUE, r);
1449     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1450     expect(TRUE, r);
1451     expect2(10, 5, position.x, position.y);
1452
1453     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1454     expect(TRUE, r);
1455     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1456     expect(TRUE, r);
1457     expect2(0, 0, position.x, position.y);
1458
1459     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1460     expect(TRUE, r);
1461     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1462     expect(TRUE, r);
1463     expect2(20, 20, position.x, position.y);
1464
1465     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1466
1467     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1468     DestroyWindow(hwnd);
1469 }
1470
1471 static void test_getorigin(void)
1472 {
1473     /* LVM_GETORIGIN */
1474
1475     HWND hwnd;
1476     DWORD r;
1477     POINT position;
1478
1479     position.x = position.y = 0;
1480
1481     hwnd = create_custom_listview_control(LVS_ICON);
1482     ok(hwnd != NULL, "failed to create a listview window\n");
1483     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1484     trace("test get origin results\n");
1485     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1486     expect(TRUE, r);
1487     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1488     DestroyWindow(hwnd);
1489
1490     hwnd = create_custom_listview_control(LVS_SMALLICON);
1491     ok(hwnd != NULL, "failed to create a listview window\n");
1492     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1493     trace("test get origin results\n");
1494     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1495     expect(TRUE, r);
1496     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1497     DestroyWindow(hwnd);
1498
1499     hwnd = create_custom_listview_control(LVS_LIST);
1500     ok(hwnd != NULL, "failed to create a listview window\n");
1501     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1502     trace("test get origin results\n");
1503     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1504     expect(FALSE, r);
1505     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1506     DestroyWindow(hwnd);
1507
1508     hwnd = create_custom_listview_control(LVS_REPORT);
1509     ok(hwnd != NULL, "failed to create a listview window\n");
1510     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1511     trace("test get origin results\n");
1512     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1513     expect(FALSE, r);
1514     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1515     DestroyWindow(hwnd);
1516
1517 }
1518
1519 static void test_multiselect(void)
1520 {
1521     typedef struct t_select_task
1522     {
1523         const char *descr;
1524         int initPos;
1525         int loopVK;
1526         int count;
1527         int result;
1528     } select_task;
1529
1530     HWND hwnd;
1531     DWORD r;
1532     int i,j,item_count,selected_count;
1533     static const int items=5;
1534     BYTE kstate[256];
1535     select_task task;
1536     LONG_PTR style;
1537     LVITEMA item;
1538
1539     static struct t_select_task task_list[] = {
1540         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1541         { "using VK_UP", -1, VK_UP, -1, -1 },
1542         { "using VK_END", 0, VK_END, 1, -1 },
1543         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1544     };
1545
1546
1547     hwnd = create_listview_control(0);
1548
1549     for (i=0;i<items;i++) {
1550             insert_item(hwnd, 0);
1551     }
1552
1553     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1554
1555     expect(items,item_count);
1556
1557     for (i=0;i<4;i++) {
1558         task = task_list[i];
1559
1560         /* deselect all items */
1561         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1562         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1563
1564         /* set initial position */
1565         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1566         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1567
1568         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1569
1570         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1571
1572         /* Set SHIFT key pressed */
1573         GetKeyboardState(kstate);
1574         kstate[VK_SHIFT]=0x80;
1575         SetKeyboardState(kstate);
1576
1577         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1578             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1579             expect(0,r);
1580             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1581             expect(0,r);
1582         }
1583
1584         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1585
1586         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);
1587
1588         /* Set SHIFT key released */
1589         GetKeyboardState(kstate);
1590         kstate[VK_SHIFT]=0x00;
1591         SetKeyboardState(kstate);
1592     }
1593     DestroyWindow(hwnd);
1594
1595     /* make multiple selection, then switch to LVS_SINGLESEL */
1596     hwnd = create_listview_control(0);
1597     for (i=0;i<items;i++) {
1598             insert_item(hwnd, 0);
1599     }
1600     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1601     expect(items,item_count);
1602     /* deselect all items */
1603     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1604     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1605     for (i=0;i<3;i++) {
1606         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1607     }
1608
1609     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1610     expect(3, r);
1611     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1612 todo_wine
1613     expect(-1, r);
1614
1615     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1616     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1617     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1618     /* check that style is accepted */
1619     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1620     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1621
1622     for (i=0;i<3;i++) {
1623         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1624         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1625     }
1626     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1627     expect(3, r);
1628     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1629     expect(3, r);
1630
1631     /* select one more */
1632     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1633
1634     for (i=0;i<3;i++) {
1635         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1636         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1637     }
1638     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1639     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1640
1641     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1642     expect(1, r);
1643     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1644 todo_wine
1645     expect(-1, r);
1646
1647     /* try to select all on LVS_SINGLESEL */
1648     memset(&item, 0, sizeof(item));
1649     item.stateMask = LVIS_SELECTED;
1650     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1651     expect(TRUE, r);
1652     ListView_SetSelectionMark(hwnd, -1);
1653
1654     item.stateMask = LVIS_SELECTED;
1655     item.state     = LVIS_SELECTED;
1656     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1657     expect(FALSE, r);
1658
1659     r = ListView_GetSelectedCount(hwnd);
1660     expect(0, r);
1661     r = ListView_GetSelectionMark(hwnd);
1662     expect(-1, r);
1663
1664     /* try to deselect all on LVS_SINGLESEL */
1665     item.stateMask = LVIS_SELECTED;
1666     item.state     = LVIS_SELECTED;
1667     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1668     expect(TRUE, r);
1669
1670     item.stateMask = LVIS_SELECTED;
1671     item.state     = 0;
1672     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1673     expect(TRUE, r);
1674     r = ListView_GetSelectedCount(hwnd);
1675     expect(0, r);
1676
1677     DestroyWindow(hwnd);
1678 }
1679
1680 static void test_subitem_rect(void)
1681 {
1682     HWND hwnd;
1683     DWORD r;
1684     LVCOLUMN col;
1685     RECT rect;
1686
1687     /* test LVM_GETSUBITEMRECT for header */
1688     hwnd = create_listview_control(0);
1689     ok(hwnd != NULL, "failed to create a listview window\n");
1690     /* add some columns */
1691     memset(&col, 0, sizeof(LVCOLUMN));
1692     col.mask = LVCF_WIDTH;
1693     col.cx = 100;
1694     r = -1;
1695     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1696     expect(0, r);
1697     col.cx = 150;
1698     r = -1;
1699     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
1700     expect(1, r);
1701     col.cx = 200;
1702     r = -1;
1703     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
1704     expect(2, r);
1705     /* item = -1 means header, subitem index is 1 based */
1706     rect.left = LVIR_BOUNDS;
1707     rect.top  = 0;
1708     rect.right = rect.bottom = 0;
1709     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1710     expect(0, r);
1711
1712     rect.left = LVIR_BOUNDS;
1713     rect.top  = 1;
1714     rect.right = rect.bottom = 0;
1715     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1716
1717     ok(r != 0, "Expected not-null LRESULT\n");
1718     expect(100, rect.left);
1719     expect(250, rect.right);
1720 todo_wine
1721     expect(3, rect.top);
1722
1723     rect.left = LVIR_BOUNDS;
1724     rect.top  = 2;
1725     rect.right = rect.bottom = 0;
1726     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1727
1728     ok(r != 0, "Expected not-null LRESULT\n");
1729     expect(250, rect.left);
1730     expect(450, rect.right);
1731 todo_wine
1732     expect(3, rect.top);
1733
1734     DestroyWindow(hwnd);
1735
1736     /* try it for non LVS_REPORT style */
1737     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
1738                          GetModuleHandle(NULL), 0);
1739     rect.left = LVIR_BOUNDS;
1740     rect.top  = 1;
1741     rect.right = rect.bottom = -10;
1742     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1743     ok(r == 0, "Expected not-null LRESULT\n");
1744     /* rect is unchanged */
1745     expect(0, rect.left);
1746     expect(-10, rect.right);
1747     expect(1, rect.top);
1748     expect(-10, rect.bottom);
1749     DestroyWindow(hwnd);
1750 }
1751
1752 /* comparison callback for test_sorting */
1753 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
1754 {
1755     if (first == second) return 0;
1756     return (first > second ? 1 : -1);
1757 }
1758
1759 static void test_sorting(void)
1760 {
1761     HWND hwnd;
1762     LVITEMA item = {0};
1763     DWORD r;
1764     LONG_PTR style;
1765     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
1766     CHAR buff[10];
1767
1768     hwnd = create_listview_control(0);
1769     ok(hwnd != NULL, "failed to create a listview window\n");
1770
1771     /* insert some items */
1772     item.mask = LVIF_PARAM | LVIF_STATE;
1773     item.state = LVIS_SELECTED;
1774     item.iItem = 0;
1775     item.iSubItem = 0;
1776     item.lParam = 3;
1777     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1778     expect(0, r);
1779
1780     item.mask = LVIF_PARAM;
1781     item.iItem = 1;
1782     item.iSubItem = 0;
1783     item.lParam = 2;
1784     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1785     expect(1, r);
1786
1787     item.mask = LVIF_STATE | LVIF_PARAM;
1788     item.state = LVIS_SELECTED;
1789     item.iItem = 2;
1790     item.iSubItem = 0;
1791     item.lParam = 4;
1792     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1793     expect(2, r);
1794
1795     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1796     expect(-1, r);
1797
1798     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1799     expect(2, r);
1800
1801     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
1802     expect(TRUE, r);
1803
1804     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1805     expect(2, r);
1806     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1807     expect(-1, r);
1808     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
1809     expect(0, r);
1810     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
1811     expect(LVIS_SELECTED, r);
1812     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
1813     expect(LVIS_SELECTED, r);
1814
1815     DestroyWindow(hwnd);
1816
1817     /* switch to LVS_SORTASCENDING when some items added */
1818     hwnd = create_listview_control(0);
1819     ok(hwnd != NULL, "failed to create a listview window\n");
1820
1821     item.mask = LVIF_TEXT;
1822     item.iItem = 0;
1823     item.iSubItem = 0;
1824     item.pszText = names[1];
1825     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1826     expect(0, r);
1827
1828     item.mask = LVIF_TEXT;
1829     item.iItem = 1;
1830     item.iSubItem = 0;
1831     item.pszText = names[2];
1832     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1833     expect(1, r);
1834
1835     item.mask = LVIF_TEXT;
1836     item.iItem = 2;
1837     item.iSubItem = 0;
1838     item.pszText = names[0];
1839     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1840     expect(2, r);
1841
1842     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1843     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
1844     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1845     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
1846
1847     /* no sorting performed when switched to LVS_SORTASCENDING */
1848     item.mask = LVIF_TEXT;
1849     item.iItem = 0;
1850     item.pszText = buff;
1851     item.cchTextMax = sizeof(buff);
1852     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1853     expect(TRUE, r);
1854     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1855
1856     item.iItem = 1;
1857     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1858     expect(TRUE, r);
1859     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1860
1861     item.iItem = 2;
1862     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1863     expect(TRUE, r);
1864     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1865
1866     /* adding new item doesn't resort list */
1867     item.mask = LVIF_TEXT;
1868     item.iItem = 3;
1869     item.iSubItem = 0;
1870     item.pszText = names[3];
1871     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1872     expect(3, r);
1873
1874     item.mask = LVIF_TEXT;
1875     item.iItem = 0;
1876     item.pszText = buff;
1877     item.cchTextMax = sizeof(buff);
1878     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1879     expect(TRUE, r);
1880     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1881
1882     item.iItem = 1;
1883     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1884     expect(TRUE, r);
1885     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1886
1887     item.iItem = 2;
1888     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1889     expect(TRUE, r);
1890     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1891
1892     item.iItem = 3;
1893     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1894     expect(TRUE, r);
1895     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1896
1897     /* corner case - item should be placed at first position */
1898     item.mask = LVIF_TEXT;
1899     item.iItem = 4;
1900     item.iSubItem = 0;
1901     item.pszText = names[4];
1902     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
1903     expect(0, r);
1904
1905     item.iItem = 0;
1906     item.pszText = buff;
1907     item.cchTextMax = sizeof(buff);
1908     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1909     expect(TRUE, r);
1910     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
1911
1912     item.iItem = 1;
1913     item.pszText = buff;
1914     item.cchTextMax = sizeof(buff);
1915     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1916     expect(TRUE, r);
1917     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
1918
1919     item.iItem = 2;
1920     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1921     expect(TRUE, r);
1922     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
1923
1924     item.iItem = 3;
1925     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1926     expect(TRUE, r);
1927     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
1928
1929     item.iItem = 4;
1930     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1931     expect(TRUE, r);
1932     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
1933
1934     DestroyWindow(hwnd);
1935 }
1936
1937 static void test_ownerdata(void)
1938 {
1939     HWND hwnd;
1940     LONG_PTR style, ret;
1941     DWORD res;
1942     LVITEMA item;
1943
1944     /* it isn't possible to set LVS_OWNERDATA after creation */
1945     hwnd = create_listview_control(0);
1946     ok(hwnd != NULL, "failed to create a listview window\n");
1947     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1948     ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
1949
1950     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1951
1952     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1953     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1954     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1955                 "try to switch to LVS_OWNERDATA seq", FALSE);
1956
1957     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1958     ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
1959     DestroyWindow(hwnd);
1960
1961     /* try to set LVS_OWNERDATA after creation just having it */
1962     hwnd = create_listview_control(LVS_OWNERDATA);
1963     ok(hwnd != NULL, "failed to create a listview window\n");
1964     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1965     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1966
1967     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1968
1969     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
1970     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1971     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1972                 "try to switch to LVS_OWNERDATA seq", FALSE);
1973     DestroyWindow(hwnd);
1974
1975     /* try to remove LVS_OWNERDATA after creation just having it */
1976     hwnd = create_listview_control(LVS_OWNERDATA);
1977     ok(hwnd != NULL, "failed to create a listview window\n");
1978     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1979     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1980
1981     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1982
1983     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
1984     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
1985     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
1986                 "try to switch to LVS_OWNERDATA seq", FALSE);
1987     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1988     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
1989     DestroyWindow(hwnd);
1990
1991     /* try select an item */
1992     hwnd = create_listview_control(LVS_OWNERDATA);
1993     ok(hwnd != NULL, "failed to create a listview window\n");
1994     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
1995     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
1996     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1997     expect(0, res);
1998     memset(&item, 0, sizeof(item));
1999     item.stateMask = LVIS_SELECTED;
2000     item.state     = LVIS_SELECTED;
2001     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2002     expect(TRUE, res);
2003     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2004     expect(1, res);
2005     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2006     expect(1, res);
2007     DestroyWindow(hwnd);
2008
2009     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2010     hwnd = create_listview_control(LVS_OWNERDATA);
2011     ok(hwnd != NULL, "failed to create a listview window\n");
2012     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2013     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2014     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2015     expect(1, res);
2016     memset(&item, 0, sizeof(item));
2017     item.mask = LVIF_STATE;
2018     item.iItem = 0;
2019     item.stateMask = LVIS_SELECTED;
2020     item.state     = LVIS_SELECTED;
2021     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2022     expect(FALSE, res);
2023     DestroyWindow(hwnd);
2024
2025     /* check notifications after focused/selected changed */
2026     hwnd = create_listview_control(LVS_OWNERDATA);
2027     ok(hwnd != NULL, "failed to create a listview window\n");
2028     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2029     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2030
2031     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2032
2033     memset(&item, 0, sizeof(item));
2034     item.stateMask = LVIS_SELECTED;
2035     item.state     = LVIS_SELECTED;
2036     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2037     expect(TRUE, res);
2038
2039     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2040                 "ownerdata select notification", TRUE);
2041
2042     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2043
2044     memset(&item, 0, sizeof(item));
2045     item.stateMask = LVIS_FOCUSED;
2046     item.state     = LVIS_FOCUSED;
2047     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2048     expect(TRUE, res);
2049
2050     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2051                 "ownerdata focus notification", TRUE);
2052     DestroyWindow(hwnd);
2053
2054     /* check notifications on LVM_GETITEM */
2055     /* zero callback mask */
2056     hwnd = create_listview_control(LVS_OWNERDATA);
2057     ok(hwnd != NULL, "failed to create a listview window\n");
2058     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2059     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2060
2061     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2062
2063     memset(&item, 0, sizeof(item));
2064     item.stateMask = LVIS_SELECTED;
2065     item.mask      = LVIF_STATE;
2066     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2067     expect(TRUE, res);
2068
2069     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2070                 "ownerdata getitem selected state 1", FALSE);
2071
2072     /* non zero callback mask but not we asking for */
2073     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2074     expect(TRUE, res);
2075
2076     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2077
2078     memset(&item, 0, sizeof(item));
2079     item.stateMask = LVIS_SELECTED;
2080     item.mask      = LVIF_STATE;
2081     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2082     expect(TRUE, res);
2083
2084     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2085                 "ownerdata getitem selected state 2", FALSE);
2086
2087     /* LVIS_OVERLAYMASK callback mask, asking for index */
2088     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2089
2090     memset(&item, 0, sizeof(item));
2091     item.stateMask = LVIS_OVERLAYMASK;
2092     item.mask      = LVIF_STATE;
2093     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2094     expect(TRUE, res);
2095
2096     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2097                 "ownerdata getitem selected state 2", FALSE);
2098
2099     DestroyWindow(hwnd);
2100 }
2101
2102 static void test_norecompute(void)
2103 {
2104     static CHAR testA[] = "test";
2105     CHAR buff[10];
2106     LVITEMA item;
2107     HWND hwnd;
2108     DWORD res;
2109
2110     /* self containing control */
2111     hwnd = create_listview_control(0);
2112     ok(hwnd != NULL, "failed to create a listview window\n");
2113     memset(&item, 0, sizeof(item));
2114     item.mask = LVIF_TEXT | LVIF_STATE;
2115     item.iItem = 0;
2116     item.stateMask = LVIS_SELECTED;
2117     item.state     = LVIS_SELECTED;
2118     item.pszText   = testA;
2119     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2120     expect(0, res);
2121     /* retrieve with LVIF_NORECOMPUTE */
2122     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2123     item.iItem = 0;
2124     item.pszText    = buff;
2125     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2126     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2127     expect(TRUE, res);
2128     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2129
2130     item.mask = LVIF_TEXT;
2131     item.iItem = 1;
2132     item.pszText = LPSTR_TEXTCALLBACK;
2133     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2134     expect(1, res);
2135
2136     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2137     item.iItem = 1;
2138     item.pszText    = buff;
2139     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2140
2141     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2142     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2143     expect(TRUE, res);
2144     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2145        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2146     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2147
2148     DestroyWindow(hwnd);
2149
2150     /* LVS_OWNERDATA */
2151     hwnd = create_listview_control(LVS_OWNERDATA);
2152     ok(hwnd != NULL, "failed to create a listview window\n");
2153
2154     item.mask = LVIF_STATE;
2155     item.stateMask = LVIS_SELECTED;
2156     item.state     = LVIS_SELECTED;
2157     item.iItem = 0;
2158     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2159     expect(0, res);
2160
2161     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2162     item.iItem = 0;
2163     item.pszText    = buff;
2164     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2165     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2166     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2167     expect(TRUE, res);
2168     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2169        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2170     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2171
2172     DestroyWindow(hwnd);
2173 }
2174
2175 static void test_nosortheader(void)
2176 {
2177     HWND hwnd, header;
2178     LONG_PTR style;
2179
2180     hwnd = create_listview_control(0);
2181     ok(hwnd != NULL, "failed to create a listview window\n");
2182
2183     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2184     ok(IsWindow(header), "header expected\n");
2185
2186     style = GetWindowLongPtr(header, GWL_STYLE);
2187     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2188
2189     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2190     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2191     /* HDS_BUTTONS retained */
2192     style = GetWindowLongPtr(header, GWL_STYLE);
2193     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2194
2195     DestroyWindow(hwnd);
2196
2197     /* create with LVS_NOSORTHEADER */
2198     hwnd = create_listview_control(LVS_NOSORTHEADER);
2199     ok(hwnd != NULL, "failed to create a listview window\n");
2200
2201     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2202     ok(IsWindow(header), "header expected\n");
2203
2204     style = GetWindowLongPtr(header, GWL_STYLE);
2205     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2206
2207     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2208     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2209     /* not changed here */
2210     style = GetWindowLongPtr(header, GWL_STYLE);
2211     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2212
2213     DestroyWindow(hwnd);
2214 }
2215
2216 START_TEST(listview)
2217 {
2218     HMODULE hComctl32;
2219     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
2220
2221     hComctl32 = GetModuleHandleA("comctl32.dll");
2222     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
2223     if (pInitCommonControlsEx)
2224     {
2225         INITCOMMONCONTROLSEX iccex;
2226         iccex.dwSize = sizeof(iccex);
2227         iccex.dwICC  = ICC_LISTVIEW_CLASSES;
2228         pInitCommonControlsEx(&iccex);
2229     }
2230     else
2231         InitCommonControls();
2232
2233     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2234
2235     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2236     hwndparent = create_parent_window();
2237     ok_sequence(sequences, PARENT_SEQ_INDEX, create_parent_wnd_seq, "create parent window", TRUE);
2238     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2239
2240     test_images();
2241     test_checkboxes();
2242     test_items();
2243     test_create();
2244     test_redraw();
2245     test_customdraw();
2246     test_icon_spacing();
2247     test_color();
2248     test_item_count();
2249     test_item_position();
2250     test_columns();
2251     test_getorigin();
2252     test_multiselect();
2253     test_subitem_rect();
2254     test_sorting();
2255     test_ownerdata();
2256     test_norecompute();
2257     test_nosortheader();
2258 }