1 /*
2  * ListView tests
3  *
4  * Copyright 2006 Mike McCormack for CodeWeavers
5  * Copyright 2007 George Gov
6  * Copyright 2009-2014 Nikolay Sivov
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #include <stdio.h>
24 #include <windows.h>
25 #include <commctrl.h>
26 
27 #include "wine/test.h"
28 #include "v6util.h"
29 #include "msg.h"
30 
31 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
32 static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
33 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
34 static BOOL (WINAPI *p_TrackMouseEvent)(TRACKMOUSEEVENT *);
35 
36 enum seq_index {
37     PARENT_SEQ_INDEX,
38     PARENT_FULL_SEQ_INDEX,
39     PARENT_CD_SEQ_INDEX,
40     LISTVIEW_SEQ_INDEX,
41     EDITBOX_SEQ_INDEX,
42     COMBINED_SEQ_INDEX,
43     NUM_MSG_SEQUENCES
44 };
45 
46 #define LISTVIEW_ID 0
47 #define HEADER_ID   1
48 
49 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
50 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
51        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
52 
53 static const WCHAR testparentclassW[] =
54     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
55 
56 static HWND hwndparent, hwndparentW;
57 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
58 static BOOL blockEdit;
59 /* return nonzero on NM_HOVER */
60 static BOOL g_block_hover;
61 /* notification data for LVN_ITEMCHANGED */
62 static NMLISTVIEW g_nmlistview;
63 /* notification data for LVN_ITEMCHANGING */
64 static NMLISTVIEW g_nmlistview_changing;
65 /* format reported to control:
66    -1 falls to defproc, anything else returned */
67 static INT notifyFormat;
68 /* indicates we're running < 5.80 version */
69 static BOOL g_is_below_5;
70 /* item data passed to LVN_GETDISPINFOA */
71 static LVITEMA g_itema;
72 /* alter notification code A->W */
73 static BOOL g_disp_A_to_W;
74 /* dispinfo data sent with LVN_LVN_ENDLABELEDIT */
75 static NMLVDISPINFOA g_editbox_disp_info;
76 /* when this is set focus will be tested on LVN_DELETEITEM */
77 static BOOL g_focus_test_LVN_DELETEITEM;
78 
79 static HWND subclass_editbox(HWND hwndListview);
80 
81 static void init_functions(void)
82 {
83     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
84 
85 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
86     X(ImageList_Create);
87     X(ImageList_Destroy);
88     X(ImageList_Add);
89     X(_TrackMouseEvent);
90 #undef X
91 }
92 
93 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
94 
95 static const struct message create_ownerdrawfixed_parent_seq[] = {
96     { WM_NOTIFYFORMAT, sent },
97     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
98     { WM_MEASUREITEM, sent },
99     { WM_PARENTNOTIFY, sent },
100     { 0 }
101 };
102 
103 static const struct message redraw_listview_seq[] = {
104     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
105     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
106     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
107     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
108     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
109     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
110     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
111     { 0 }
112 };
113 
114 static const struct message listview_icon_spacing_seq[] = {
115     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
116     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
117     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
118     { 0 }
119 };
120 
121 static const struct message listview_color_seq[] = {
122     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
123     { LVM_GETBKCOLOR,     sent },
124     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
125     { LVM_GETTEXTCOLOR,   sent },
126     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
127     { LVM_GETTEXTBKCOLOR, sent },
128 
129     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
130     { LVM_GETBKCOLOR,     sent },
131     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
132     { LVM_GETTEXTCOLOR,   sent },
133     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
134     { LVM_GETTEXTBKCOLOR, sent },
135 
136     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
137     { LVM_GETBKCOLOR,     sent },
138     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
139     { LVM_GETTEXTCOLOR,   sent },
140     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
141     { LVM_GETTEXTBKCOLOR, sent },
142 
143     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
144     { LVM_GETBKCOLOR,     sent },
145     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
146     { LVM_GETTEXTCOLOR,   sent },
147     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
148     { LVM_GETTEXTBKCOLOR, sent },
149     { 0 }
150 };
151 
152 static const struct message listview_item_count_seq[] = {
153     { LVM_GETITEMCOUNT,   sent },
154     { LVM_INSERTITEMA,    sent },
155     { LVM_INSERTITEMA,    sent },
156     { LVM_INSERTITEMA,    sent },
157     { LVM_GETITEMCOUNT,   sent },
158     { LVM_DELETEITEM,     sent|wparam, 2 },
159     { WM_NCPAINT,         sent|optional },
160     { WM_ERASEBKGND,      sent|optional },
161     { LVM_GETITEMCOUNT,   sent },
162     { LVM_DELETEALLITEMS, sent },
163     { LVM_GETITEMCOUNT,   sent },
164     { LVM_INSERTITEMA,    sent },
165     { LVM_INSERTITEMA,    sent },
166     { LVM_GETITEMCOUNT,   sent },
167     { LVM_INSERTITEMA,    sent },
168     { LVM_GETITEMCOUNT,   sent },
169     { 0 }
170 };
171 
172 static const struct message listview_itempos_seq[] = {
173     { LVM_INSERTITEMA,     sent },
174     { LVM_INSERTITEMA,     sent },
175     { LVM_INSERTITEMA,     sent },
176     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
177     { WM_NCPAINT,          sent|optional },
178     { WM_ERASEBKGND,       sent|optional },
179     { LVM_GETITEMPOSITION, sent|wparam,        1 },
180     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
181     { LVM_GETITEMPOSITION, sent|wparam,        2 },
182     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
183     { LVM_GETITEMPOSITION, sent|wparam,        0 },
184     { 0 }
185 };
186 
187 static const struct message listview_ownerdata_switchto_seq[] = {
188     { WM_STYLECHANGING,    sent },
189     { WM_STYLECHANGED,     sent },
190     { 0 }
191 };
192 
193 static const struct message listview_getorderarray_seq[] = {
194     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
195     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
196     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID },
197     { HDM_GETORDERARRAY,       sent|id|wparam, 0, 0, HEADER_ID },
198     { 0 }
199 };
200 
201 static const struct message listview_setorderarray_seq[] = {
202     { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
203     { HDM_SETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
204     { LVM_SETCOLUMNORDERARRAY, sent|id|wparam, 0, 0, LISTVIEW_ID },
205     { HDM_SETORDERARRAY,       sent|id|wparam, 0, 0, HEADER_ID },
206     { 0 }
207 };
208 
209 static const struct message empty_seq[] = {
210     { 0 }
211 };
212 
213 static const struct message parent_focus_change_ownerdata_seq[] = {
214     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
215     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
216     { 0 }
217 };
218 
219 static const struct message forward_erasebkgnd_parent_seq[] = {
220     { WM_ERASEBKGND, sent },
221     { 0 }
222 };
223 
224 static const struct message ownerdata_select_focus_parent_seq[] = {
225     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
226     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
227     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
228     { 0 }
229 };
230 
231 static const struct message ownerdata_setstate_all_parent_seq[] = {
232     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
233     { 0 }
234 };
235 
236 static const struct message ownerdata_defocus_all_parent_seq[] = {
237     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
238     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
239     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
240     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
241     { 0 }
242 };
243 
244 static const struct message ownerdata_deselect_all_parent_seq[] = {
245     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
246     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
247     { 0 }
248 };
249 
250 static const struct message change_all_parent_seq[] = {
251     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
252     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
253 
254     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
255     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
256 
257     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
258     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
259 
260     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
261     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
262 
263     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
264     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
265     { 0 }
266 };
267 
268 static const struct message changing_all_parent_seq[] = {
269     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
270     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
271     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
272     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
273     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
274     { 0 }
275 };
276 
277 static const struct message textcallback_set_again_parent_seq[] = {
278     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
279     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
280     { 0 }
281 };
282 
283 static const struct message single_getdispinfo_parent_seq[] = {
284     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
285     { 0 }
286 };
287 
288 static const struct message getitemposition_seq1[] = {
289     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
290     { 0 }
291 };
292 
293 static const struct message getitemposition_seq2[] = {
294     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
295     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
296     { 0 }
297 };
298 
299 static const struct message getsubitemrect_seq[] = {
300     { LVM_GETSUBITEMRECT, sent|id|wparam, -1, 0, LISTVIEW_ID },
301     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
302     { LVM_GETSUBITEMRECT, sent|id|wparam, 0, 0, LISTVIEW_ID },
303     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
304     { LVM_GETSUBITEMRECT, sent|id|wparam, -10, 0, LISTVIEW_ID },
305     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
306     { LVM_GETSUBITEMRECT, sent|id|wparam, 20, 0, LISTVIEW_ID },
307     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
308     { 0 }
309 };
310 
311 static const struct message editbox_create_pos[] = {
312     /* sequence sent after LVN_BEGINLABELEDIT */
313     /* next two are 4.7x specific */
314     { WM_WINDOWPOSCHANGING, sent },
315     { WM_WINDOWPOSCHANGED, sent|optional },
316 
317     { WM_WINDOWPOSCHANGING, sent|optional },
318     { WM_NCCALCSIZE, sent },
319     { WM_WINDOWPOSCHANGED, sent },
320     { WM_MOVE, sent|defwinproc },
321     { WM_SIZE, sent|defwinproc },
322     /* the rest is todo, skipped in 4.7x */
323     { WM_WINDOWPOSCHANGING, sent|optional },
324     { WM_WINDOWPOSCHANGED, sent|optional },
325     { 0 }
326 };
327 
328 static const struct message scroll_parent_seq[] = {
329     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
330     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
331     { 0 }
332 };
333 
334 static const struct message setredraw_seq[] = {
335     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
336     { 0 }
337 };
338 
339 static const struct message lvs_ex_transparentbkgnd_seq[] = {
340     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
341     { 0 }
342 };
343 
344 static const struct message edit_end_nochange[] = {
345     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDLABELEDITA },
346     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },     /* todo */
347     { WM_NOTIFY, sent|id, 0, 0, NM_SETFOCUS },
348     { 0 }
349 };
350 
351 static const struct message hover_parent[] = {
352     { WM_GETDLGCODE, sent }, /* todo_wine */
353     { WM_NOTIFY, sent|id, 0, 0, NM_HOVER },
354     { 0 }
355 };
356 
357 static const struct message listview_destroy[] = {
358     { 0x0090, sent|optional }, /* Vista */
359     { WM_PARENTNOTIFY, sent },
360     { WM_SHOWWINDOW, sent },
361     { WM_WINDOWPOSCHANGING, sent },
362     { WM_WINDOWPOSCHANGED, sent|optional },
363     { WM_DESTROY, sent },
364     { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS },
365     { WM_NCDESTROY, sent },
366     { 0 }
367 };
368 
369 static const struct message listview_ownerdata_destroy[] = {
370     { 0x0090, sent|optional }, /* Vista */
371     { WM_PARENTNOTIFY, sent },
372     { WM_SHOWWINDOW, sent },
373     { WM_WINDOWPOSCHANGING, sent },
374     { WM_WINDOWPOSCHANGED, sent|optional },
375     { WM_DESTROY, sent },
376     { WM_NCDESTROY, sent },
377     { 0 }
378 };
379 
380 static const struct message listview_ownerdata_deleteall[] = {
381     { LVM_DELETEALLITEMS, sent },
382     { WM_NOTIFY, sent|id, 0, 0, LVN_DELETEALLITEMS },
383     { 0 }
384 };
385 
386 static const struct message listview_header_changed_seq[] = {
387     { LVM_SETCOLUMNA, sent },
388     { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
389     { WM_NOTIFY, sent|id|defwinproc, 0, 0, LISTVIEW_ID },
390     { 0 }
391 };
392 
393 static const struct message parent_header_click_seq[] = {
394     { WM_NOTIFY, sent|id, 0, 0, LVN_COLUMNCLICK },
395     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCLICKA },
396     { 0 }
397 };
398 
399 static const struct message parent_header_divider_dclick_seq[] = {
400     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGINGA },
401     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },
402     { WM_NOTIFY, sent|id, 0, 0, NM_CUSTOMDRAW },
403     { WM_NOTIFY, sent|id, 0, 0, HDN_ITEMCHANGEDA },
404     { WM_NOTIFY, sent|id, 0, 0, HDN_DIVIDERDBLCLICKA },
405     { 0 }
406 };
407 
408 static const struct message listview_set_imagelist[] = {
409     { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID },
410     { 0 }
411 };
412 
413 static const struct message listview_header_set_imagelist[] = {
414     { LVM_SETIMAGELIST, sent|id, 0, 0, LISTVIEW_ID },
415     { HDM_SETIMAGELIST, sent|id, 0, 0, HEADER_ID },
416     { 0 }
417 };
418 
419 static const struct message parent_insert_focused_seq[] = {
420     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
421     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
422     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
423     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
424     { WM_NOTIFY, sent|id, 0, 0, LVN_INSERTITEM },
425     { 0 }
426 };
427 
428 static const struct message parent_report_cd_seq[] = {
429     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
430     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
431     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM },
432     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM },
433     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT|CDDS_SUBITEM },
434     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT|CDDS_SUBITEM },
435     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
436     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
437     { 0 }
438 };
439 
440 static const struct message parent_list_cd_seq[] = {
441     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_PREPAINT },
442     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPREPAINT },
443     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_ITEMPOSTPAINT },
444     { WM_NOTIFY, sent|id|custdraw, 0, 0, NM_CUSTOMDRAW, CDDS_POSTPAINT },
445     { 0 }
446 };
447 
448 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
449 {
450     static LONG defwndproc_counter = 0;
451     LRESULT ret;
452     struct message msg;
453 
454     msg.message = message;
455     msg.flags = sent|wparam|lparam;
456     if (defwndproc_counter) msg.flags |= defwinproc;
457     msg.wParam = wParam;
458     msg.lParam = lParam;
459     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
460 
461     /* log system messages, except for painting */
462     if (message < WM_USER &&
463         message != WM_PAINT &&
464         message != WM_ERASEBKGND &&
465         message != WM_NCPAINT &&
466         message != WM_NCHITTEST &&
467         message != WM_GETTEXT &&
468         message != WM_GETICON &&
469         message != WM_DEVICECHANGE)
470     {
471         add_message(sequences, PARENT_SEQ_INDEX, &msg);
472         add_message(sequences, COMBINED_SEQ_INDEX, &msg);
473     }
474     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
475 
476     switch (message)
477     {
478       case WM_NOTIFY:
479       {
480           switch (((NMHDR*)lParam)->code)
481           {
482           case LVN_BEGINLABELEDITA:
483           {
484               HWND edit = NULL;
485 
486               /* subclass edit box */
487               if (!blockEdit)
488                   edit = subclass_editbox(((NMHDR*)lParam)->hwndFrom);
489 
490               if (edit)
491               {
492                   INT len = SendMessageA(edit, EM_GETLIMITTEXT, 0, 0);
493                   ok(len == 259 || broken(len == 260) /* includes NULL in NT4 */,
494                       "text limit %d, expected 259\n", len);
495               }
496 
497               return blockEdit;
498           }
499           case LVN_ENDLABELEDITA:
500               {
501               HWND edit;
502 
503               /* always accept new item text */
504               NMLVDISPINFOA *di = (NMLVDISPINFOA*)lParam;
505               g_editbox_disp_info = *di;
506               trace("LVN_ENDLABELEDIT: text=%s\n", di->item.pszText ? di->item.pszText : "(null)");
507 
508               /* edit control still available from this notification */
509               edit = (HWND)SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETEDITCONTROL, 0, 0);
510               ok(IsWindow(edit), "expected valid edit control handle\n");
511               ok((GetWindowLongA(edit, GWL_STYLE) & ES_MULTILINE) == 0, "edit is multiline\n");
512 
513               return TRUE;
514               }
515           case LVN_BEGINSCROLL:
516           case LVN_ENDSCROLL:
517               {
518               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
519 
520               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
521                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
522               }
523               break;
524           case LVN_ITEMCHANGING:
525               {
526                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
527                   g_nmlistview_changing = *nmlv;
528               }
529               break;
530           case LVN_ITEMCHANGED:
531               {
532                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
533                   g_nmlistview = *nmlv;
534               }
535               break;
536           case LVN_GETDISPINFOA:
537               {
538                   NMLVDISPINFOA *dispinfo = (NMLVDISPINFOA*)lParam;
539                   g_itema = dispinfo->item;
540 
541                   if (g_disp_A_to_W && (dispinfo->item.mask & LVIF_TEXT))
542                   {
543                       static const WCHAR testW[] = {'T','E','S','T',0};
544                       dispinfo->hdr.code = LVN_GETDISPINFOW;
545                       memcpy(dispinfo->item.pszText, testW, sizeof(testW));
546                   }
547 
548                   /* test control buffer size for text, 10 used to mask cases when control
549                      is using caller buffer to process LVM_GETITEM for example */
550                   if (dispinfo->item.mask & LVIF_TEXT && dispinfo->item.cchTextMax > 10)
551                       ok(dispinfo->item.cchTextMax == 260 ||
552                          broken(dispinfo->item.cchTextMax == 264) /* NT4 reports aligned size */,
553                       "buffer size %d\n", dispinfo->item.cchTextMax);
554               }
555               break;
556           case LVN_DELETEITEM:
557               if (g_focus_test_LVN_DELETEITEM)
558               {
559                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
560                   UINT state;
561 
562                   state = SendMessageA(((NMHDR*)lParam)->hwndFrom, LVM_GETITEMSTATE, nmlv->iItem, LVIS_FOCUSED);
563                   ok(state == 0, "got state %x\n", state);
564               }
565               break;
566           case NM_HOVER:
567               if (g_block_hover) return 1;
568               break;
569           }
570           break;
571       }
572       case WM_NOTIFYFORMAT:
573       {
574           /* force to return format */
575           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
576           break;
577       }
578     }
579 
580     defwndproc_counter++;
581     if (IsWindowUnicode(hwnd))
582         ret = DefWindowProcW(hwnd, message, wParam, lParam);
583     else
584         ret = DefWindowProcA(hwnd, message, wParam, lParam);
585     defwndproc_counter--;
586 
587     return ret;
588 }
589 
590 static BOOL register_parent_wnd_class(BOOL Unicode)
591 {
592     WNDCLASSA clsA;
593     WNDCLASSW clsW;
594 
595     if (Unicode)
596     {
597         clsW.style = 0;
598         clsW.lpfnWndProc = parent_wnd_proc;
599         clsW.cbClsExtra = 0;
600         clsW.cbWndExtra = 0;
601         clsW.hInstance = GetModuleHandleW(NULL);
602         clsW.hIcon = 0;
603         clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
604         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
605         clsW.lpszMenuName = NULL;
606         clsW.lpszClassName = testparentclassW;
607     }
608     else
609     {
610         clsA.style = 0;
611         clsA.lpfnWndProc = parent_wnd_proc;
612         clsA.cbClsExtra = 0;
613         clsA.cbWndExtra = 0;
614         clsA.hInstance = GetModuleHandleA(NULL);
615         clsA.hIcon = 0;
616         clsA.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
617         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
618         clsA.lpszMenuName = NULL;
619         clsA.lpszClassName = "Listview test parent class";
620     }
621 
622     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
623 }
624 
625 static HWND create_parent_window(BOOL Unicode)
626 {
627     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W',0};
628     HWND hwnd;
629 
630     if (!register_parent_wnd_class(Unicode))
631         return NULL;
632 
633     blockEdit = FALSE;
634     notifyFormat = -1;
635 
636     if (Unicode)
637         hwnd = CreateWindowExW(0, testparentclassW, nameW,
638                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
639                                WS_MAXIMIZEBOX | WS_VISIBLE,
640                                0, 0, 100, 100,
641                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
642     else
643         hwnd = CreateWindowExA(0, "Listview test parent class",
644                                "Listview test parent window",
645                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
646                                WS_MAXIMIZEBOX | WS_VISIBLE,
647                                0, 0, 100, 100,
648                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
649     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
650     return hwnd;
651 }
652 
653 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
654 {
655     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
656     static LONG defwndproc_counter = 0;
657     LRESULT ret;
658     struct message msg;
659 
660     msg.message = message;
661     msg.flags = sent|wparam|lparam;
662     if (defwndproc_counter) msg.flags |= defwinproc;
663     msg.wParam = wParam;
664     msg.lParam = lParam;
665     msg.id = LISTVIEW_ID;
666     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
667     add_message(sequences, COMBINED_SEQ_INDEX, &msg);
668 
669     defwndproc_counter++;
670     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
671     defwndproc_counter--;
672     return ret;
673 }
674 
675 static HWND create_listview_control(DWORD style)
676 {
677     WNDPROC oldproc;
678     HWND hwnd;
679     RECT rect;
680 
681     GetClientRect(hwndparent, &rect);
682     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo",
683                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
684                            0, 0, rect.right, rect.bottom,
685                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
686     ok(hwnd != NULL, "gle=%d\n", GetLastError());
687 
688     if (!hwnd) return NULL;
689 
690     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
691                                         (LONG_PTR)listview_subclass_proc);
692     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
693 
694     return hwnd;
695 }
696 
697 /* unicode listview window with specified parent */
698 static HWND create_listview_controlW(DWORD style, HWND parent)
699 {
700     WNDPROC oldproc;
701     HWND hwnd;
702     RECT rect;
703     static const WCHAR nameW[] = {'f','o','o',0};
704 
705     GetClientRect(parent, &rect);
706     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
707                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
708                            0, 0, rect.right, rect.bottom,
709                            parent, NULL, GetModuleHandleW(NULL), NULL);
710     ok(hwnd != NULL, "gle=%d\n", GetLastError());
711 
712     if (!hwnd) return NULL;
713 
714     oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
715                                         (LONG_PTR)listview_subclass_proc);
716     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
717 
718     return hwnd;
719 }
720 
721 static BOOL is_win_xp(void)
722 {
723     HWND hwnd, header;
724     BOOL ret;
725 
726     hwnd = create_listview_control(LVS_ICON);
727     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, LVS_EX_HEADERINALLVIEWS);
728     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
729     ret = !IsWindow(header);
730 
731     DestroyWindow(hwnd);
732 
733     return ret;
734 }
735 
736 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
737 {
738     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
739     static LONG defwndproc_counter = 0;
740     struct message msg = { 0 };
741     LRESULT ret;
742 
743     msg.message = message;
744     msg.flags = sent|wparam|lparam;
745     if (defwndproc_counter) msg.flags |= defwinproc;
746     msg.wParam = wParam;
747     msg.lParam = lParam;
748     msg.id = HEADER_ID;
749     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
750 
751     defwndproc_counter++;
752     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
753     defwndproc_counter--;
754     return ret;
755 }
756 
757 static HWND subclass_header(HWND hwndListview)
758 {
759     WNDPROC oldproc;
760     HWND hwnd;
761 
762     hwnd = (HWND)SendMessageA(hwndListview, LVM_GETHEADER, 0, 0);
763     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
764                                          (LONG_PTR)header_subclass_proc);
765     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
766 
767     return hwnd;
768 }
769 
770 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
771 {
772     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
773     static LONG defwndproc_counter = 0;
774     struct message msg = { 0 };
775     LRESULT ret;
776 
777     msg.message = message;
778     msg.flags = sent|wparam|lparam;
779     if (defwndproc_counter) msg.flags |= defwinproc;
780     msg.wParam = wParam;
781     msg.lParam = lParam;
782 
783     /* all we need is sizing */
784     if (message == WM_WINDOWPOSCHANGING ||
785         message == WM_NCCALCSIZE ||
786         message == WM_WINDOWPOSCHANGED ||
787         message == WM_MOVE ||
788         message == WM_SIZE)
789     {
790         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
791     }
792 
793     defwndproc_counter++;
794     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
795     defwndproc_counter--;
796     return ret;
797 }
798 
799 static HWND subclass_editbox(HWND hwndListview)
800 {
801     WNDPROC oldproc;
802     HWND hwnd;
803 
804     hwnd = (HWND)SendMessageA(hwndListview, LVM_GETEDITCONTROL, 0, 0);
805     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
806                                          (LONG_PTR)editbox_subclass_proc);
807     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
808 
809     return hwnd;
810 }
811 
812 /* Performs a single LVM_HITTEST test */
813 static void test_lvm_hittest_(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
814                               BOOL todo_item, BOOL todo_flags, int line)
815 {
816     LVHITTESTINFO lpht;
817     INT ret;
818 
819     lpht.pt.x = x;
820     lpht.pt.y = y;
821     lpht.iSubItem = 10;
822 
823     ret = SendMessageA(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
824 
825     todo_wine_if(todo_item)
826     {
827         ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
828         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
829         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
830     }
831 
832     if (todo_flags)
833     {
834         todo_wine
835             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
836     }
837     else if (broken_flags)
838         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
839                             "Expected flags %x, got %x\n", flags, lpht.flags);
840     else
841         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
842 }
843 
844 #define test_lvm_hittest(a,b,c,d,e,f,g,h) test_lvm_hittest_(a,b,c,d,e,f,g,h,__LINE__)
845 
846 /* Performs a single LVM_SUBITEMHITTEST test */
847 static void test_lvm_subitemhittest_(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
848                                      BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
849 {
850     LVHITTESTINFO lpht;
851     INT ret;
852 
853     lpht.pt.x = x;
854     lpht.pt.y = y;
855 
856     ret = SendMessageA(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
857 
858     todo_wine_if(todo_item)
859     {
860         ok_(__FILE__, line)(ret == item, "Expected %d retval, got %d\n", item, ret);
861         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
862     }
863 
864     todo_wine_if(todo_subitem)
865         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
866 
867     todo_wine_if(todo_flags)
868         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags 0x%x, got 0x%x\n", flags, lpht.flags);
869 }
870 
871 #define test_lvm_subitemhittest(a,b,c,d,e,f,g,h,i) test_lvm_subitemhittest_(a,b,c,d,e,f,g,h,i,__LINE__)
872 
873 static void test_images(void)
874 {
875     HWND hwnd;
876     INT r;
877     LVITEMA item;
878     HIMAGELIST himl;
879     HBITMAP hbmp;
880     RECT r1, r2;
881     static CHAR hello[] = "hello";
882 
883     himl = pImageList_Create(40, 40, 0, 4, 4);
884     ok(himl != NULL, "failed to create imagelist\n");
885 
886     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
887     ok(hbmp != NULL, "failed to create bitmap\n");
888 
889     r = pImageList_Add(himl, hbmp, 0);
890     ok(r == 0, "should be zero\n");
891 
892     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_OWNERDRAWFIXED,
893                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
894     ok(hwnd != NULL, "failed to create listview window\n");
895 
896     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
897                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
898 
899     ok(r == 0, "should return zero\n");
900 
901     r = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
902     ok(r == 0, "should return zero\n");
903 
904     r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
905     ok(r != 0, "got 0\n");
906 
907     /* returns dimensions */
908 
909     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
910     ok(r == 0, "should be zero items\n");
911 
912     item.mask = LVIF_IMAGE | LVIF_TEXT;
913     item.iItem = 0;
914     item.iSubItem = 1;
915     item.iImage = 0;
916     item.pszText = 0;
917     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
918     ok(r == -1, "should fail\n");
919 
920     item.iSubItem = 0;
921     item.pszText = hello;
922     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
923     ok(r == 0, "should not fail\n");
924 
925     SetRect(&r1, LVIR_ICON, 0, 0, 0);
926     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
927     expect(1, r);
928 
929     r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0);
930     ok(r == TRUE, "should not fail\n");
931 
932     item.iSubItem = 0;
933     item.pszText = hello;
934     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
935     ok(r == 0, "should not fail\n");
936 
937     SetRect(&r2, LVIR_ICON, 0, 0, 0);
938     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
939     expect(1, r);
940 
941     ok(EqualRect(&r1, &r2), "rectangle should be the same\n");
942 
943     DestroyWindow(hwnd);
944 }
945 
946 static void test_checkboxes(void)
947 {
948     HWND hwnd;
949     LVITEMA item;
950     DWORD r;
951     static CHAR text[]  = "Text",
952                 text2[] = "Text2",
953                 text3[] = "Text3";
954 
955     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
956                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
957     ok(hwnd != NULL, "failed to create listview window\n");
958 
959     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
960     item.mask = LVIF_TEXT | LVIF_STATE;
961     item.stateMask = 0xffff;
962     item.state = 0xfccc;
963     item.iItem = 0;
964     item.iSubItem = 0;
965     item.pszText = text;
966     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
967     expect(0, r);
968 
969     item.iItem = 0;
970     item.mask = LVIF_STATE;
971     item.stateMask = 0xffff;
972     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
973     expect(1, r);
974     ok(item.state == 0xfccc, "state %x\n", item.state);
975 
976     /* Don't set LVIF_STATE */
977     item.mask = LVIF_TEXT;
978     item.stateMask = 0xffff;
979     item.state = 0xfccc;
980     item.iItem = 1;
981     item.iSubItem = 0;
982     item.pszText = text;
983     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
984     expect(1, r);
985 
986     item.iItem = 1;
987     item.mask = LVIF_STATE;
988     item.stateMask = 0xffff;
989     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
990     expect(1, r);
991     ok(item.state == 0, "state %x\n", item.state);
992 
993     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
994     expect(0, r);
995 
996     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
997     item.iItem = 0;
998     item.mask = LVIF_STATE;
999     item.stateMask = 0xffff;
1000     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1001     expect(1, r);
1002     if (item.state != 0x1ccc)
1003     {
1004         win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
1005         DestroyWindow(hwnd);
1006         return;
1007     }
1008 
1009     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
1010     item.iItem = 2;
1011     item.mask = LVIF_TEXT;
1012     item.state = 0;
1013     item.pszText = text2;
1014     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1015     expect(2, r);
1016 
1017     item.iItem = 2;
1018     item.mask = LVIF_STATE;
1019     item.stateMask = 0xffff;
1020     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1021     expect(1, r);
1022     ok(item.state == 0x1000, "state %x\n", item.state);
1023 
1024     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
1025     item.iItem = 3;
1026     item.mask = LVIF_TEXT | LVIF_STATE;
1027     item.stateMask = 0xffff;
1028     item.state = 0x2aaa;
1029     item.pszText = text3;
1030     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1031     expect(3, r);
1032 
1033     item.iItem = 3;
1034     item.mask = LVIF_STATE;
1035     item.stateMask = 0xffff;
1036     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1037     expect(1, r);
1038     ok(item.state == 0x1aaa, "state %x\n", item.state);
1039 
1040     /* Set an item's state to checked */
1041     item.iItem = 3;
1042     item.mask = LVIF_STATE;
1043     item.stateMask = 0xf000;
1044     item.state = 0x2000;
1045     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1046     expect(1, r);
1047 
1048     item.iItem = 3;
1049     item.mask = LVIF_STATE;
1050     item.stateMask = 0xffff;
1051     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1052     expect(1, r);
1053     ok(item.state == 0x2aaa, "state %x\n", item.state);
1054 
1055     /* Check that only the bits we asked for are returned,
1056      * and that all the others are set to zero
1057      */
1058     item.iItem = 3;
1059     item.mask = LVIF_STATE;
1060     item.stateMask = 0xf000;
1061     item.state = 0xffff;
1062     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1063     expect(1, r);
1064     ok(item.state == 0x2000, "state %x\n", item.state);
1065 
1066     /* Set the style again and check that doesn't change an item's state */
1067     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
1068     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
1069 
1070     item.iItem = 3;
1071     item.mask = LVIF_STATE;
1072     item.stateMask = 0xffff;
1073     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1074     expect(1, r);
1075     ok(item.state == 0x2aaa, "state %x\n", item.state);
1076 
1077     /* Unsetting the checkbox extended style doesn't change an item's state */
1078     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
1079     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
1080 
1081     item.iItem = 3;
1082     item.mask = LVIF_STATE;
1083     item.stateMask = 0xffff;
1084     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1085     expect(1, r);
1086     ok(item.state == 0x2aaa, "state %x\n", item.state);
1087 
1088     /* Now setting the style again will change an item's state */
1089     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
1090     expect(0, r);
1091 
1092     item.iItem = 3;
1093     item.mask = LVIF_STATE;
1094     item.stateMask = 0xffff;
1095     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1096     expect(1, r);
1097     ok(item.state == 0x1aaa, "state %x\n", item.state);
1098 
1099     /* Toggle checkbox tests (bug 9934) */
1100     memset (&item, 0xcc, sizeof(item));
1101     item.mask = LVIF_STATE;
1102     item.iItem = 3;
1103     item.iSubItem = 0;
1104     item.state = LVIS_FOCUSED;
1105     item.stateMask = LVIS_FOCUSED;
1106     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1107     expect(1, r);
1108 
1109     item.iItem = 3;
1110     item.mask = LVIF_STATE;
1111     item.stateMask = 0xffff;
1112     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1113     expect(1, r);
1114     ok(item.state == 0x1aab, "state %x\n", item.state);
1115 
1116     r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0);
1117     expect(0, r);
1118     r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0);
1119     expect(0, r);
1120 
1121     item.iItem = 3;
1122     item.mask = LVIF_STATE;
1123     item.stateMask = 0xffff;
1124     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1125     expect(1, r);
1126     ok(item.state == 0x2aab, "state %x\n", item.state);
1127 
1128     r = SendMessageA(hwnd, WM_KEYDOWN, VK_SPACE, 0);
1129     expect(0, r);
1130     r = SendMessageA(hwnd, WM_KEYUP, VK_SPACE, 0);
1131     expect(0, r);
1132 
1133     item.iItem = 3;
1134     item.mask = LVIF_STATE;
1135     item.stateMask = 0xffff;
1136     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1137     expect(1, r);
1138     ok(item.state == 0x1aab, "state %x\n", item.state);
1139 
1140     DestroyWindow(hwnd);
1141 }
1142 
1143 static void insert_column(HWND hwnd, int idx)
1144 {
1145     LVCOLUMNA column;
1146     INT rc;
1147 
1148     memset(&column, 0xcc, sizeof(column));
1149     column.mask = LVCF_SUBITEM;
1150     column.iSubItem = idx;
1151 
1152     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, idx, (LPARAM)&column);
1153     expect(idx, rc);
1154 }
1155 
1156 static void insert_item(HWND hwnd, int idx)
1157 {
1158     static CHAR text[] = "foo";
1159 
1160     LVITEMA item;
1161     INT rc;
1162 
1163     memset(&item, 0xcc, sizeof (item));
1164     item.mask = LVIF_TEXT;
1165     item.iItem = idx;
1166     item.iSubItem = 0;
1167     item.pszText = text;
1168 
1169     rc = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
1170     expect(idx, rc);
1171 }
1172 
1173 static void test_items(void)
1174 {
1175     const LPARAM lparamTest = 0x42;
1176     static CHAR text[] = "Text";
1177     char buffA[5];
1178     HWND hwnd;
1179     LVITEMA item;
1180     DWORD r;
1181 
1182     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
1183                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1184     ok(hwnd != NULL, "failed to create listview window\n");
1185 
1186     /*
1187      * Test setting/getting item params
1188      */
1189 
1190     /* Set up two columns */
1191     insert_column(hwnd, 0);
1192     insert_column(hwnd, 1);
1193 
1194     /* LVIS_SELECTED with zero stateMask */
1195     /* set */
1196     memset (&item, 0, sizeof (item));
1197     item.mask = LVIF_STATE;
1198     item.state = LVIS_SELECTED;
1199     item.stateMask = 0;
1200     item.iItem = 0;
1201     item.iSubItem = 0;
1202     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1203     expect(0, r);
1204     /* get */
1205     memset (&item, 0xcc, sizeof (item));
1206     item.mask = LVIF_STATE;
1207     item.stateMask = LVIS_SELECTED;
1208     item.state = 0;
1209     item.iItem = 0;
1210     item.iSubItem = 0;
1211     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1212     expect(1, r);
1213     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1214     r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
1215     ok(r, "got %d\n", r);
1216 
1217     /* LVIS_SELECTED with zero stateMask */
1218     /* set */
1219     memset (&item, 0, sizeof (item));
1220     item.mask = LVIF_STATE;
1221     item.state = LVIS_FOCUSED;
1222     item.stateMask = 0;
1223     item.iItem = 0;
1224     item.iSubItem = 0;
1225     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1226     expect(0, r);
1227     /* get */
1228     memset (&item, 0xcc, sizeof (item));
1229     item.mask = LVIF_STATE;
1230     item.stateMask = LVIS_FOCUSED;
1231     item.state = 0;
1232     item.iItem = 0;
1233     item.iSubItem = 0;
1234     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1235     expect(1, r);
1236     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1237     r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
1238     ok(r, "got %d\n", r);
1239 
1240     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1241     /* set */
1242     memset (&item, 0, sizeof (item));
1243     item.mask = LVIF_STATE;
1244     item.state = LVIS_CUT;
1245     item.stateMask = LVIS_FOCUSED;
1246     item.iItem = 0;
1247     item.iSubItem = 0;
1248     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1249     expect(0, r);
1250     /* get */
1251     memset (&item, 0xcc, sizeof (item));
1252     item.mask = LVIF_STATE;
1253     item.stateMask = LVIS_CUT;
1254     item.state = 0;
1255     item.iItem = 0;
1256     item.iSubItem = 0;
1257     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1258     expect(1, r);
1259     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1260     r = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
1261     ok(r, "got %d\n", r);
1262 
1263     /* Insert an item with just a param */
1264     memset (&item, 0xcc, sizeof (item));
1265     item.mask = LVIF_PARAM;
1266     item.iItem = 0;
1267     item.iSubItem = 0;
1268     item.lParam = lparamTest;
1269     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1270     expect(0, r);
1271 
1272     /* Test getting of the param */
1273     memset (&item, 0xcc, sizeof (item));
1274     item.mask = LVIF_PARAM;
1275     item.iItem = 0;
1276     item.iSubItem = 0;
1277     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1278     expect(1, r);
1279     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1280 
1281     /* Set up a subitem */
1282     memset (&item, 0xcc, sizeof (item));
1283     item.mask = LVIF_TEXT;
1284     item.iItem = 0;
1285     item.iSubItem = 1;
1286     item.pszText = text;
1287     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1288     expect(1, r);
1289 
1290     item.mask = LVIF_TEXT;
1291     item.iItem = 0;
1292     item.iSubItem = 1;
1293     item.pszText = buffA;
1294     item.cchTextMax = sizeof(buffA);
1295     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1296     expect(1, r);
1297     ok(!memcmp(item.pszText, text, sizeof(text)), "got text %s, expected %s\n", item.pszText, text);
1298 
1299     /* set up with extra flag */
1300     /* 1. reset subitem text */
1301     item.mask = LVIF_TEXT;
1302     item.iItem = 0;
1303     item.iSubItem = 1;
1304     item.pszText = NULL;
1305     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1306     expect(1, r);
1307 
1308     item.mask = LVIF_TEXT;
1309     item.iItem = 0;
1310     item.iSubItem = 1;
1311     item.pszText = buffA;
1312     buffA[0] = 'a';
1313     item.cchTextMax = sizeof(buffA);
1314     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1315     expect(1, r);
1316     ok(item.pszText[0] == 0, "got %p\n", item.pszText);
1317 
1318     /* 2. set new text with extra flag specified */
1319     item.mask = LVIF_TEXT | LVIF_DI_SETITEM;
1320     item.iItem = 0;
1321     item.iSubItem = 1;
1322     item.pszText = text;
1323     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1324     ok(r == 1 || broken(r == 0) /* NT4 */, "ret %d\n", r);
1325 
1326     if (r == 1)
1327     {
1328         item.mask = LVIF_TEXT;
1329         item.iItem = 0;
1330         item.iSubItem = 1;
1331         item.pszText = buffA;
1332         buffA[0] = 'a';
1333         item.cchTextMax = sizeof(buffA);
1334         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1335         expect(1, r);
1336         ok(!memcmp(item.pszText, text, sizeof(text)), "got %s, expected %s\n", item.pszText, text);
1337     }
1338 
1339     /* Query param from subitem: returns main item param */
1340     memset (&item, 0xcc, sizeof (item));
1341     item.mask = LVIF_PARAM;
1342     item.iItem = 0;
1343     item.iSubItem = 1;
1344     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1345     expect(1, r);
1346     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1347 
1348     /* Set up param on first subitem: no effect */
1349     memset (&item, 0xcc, sizeof (item));
1350     item.mask = LVIF_PARAM;
1351     item.iItem = 0;
1352     item.iSubItem = 1;
1353     item.lParam = lparamTest+1;
1354     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1355     expect(0, r);
1356 
1357     /* Query param from subitem again: should still return main item param */
1358     memset (&item, 0xcc, sizeof (item));
1359     item.mask = LVIF_PARAM;
1360     item.iItem = 0;
1361     item.iSubItem = 1;
1362     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1363     expect(1, r);
1364     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1365 
1366     /**** Some tests of state highlighting ****/
1367     memset (&item, 0xcc, sizeof (item));
1368     item.mask = LVIF_STATE;
1369     item.iItem = 0;
1370     item.iSubItem = 0;
1371     item.state = LVIS_SELECTED;
1372     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1373     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1374     expect(1, r);
1375     item.iSubItem = 1;
1376     item.state = LVIS_DROPHILITED;
1377     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1378     expect(1, r);
1379 
1380     memset (&item, 0xcc, sizeof (item));
1381     item.mask = LVIF_STATE;
1382     item.iItem = 0;
1383     item.iSubItem = 0;
1384     item.stateMask = -1;
1385     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1386     expect(1, r);
1387     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1388     item.iSubItem = 1;
1389     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1390     expect(1, r);
1391     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1392 
1393     /* some notnull but meaningless masks */
1394     memset (&item, 0, sizeof(item));
1395     item.mask = LVIF_NORECOMPUTE;
1396     item.iItem = 0;
1397     item.iSubItem = 0;
1398     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1399     expect(1, r);
1400     memset (&item, 0, sizeof(item));
1401     item.mask = LVIF_DI_SETITEM;
1402     item.iItem = 0;
1403     item.iSubItem = 0;
1404     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1405     expect(1, r);
1406 
1407     /* set text to callback value already having it */
1408     r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0);
1409     expect(TRUE, r);
1410     memset (&item, 0, sizeof (item));
1411     item.mask  = LVIF_TEXT;
1412     item.pszText = LPSTR_TEXTCALLBACKA;
1413     item.iItem = 0;
1414     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1415     expect(0, r);
1416     memset (&item, 0, sizeof (item));
1417 
1418     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1419 
1420     item.pszText = LPSTR_TEXTCALLBACKA;
1421     r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0 , (LPARAM) &item);
1422     expect(TRUE, r);
1423 
1424     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1425                 "check callback text comparison rule", FALSE);
1426 
1427     DestroyWindow(hwnd);
1428 }
1429 
1430 static void test_columns(void)
1431 {
1432     HWND hwnd, header;
1433     LVCOLUMNA column;
1434     LVITEMA item;
1435     INT order[2];
1436     CHAR buff[5];
1437     DWORD rc;
1438 
1439     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_LIST,
1440                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1441     ok(hwnd != NULL, "failed to create listview window\n");
1442 
1443     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
1444     ok(header == NULL, "got %p\n", header);
1445 
1446     rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1447     ok(rc == 0, "got %d\n", rc);
1448 
1449     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
1450     ok(header == NULL, "got %p\n", header);
1451 
1452     DestroyWindow(hwnd);
1453 
1454     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", LVS_REPORT,
1455                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1456     ok(hwnd != NULL, "failed to create listview window\n");
1457 
1458     rc = SendMessageA(hwnd, LVM_DELETECOLUMN, -1, 0);
1459     ok(!rc, "got %d\n", rc);
1460 
1461     rc = SendMessageA(hwnd, LVM_DELETECOLUMN, 0, 0);
1462     ok(!rc, "got %d\n", rc);
1463 
1464     /* Add a column with no mask */
1465     memset(&column, 0xcc, sizeof(column));
1466     column.mask = 0;
1467     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column);
1468     ok(rc == 0, "Inserting column with no mask failed with %d\n", rc);
1469 
1470     /* Check its width */
1471     rc = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
1472     ok(rc == 10, "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1473 
1474     DestroyWindow(hwnd);
1475 
1476     /* LVM_GETCOLUMNORDERARRAY */
1477     hwnd = create_listview_control(LVS_REPORT);
1478     subclass_header(hwnd);
1479 
1480     memset(&column, 0, sizeof(column));
1481     column.mask = LVCF_WIDTH;
1482     column.cx = 100;
1483     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&column);
1484     expect(0, rc);
1485 
1486     column.cx = 200;
1487     rc = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&column);
1488     expect(1, rc);
1489 
1490     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1491 
1492     rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1493     expect(1, rc);
1494     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1495     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1496 
1497     rc = SendMessageA(hwnd, LVM_GETCOLUMNORDERARRAY, 0, 0);
1498     expect(0, rc);
1499 
1500     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1501 
1502     /* LVM_SETCOLUMNORDERARRAY */
1503     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1504 
1505     order[0] = 0;
1506     order[1] = 1;
1507     rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1508     expect(1, rc);
1509 
1510     rc = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 0, 0);
1511     expect(0, rc);
1512 
1513     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_setorderarray_seq, "set order array", FALSE);
1514 
1515     /* after column added subitem is considered as present */
1516     insert_item(hwnd, 0);
1517 
1518     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1519 
1520     item.pszText = buff;
1521     item.cchTextMax = sizeof(buff);
1522     item.iItem = 0;
1523     item.iSubItem = 1;
1524     item.mask = LVIF_TEXT;
1525     memset(&g_itema, 0, sizeof(g_itema));
1526     rc = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
1527     expect(1, rc);
1528     ok(g_itema.iSubItem == 1, "got %d\n", g_itema.iSubItem);
1529 
1530     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
1531         "get subitem text after column added", FALSE);
1532 
1533     DestroyWindow(hwnd);
1534 }
1535 
1536 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1537 static WNDPROC listviewWndProc;
1538 static HIMAGELIST test_create_imagelist;
1539 
1540 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1541 {
1542     LRESULT ret;
1543 
1544     if (uMsg == WM_CREATE)
1545     {
1546         CREATESTRUCTA *lpcs = (CREATESTRUCTA*)lParam;
1547         lpcs->style |= LVS_REPORT;
1548     }
1549     ret = CallWindowProcA(listviewWndProc, hwnd, uMsg, wParam, lParam);
1550     if (uMsg == WM_CREATE) SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1551     return ret;
1552 }
1553 
1554 /* Header creation is delayed in classic implementation. */
1555 #define TEST_NO_HEADER(a) test_header_presence_(a, FALSE, __LINE__)
1556 #define TEST_HEADER_EXPECTED(a) test_header_presence_(a, TRUE, __LINE__)
1557 #define TEST_NO_HEADER2(a, b) test_header_presence_(a, b, __LINE__)
1558 static void test_header_presence_(HWND hwnd, BOOL present, int line)
1559 {
1560     HWND header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
1561 
1562     if (present)
1563     {
1564         ok_(__FILE__, line)(IsWindow(header), "Header should have been created.\n");
1565         if (header) /* FIXME: remove when todo's are fixed */
1566             ok_(__FILE__, line)(header == GetDlgItem(hwnd, 0), "Dialog item expected.\n");
1567     }
1568     else
1569     {
1570         ok_(__FILE__, line)(!IsWindow(header), "Header shouldn't be created.\n");
1571         ok_(__FILE__, line)(NULL == GetDlgItem(hwnd, 0), "NULL dialog item expected.\n");
1572     }
1573 }
1574 
1575 static void test_create(BOOL is_version_6)
1576 {
1577     static const WCHAR testtextW[] = {'t','e','s','t',' ','t','e','x','t',0};
1578     char buff[16];
1579     HWND hList;
1580     HWND hHeader;
1581     LONG_PTR ret;
1582     LONG r;
1583     LVCOLUMNA col;
1584     RECT rect;
1585     WNDCLASSEXA cls;
1586     DWORD style;
1587     ATOM class;
1588 
1589     if (is_win_xp() && is_version_6)
1590     {
1591         win_skip("Skipping some tests on XP.\n");
1592         return;
1593     }
1594 
1595     cls.cbSize = sizeof(WNDCLASSEXA);
1596     r = GetClassInfoExA(GetModuleHandleA(NULL), WC_LISTVIEWA, &cls);
1597     ok(r, "Failed to get class info.\n");
1598     listviewWndProc = cls.lpfnWndProc;
1599     cls.lpfnWndProc = create_test_wndproc;
1600     cls.lpszClassName = "MyListView32";
1601     class = RegisterClassExA(&cls);
1602     ok(class, "Failed to register class.\n");
1603 
1604     test_create_imagelist = pImageList_Create(16, 16, 0, 5, 10);
1605     hList = CreateWindowA("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
1606     ok((HIMAGELIST)SendMessageA(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1607     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
1608     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1609     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1610     DestroyWindow(hList);
1611 
1612     /* header isn't created on LVS_ICON and LVS_LIST styles */
1613     hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
1614     TEST_NO_HEADER(hList);
1615 
1616     /* insert column */
1617     memset(&col, 0, sizeof(LVCOLUMNA));
1618     col.mask = LVCF_WIDTH;
1619     col.cx = 100;
1620     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
1621     expect(0, r);
1622     TEST_HEADER_EXPECTED(hList);
1623     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
1624     style = GetWindowLongA(hHeader, GWL_STYLE);
1625     ok(!(style & HDS_HIDDEN), "Not expected HDS_HIDDEN\n");
1626     DestroyWindow(hList);
1627 
1628     hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1629                            GetModuleHandleA(NULL), 0);
1630     TEST_NO_HEADER(hList);
1631     /* insert column */
1632     memset(&col, 0, sizeof(LVCOLUMNA));
1633     col.mask = LVCF_WIDTH;
1634     col.cx = 100;
1635     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
1636     expect(0, r);
1637     TEST_HEADER_EXPECTED(hList);
1638     DestroyWindow(hList);
1639 
1640     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1641     hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1642                            GetModuleHandleA(NULL), 0);
1643     ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongPtrA(hList, GWL_STYLE) | LVS_REPORT);
1644     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1645     TEST_HEADER_EXPECTED(hList);
1646     ret = SetWindowLongPtrA(hList, GWL_STYLE, GetWindowLongA(hList, GWL_STYLE) & ~LVS_REPORT);
1647     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1648     TEST_HEADER_EXPECTED(hList);
1649     DestroyWindow(hList);
1650 
1651     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1652     hList = CreateWindowA(WC_LISTVIEWA, "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1653                            GetModuleHandleA(NULL), 0);
1654     ret = SetWindowLongPtrA(hList, GWL_STYLE,
1655                            (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1656     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1657     TEST_HEADER_EXPECTED(hList);
1658     ret = SetWindowLongPtrA(hList, GWL_STYLE, (GetWindowLongPtrA(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1659     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1660     TEST_HEADER_EXPECTED(hList);
1661     DestroyWindow(hList);
1662 
1663     /* LVS_REPORT without WS_VISIBLE */
1664     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1665                           GetModuleHandleA(NULL), 0);
1666     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
1667 todo_wine_if(is_version_6)
1668     TEST_NO_HEADER2(hList, is_version_6);
1669 
1670     /* insert column */
1671     memset(&col, 0, sizeof(LVCOLUMNA));
1672     col.mask = LVCF_WIDTH;
1673     col.cx = 100;
1674     r = SendMessageA(hList, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
1675     expect(0, r);
1676     TEST_HEADER_EXPECTED(hList);
1677     DestroyWindow(hList);
1678 
1679     /* LVS_REPORT without WS_VISIBLE, try to show it */
1680     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1681                           GetModuleHandleA(NULL), 0);
1682 todo_wine_if(is_version_6)
1683     TEST_NO_HEADER2(hList, is_version_6);
1684 
1685     ShowWindow(hList, SW_SHOW);
1686     TEST_HEADER_EXPECTED(hList);
1687     DestroyWindow(hList);
1688 
1689     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1690     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1691                           0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
1692     TEST_HEADER_EXPECTED(hList);
1693     hHeader = (HWND)SendMessageA(hList, LVM_GETHEADER, 0, 0);
1694     /* HDS_DRAGDROP set by default */
1695     ok(GetWindowLongPtrA(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1696     DestroyWindow(hList);
1697 
1698     /* setting LVS_EX_HEADERDRAGDROP creates header */
1699     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1700                           GetModuleHandleA(NULL), 0);
1701 todo_wine_if(is_version_6)
1702     TEST_NO_HEADER2(hList, is_version_6);
1703 
1704     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1705     TEST_HEADER_EXPECTED(hList);
1706     DestroyWindow(hList);
1707 
1708     /* setting LVS_EX_GRIDLINES creates header */
1709     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1710                           GetModuleHandleA(NULL), 0);
1711 todo_wine_if(is_version_6)
1712     TEST_NO_HEADER2(hList, is_version_6);
1713 
1714     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_GRIDLINES);
1715     TEST_HEADER_EXPECTED(hList);
1716     DestroyWindow(hList);
1717 
1718     /* setting LVS_EX_FULLROWSELECT creates header */
1719     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1720                           GetModuleHandleA(NULL), 0);
1721 todo_wine_if(is_version_6)
1722     TEST_NO_HEADER2(hList, is_version_6);
1723     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
1724     TEST_HEADER_EXPECTED(hList);
1725     DestroyWindow(hList);
1726 
1727     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1728     hList = create_listview_control(LVS_ICON);
1729     SendMessageA(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1730     r = SendMessageA(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1731     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1732     DestroyWindow(hList);
1733 
1734     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1735     hList = CreateWindowA(WC_LISTVIEWA, "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1736                           GetModuleHandleA(NULL), 0);
1737 todo_wine_if(is_version_6)
1738     TEST_NO_HEADER2(hList, is_version_6);
1739 
1740     SetRect(&rect, LVIR_BOUNDS, 1, -10, -10);
1741     r = SendMessageA(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1742     ok(r == 1, "Unexpected ret value %d.\n", r);
1743     /* right value contains garbage, probably because header columns are not set up */
1744     ok(rect.bottom >= 0, "Unexpected rectangle.\n");
1745 
1746 todo_wine_if(is_version_6)
1747     TEST_NO_HEADER2(hList, is_version_6);
1748     DestroyWindow(hList);
1749 
1750     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1751     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1752     hList = create_listview_control(LVS_OWNERDRAWFIXED | LVS_REPORT);
1753     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1754                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1755     DestroyWindow(hList);
1756 
1757     /* Test that window text is preserved. */
1758     hList = CreateWindowExA(0, WC_LISTVIEWA, "test text", WS_CHILD | WS_BORDER | WS_VISIBLE,
1759         0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL);
1760     ok(hList != NULL, "Failed to create ListView window.\n");
1761     *buff = 0;
1762     GetWindowTextA(hList, buff, sizeof(buff));
1763     ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff);
1764     DestroyWindow(hList);
1765 
1766     hList = CreateWindowExW(0, WC_LISTVIEWW, testtextW, WS_CHILD | WS_BORDER | WS_VISIBLE,
1767         0, 0, 100, 100, hwndparent, NULL, GetModuleHandleA(NULL), NULL);
1768     ok(hList != NULL, "Failed to create ListView window.\n");
1769     *buff = 0;
1770     GetWindowTextA(hList, buff, sizeof(buff));
1771     ok(!strcmp(buff, "test text"), "Unexpected window text %s.\n", buff);
1772     DestroyWindow(hList);
1773 
1774     r = UnregisterClassA("MyListView32", NULL);
1775     ok(r, "Failed to unregister test class.\n");
1776 }
1777 
1778 static void test_redraw(void)
1779 {
1780     HWND hwnd;
1781     HDC hdc;
1782     BOOL res;
1783     DWORD r;
1784 
1785     hwnd = create_listview_control(LVS_REPORT);
1786     subclass_header(hwnd);
1787 
1788     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1789 
1790     InvalidateRect(hwnd, NULL, TRUE);
1791     UpdateWindow(hwnd);
1792     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1793 
1794     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1795 
1796     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1797     /* 1. Without backbuffer */
1798     res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
1799     expect(TRUE, res);
1800 
1801     hdc = GetWindowDC(hwndparent);
1802 
1803     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1804     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1805     ok(r == 1, "Expected not zero result\n");
1806     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1807                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1808 
1809     res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT);
1810     expect(TRUE, res);
1811 
1812     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1813     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1814     expect(1, r);
1815     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1816                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1817 
1818     /* 2. With backbuffer */
1819     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1820                                                      LVS_EX_DOUBLEBUFFER);
1821     res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
1822     expect(TRUE, res);
1823 
1824     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1825     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1826     expect(1, r);
1827     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1828                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1829 
1830     res = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_DEFAULT);
1831     expect(TRUE, res);
1832 
1833     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1834     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1835     todo_wine expect(1, r);
1836     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1837                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1838 
1839     ReleaseDC(hwndparent, hdc);
1840 
1841     DestroyWindow(hwnd);
1842 }
1843 
1844 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
1845 {
1846     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1847 
1848     if(message == WM_NOTIFY) {
1849         NMHDR *nmhdr = (NMHDR*)lParam;
1850         if(nmhdr->code == NM_CUSTOMDRAW) {
1851             NMLVCUSTOMDRAW *nmlvcd = (NMLVCUSTOMDRAW*)nmhdr;
1852             struct message msg;
1853 
1854             msg.message = message;
1855             msg.flags = sent|wparam|lparam|custdraw;
1856             msg.wParam = wParam;
1857             msg.lParam = lParam;
1858             msg.id = nmhdr->code;
1859             msg.stage = nmlvcd->nmcd.dwDrawStage;
1860             add_message(sequences, PARENT_CD_SEQ_INDEX, &msg);
1861 
1862             switch(nmlvcd->nmcd.dwDrawStage) {
1863             case CDDS_PREPAINT:
1864                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1865                 return CDRF_NOTIFYITEMDRAW|CDRF_NOTIFYPOSTPAINT;
1866             case CDDS_ITEMPREPAINT:
1867                 nmlvcd->clrTextBk = CLR_DEFAULT;
1868                 nmlvcd->clrText = RGB(0, 255, 0);
1869                 return CDRF_NOTIFYSUBITEMDRAW|CDRF_NOTIFYPOSTPAINT;
1870             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1871                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1872                 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk);
1873                 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText);
1874                 if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS))
1875                 {
1876                     todo_wine_if(nmlvcd->iSubItem)
1877                         ok(clr == c0ffee, "clr=%.8x\n", clr);
1878                 }
1879                 return CDRF_NOTIFYPOSTPAINT;
1880             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1881                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1882                 if (!(GetWindowLongW(nmhdr->hwndFrom, GWL_STYLE) & LVS_SHOWSELALWAYS))
1883                     todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1884                 ok(nmlvcd->clrTextBk == CLR_DEFAULT, "got 0x%x\n", nmlvcd->clrTextBk);
1885                 ok(nmlvcd->clrText == RGB(0, 255, 0), "got 0x%x\n", nmlvcd->clrText);
1886                 return CDRF_DODEFAULT;
1887             }
1888             return CDRF_DODEFAULT;
1889         }
1890     }
1891 
1892     return DefWindowProcA(hwnd, message, wParam, lParam);
1893 }
1894 
1895 static void test_customdraw(void)
1896 {
1897     HWND hwnd;
1898     WNDPROC oldwndproc;
1899     LVITEMA item;
1900 
1901     hwnd = create_listview_control(LVS_REPORT);
1902 
1903     insert_column(hwnd, 0);
1904     insert_column(hwnd, 1);
1905     insert_item(hwnd, 0);
1906 
1907     oldwndproc = (WNDPROC)SetWindowLongPtrA(hwndparent, GWLP_WNDPROC,
1908                                            (LONG_PTR)cd_wndproc);
1909 
1910     InvalidateRect(hwnd, NULL, TRUE);
1911     UpdateWindow(hwnd);
1912 
1913     /* message tests */
1914     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1915     InvalidateRect(hwnd, NULL, TRUE);
1916     UpdateWindow(hwnd);
1917     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT", FALSE);
1918 
1919     /* check colors when item is selected */
1920     SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) | LVS_SHOWSELALWAYS);
1921     item.mask = LVIF_STATE;
1922     item.stateMask = LVIS_SELECTED;
1923     item.state = LVIS_SELECTED;
1924     SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
1925 
1926     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1927     InvalidateRect(hwnd, NULL, TRUE);
1928     UpdateWindow(hwnd);
1929     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_report_cd_seq, "parent customdraw, LVS_REPORT, selection", FALSE);
1930 
1931     DestroyWindow(hwnd);
1932 
1933     hwnd = create_listview_control(LVS_LIST);
1934 
1935     insert_column(hwnd, 0);
1936     insert_column(hwnd, 1);
1937     insert_item(hwnd, 0);
1938 
1939     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1940     InvalidateRect(hwnd, NULL, TRUE);
1941     UpdateWindow(hwnd);
1942     ok_sequence(sequences, PARENT_CD_SEQ_INDEX, parent_list_cd_seq, "parent customdraw, LVS_LIST", FALSE);
1943 
1944     SetWindowLongPtrA(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1945     DestroyWindow(hwnd);
1946 }
1947 
1948 static void test_icon_spacing(void)
1949 {
1950     /* LVM_SETICONSPACING */
1951     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1952 
1953     HWND hwnd;
1954     WORD w, h;
1955     INT r;
1956 
1957     hwnd = create_listview_control(LVS_ICON);
1958     ok(hwnd != NULL, "failed to create a listview window\n");
1959 
1960     r = SendMessageA(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, NF_REQUERY);
1961     expect(NFR_ANSI, r);
1962 
1963     /* reset the icon spacing to defaults */
1964     SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1965 
1966     /* now we can request what the defaults are */
1967     r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1968     w = LOWORD(r);
1969     h = HIWORD(r);
1970 
1971     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1972 
1973     r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1974     ok(r == MAKELONG(w, h) ||
1975        broken(r == MAKELONG(w, w)), /* win98 */
1976        "Expected %d, got %d\n", MAKELONG(w, h), r);
1977 
1978     r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1979     expect(MAKELONG(20,30), r);
1980 
1981     r = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1982     expect(MAKELONG(25,35), r);
1983 
1984     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1985 
1986     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1987     DestroyWindow(hwnd);
1988 }
1989 
1990 static void test_color(void)
1991 {
1992     RECT rect;
1993     HWND hwnd;
1994     DWORD r;
1995     int i;
1996 
1997     COLORREF color;
1998     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1999 
2000     hwnd = create_listview_control(LVS_REPORT);
2001     ok(hwnd != NULL, "failed to create a listview window\n");
2002 
2003     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2004 
2005     for (i = 0; i < 4; i++)
2006     {
2007         color = colors[i];
2008 
2009         r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, color);
2010         expect(TRUE, r);
2011         r = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0);
2012         expect(color, r);
2013 
2014         r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, color);
2015         expect (TRUE, r);
2016         r = SendMessageA(hwnd, LVM_GETTEXTCOLOR, 0, 0);
2017         expect(color, r);
2018 
2019         r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
2020         expect(TRUE, r);
2021         r = SendMessageA(hwnd, LVM_GETTEXTBKCOLOR, 0, 0);
2022         expect(color, r);
2023     }
2024 
2025     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
2026     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2027 
2028     /* invalidation test done separately to avoid a message chain mess */
2029     r = ValidateRect(hwnd, NULL);
2030     expect(TRUE, r);
2031     r = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, colors[0]);
2032     expect(TRUE, r);
2033 
2034     rect.right = rect.bottom = 1;
2035     r = GetUpdateRect(hwnd, &rect, TRUE);
2036     todo_wine expect(FALSE, r);
2037     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
2038 
2039     r = ValidateRect(hwnd, NULL);
2040     expect(TRUE, r);
2041     r = SendMessageA(hwnd, LVM_SETTEXTCOLOR, 0, colors[0]);
2042     expect(TRUE, r);
2043 
2044     rect.right = rect.bottom = 1;
2045     r = GetUpdateRect(hwnd, &rect, TRUE);
2046     todo_wine expect(FALSE, r);
2047     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
2048 
2049     r = ValidateRect(hwnd, NULL);
2050     expect(TRUE, r);
2051     r = SendMessageA(hwnd, LVM_SETTEXTBKCOLOR, 0, colors[0]);
2052     expect(TRUE, r);
2053 
2054     rect.right = rect.bottom = 1;
2055     r = GetUpdateRect(hwnd, &rect, TRUE);
2056     todo_wine expect(FALSE, r);
2057     ok(rect.right == 0 && rect.bottom == 0, "got update rectangle\n");
2058 
2059     DestroyWindow(hwnd);
2060 }
2061 
2062 static void test_item_count(void)
2063 {
2064     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
2065 
2066     HWND hwnd;
2067     DWORD r;
2068     HDC hdc;
2069     HFONT hOldFont;
2070     TEXTMETRICA tm;
2071     RECT rect;
2072     INT height;
2073 
2074     LVITEMA item0;
2075     LVITEMA item1;
2076     LVITEMA item2;
2077     static CHAR item0text[] = "item0";
2078     static CHAR item1text[] = "item1";
2079     static CHAR item2text[] = "item2";
2080 
2081     hwnd = create_listview_control(LVS_REPORT);
2082     ok(hwnd != NULL, "failed to create a listview window\n");
2083 
2084     /* resize in dpiaware manner to fit all 3 items added */
2085     hdc = GetDC(0);
2086     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
2087     GetTextMetricsA(hdc, &tm);
2088     /* 2 extra pixels for bounds and header border */
2089     height = tm.tmHeight + 2;
2090     SelectObject(hdc, hOldFont);
2091     ReleaseDC(0, hdc);
2092 
2093     GetWindowRect(hwnd, &rect);
2094     /* 3 items + 1 header + 1 to be sure */
2095     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
2096 
2097     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2098 
2099     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2100     expect(0, r);
2101 
2102     /* [item0] */
2103     item0.mask = LVIF_TEXT;
2104     item0.iItem = 0;
2105     item0.iSubItem = 0;
2106     item0.pszText = item0text;
2107     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0);
2108     expect(0, r);
2109 
2110     /* [item0, item1] */
2111     item1.mask = LVIF_TEXT;
2112     item1.iItem = 1;
2113     item1.iSubItem = 0;
2114     item1.pszText = item1text;
2115     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1);
2116     expect(1, r);
2117 
2118     /* [item0, item1, item2] */
2119     item2.mask = LVIF_TEXT;
2120     item2.iItem = 2;
2121     item2.iSubItem = 0;
2122     item2.pszText = item2text;
2123     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2);
2124     expect(2, r);
2125 
2126     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2127     expect(3, r);
2128 
2129     /* [item0, item1] */
2130     r = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0);
2131     expect(TRUE, r);
2132 
2133     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2134     expect(2, r);
2135 
2136     /* [] */
2137     r = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0);
2138     expect(TRUE, r);
2139 
2140     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2141     expect(0, r);
2142 
2143     /* [item0] */
2144     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1);
2145     expect(0, r);
2146 
2147     /* [item0, item1] */
2148     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1);
2149     expect(1, r);
2150 
2151     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2152     expect(2, r);
2153 
2154     /* [item0, item1, item2] */
2155     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2);
2156     expect(2, r);
2157 
2158     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2159     expect(3, r);
2160 
2161     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
2162 
2163     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2164     DestroyWindow(hwnd);
2165 }
2166 
2167 static void test_item_position(void)
2168 {
2169     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
2170 
2171     HWND hwnd;
2172     DWORD r;
2173     POINT position;
2174 
2175     LVITEMA item0;
2176     LVITEMA item1;
2177     LVITEMA item2;
2178     static CHAR item0text[] = "item0";
2179     static CHAR item1text[] = "item1";
2180     static CHAR item2text[] = "item2";
2181 
2182     hwnd = create_listview_control(LVS_ICON);
2183     ok(hwnd != NULL, "failed to create a listview window\n");
2184 
2185     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2186 
2187     /* [item0] */
2188     item0.mask = LVIF_TEXT;
2189     item0.iItem = 0;
2190     item0.iSubItem = 0;
2191     item0.pszText = item0text;
2192     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item0);
2193     expect(0, r);
2194 
2195     /* [item0, item1] */
2196     item1.mask = LVIF_TEXT;
2197     item1.iItem = 1;
2198     item1.iSubItem = 0;
2199     item1.pszText = item1text;
2200     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item1);
2201     expect(1, r);
2202 
2203     /* [item0, item1, item2] */
2204     item2.mask = LVIF_TEXT;
2205     item2.iItem = 2;
2206     item2.iSubItem = 0;
2207     item2.pszText = item2text;
2208     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item2);
2209     expect(2, r);
2210 
2211     r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
2212     expect(TRUE, r);
2213     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
2214     expect(TRUE, r);
2215     expect2(10, 5, position.x, position.y);
2216 
2217     r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
2218     expect(TRUE, r);
2219     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
2220     expect(TRUE, r);
2221     expect2(0, 0, position.x, position.y);
2222 
2223     r = SendMessageA(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
2224     expect(TRUE, r);
2225     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
2226     expect(TRUE, r);
2227     expect2(20, 20, position.x, position.y);
2228 
2229     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
2230 
2231     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2232     DestroyWindow(hwnd);
2233 }
2234 
2235 static void test_getorigin(void)
2236 {
2237     /* LVM_GETORIGIN */
2238 
2239     HWND hwnd;
2240     DWORD r;
2241     POINT position;
2242 
2243     position.x = position.y = 0;
2244 
2245     hwnd = create_listview_control(LVS_ICON);
2246     ok(hwnd != NULL, "failed to create a listview window\n");
2247     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2248 
2249     r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2250     expect(TRUE, r);
2251     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2252     DestroyWindow(hwnd);
2253 
2254     hwnd = create_listview_control(LVS_SMALLICON);
2255     ok(hwnd != NULL, "failed to create a listview window\n");
2256     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2257 
2258     r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2259     expect(TRUE, r);
2260     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2261     DestroyWindow(hwnd);
2262 
2263     hwnd = create_listview_control(LVS_LIST);
2264     ok(hwnd != NULL, "failed to create a listview window\n");
2265     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2266 
2267     r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2268     expect(FALSE, r);
2269     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2270     DestroyWindow(hwnd);
2271 
2272     hwnd = create_listview_control(LVS_REPORT);
2273     ok(hwnd != NULL, "failed to create a listview window\n");
2274     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2275 
2276     r = SendMessageA(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
2277     expect(FALSE, r);
2278     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2279     DestroyWindow(hwnd);
2280 }
2281 
2282 static void test_multiselect(void)
2283 {
2284     typedef struct t_select_task
2285     {
2286 	const char *descr;
2287         int initPos;
2288         int loopVK;
2289         int count;
2290 	int result;
2291     } select_task;
2292 
2293     HWND hwnd;
2294     INT r;
2295     int i, j;
2296     static const int items=5;
2297     DWORD item_count;
2298     BYTE kstate[256];
2299     select_task task;
2300     LONG_PTR style;
2301     LVITEMA item;
2302 
2303     static struct t_select_task task_list[] = {
2304         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
2305         { "using VK_UP", -1, VK_UP, -1, -1 },
2306         { "using VK_END", 0, VK_END, 1, -1 },
2307         { "using VK_HOME", -1, VK_HOME, 1, -1 }
2308     };
2309 
2310     hwnd = create_listview_control(LVS_REPORT);
2311 
2312     for (i = 0; i < items; i++)
2313         insert_item(hwnd, 0);
2314 
2315     item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2316     expect(items, item_count);
2317 
2318     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2319     ok(r == -1, "got %d\n", r);
2320 
2321     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0);
2322     ok(r == -1, "got %d\n", r);
2323 
2324     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, 0);
2325     ok(r == 0, "got %d\n", r);
2326 
2327     /* out of range index */
2328     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, items);
2329     ok(r == 0, "got %d\n", r);
2330 
2331     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2332     ok(r == 0, "got %d\n", r);
2333 
2334     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -2);
2335     ok(r == 0, "got %d\n", r);
2336 
2337     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2338     ok(r == 0, "got %d\n", r);
2339 
2340     for (i = 0; i < sizeof(task_list)/sizeof(task_list[0]); i++) {
2341         DWORD selected_count;
2342         LVITEMA item;
2343 
2344         task = task_list[i];
2345 
2346 	/* deselect all items */
2347         item.state = 0;
2348         item.stateMask = LVIS_SELECTED;
2349         r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2350         ok(r, "got %d\n", r);
2351 	SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2352 
2353 	/* set initial position */
2354         r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
2355         ok(r, "got %d\n", r);
2356 
2357         item.state = LVIS_SELECTED;
2358         item.stateMask = LVIS_SELECTED;
2359         r = SendMessageA(hwnd, LVM_SETITEMSTATE, task.initPos == -1 ? item_count-1 : task.initPos, (LPARAM)&item);
2360         ok(r, "got %d\n", r);
2361 
2362 	selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2363 	ok(selected_count == 1, "expected 1, got %d\n", selected_count);
2364 
2365 	/* Set SHIFT key pressed */
2366         GetKeyboardState(kstate);
2367         kstate[VK_SHIFT]=0x80;
2368         SetKeyboardState(kstate);
2369 
2370 	for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
2371 	    r = SendMessageA(hwnd, WM_KEYDOWN, task.loopVK, 0);
2372 	    expect(0,r);
2373 	    r = SendMessageA(hwnd, WM_KEYUP, task.loopVK, 0);
2374 	    expect(0,r);
2375 	}
2376 
2377 	selected_count = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2378 
2379 	ok((task.result == -1 ? item_count : task.result) == selected_count,
2380             "Failed multiple selection %s. There should be %d selected items (is %d)\n",
2381             task.descr, item_count, selected_count);
2382 
2383 	/* Set SHIFT key released */
2384 	GetKeyboardState(kstate);
2385         kstate[VK_SHIFT]=0x00;
2386         SetKeyboardState(kstate);
2387     }
2388     DestroyWindow(hwnd);
2389 
2390     /* make multiple selection, then switch to LVS_SINGLESEL */
2391     hwnd = create_listview_control(LVS_REPORT);
2392     for (i=0;i<items;i++) {
2393 	    insert_item(hwnd, 0);
2394     }
2395     item_count = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2396     expect(items,item_count);
2397 
2398     /* try with NULL pointer */
2399     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, 0);
2400     expect(FALSE, r);
2401 
2402     /* select all, check notifications */
2403     item.state = 0;
2404     item.stateMask = LVIS_SELECTED;
2405     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2406     ok(r, "got %d\n", r);
2407 
2408     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2409 
2410     item.stateMask = LVIS_SELECTED;
2411     item.state     = LVIS_SELECTED;
2412     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2413     expect(TRUE, r);
2414 
2415     ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
2416                 "select all notification", FALSE);
2417 
2418     /* select all again (all selected already) */
2419     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2420 
2421     memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
2422 
2423     item.stateMask = LVIS_SELECTED;
2424     item.state     = LVIS_SELECTED;
2425     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2426     expect(TRUE, r);
2427 
2428     ok(g_nmlistview_changing.uNewState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uNewState);
2429     ok(g_nmlistview_changing.uOldState == LVIS_SELECTED, "got 0x%x\n", g_nmlistview_changing.uOldState);
2430     ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
2431 
2432     ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
2433                 "select all notification 2", FALSE);
2434 
2435     /* deselect all items */
2436     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2437 
2438     item.state = 0;
2439     item.stateMask = LVIS_SELECTED;
2440     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2441     ok(r, "got %d\n", r);
2442 
2443     ok_sequence(sequences, PARENT_SEQ_INDEX, change_all_parent_seq,
2444                 "deselect all notification", FALSE);
2445 
2446     /* deselect all items again */
2447     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2448     item.state = 0;
2449     item.stateMask = LVIS_SELECTED;
2450     SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2451     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "deselect all notification 2", FALSE);
2452 
2453     /* any non-zero state value does the same */
2454     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2455 
2456     memset(&g_nmlistview_changing, 0xcc, sizeof(g_nmlistview_changing));
2457 
2458     item.stateMask = LVIS_SELECTED;
2459     item.state     = LVIS_CUT;
2460     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2461     expect(TRUE, r);
2462 
2463     ok(g_nmlistview_changing.uNewState == 0, "got 0x%x\n", g_nmlistview_changing.uNewState);
2464     ok(g_nmlistview_changing.uOldState == 0, "got 0x%x\n", g_nmlistview_changing.uOldState);
2465     ok(g_nmlistview_changing.uChanged == LVIF_STATE, "got 0x%x\n", g_nmlistview_changing.uChanged);
2466 
2467     ok_sequence(sequences, PARENT_SEQ_INDEX, changing_all_parent_seq,
2468                 "set state all notification 3", FALSE);
2469 
2470     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2471     ok(r, "got %d\n", r);
2472     for (i = 0; i < 3; i++) {
2473         item.state = LVIS_SELECTED;
2474         item.stateMask = LVIS_SELECTED;
2475         r = SendMessageA(hwnd, LVM_SETITEMSTATE, i, (LPARAM)&item);
2476         ok(r, "got %d\n", r);
2477     }
2478 
2479     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2480     expect(3, r);
2481     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2482     expect(-1, r);
2483 
2484     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2485     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
2486     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
2487     /* check that style is accepted */
2488     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2489     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
2490 
2491     for (i=0;i<3;i++) {
2492         r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED);
2493         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2494     }
2495     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2496     expect(3, r);
2497     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2498     ok(r == -1, "got %d\n", r);
2499 
2500     /* select one more */
2501     item.state = LVIS_SELECTED;
2502     item.stateMask = LVIS_SELECTED;
2503     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item);
2504     ok(r, "got %d\n", r);
2505 
2506     for (i=0;i<3;i++) {
2507         r = SendMessageA(hwnd, LVM_GETITEMSTATE, i, LVIS_SELECTED);
2508         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
2509     }
2510 
2511     r = SendMessageA(hwnd, LVM_GETITEMSTATE, 3, LVIS_SELECTED);
2512     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
2513 
2514     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2515     expect(1, r);
2516     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2517     expect(-1, r);
2518 
2519     /* try to select all on LVS_SINGLESEL */
2520     memset(&item, 0, sizeof(item));
2521     item.stateMask = LVIS_SELECTED;
2522     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2523     expect(TRUE, r);
2524     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2525     ok(r == -1, "got %d\n", r);
2526 
2527     item.stateMask = LVIS_SELECTED;
2528     item.state     = LVIS_SELECTED;
2529     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2530     expect(FALSE, r);
2531 
2532     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2533     expect(0, r);
2534     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2535     expect(-1, r);
2536 
2537     /* try to deselect all on LVS_SINGLESEL */
2538     item.stateMask = LVIS_SELECTED;
2539     item.state     = LVIS_SELECTED;
2540     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2541     expect(TRUE, r);
2542 
2543     item.stateMask = LVIS_SELECTED;
2544     item.state     = 0;
2545     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2546     expect(TRUE, r);
2547     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2548     expect(0, r);
2549 
2550     /* 1. selection mark is update when new focused item is set */
2551     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2552     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
2553 
2554     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2555     expect(-1, r);
2556 
2557     item.stateMask = LVIS_FOCUSED;
2558     item.state     = LVIS_FOCUSED;
2559     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2560     expect(TRUE, r);
2561 
2562     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2563     expect(0, r);
2564 
2565     /* it's not updated if already set */
2566     item.stateMask = LVIS_FOCUSED;
2567     item.state     = LVIS_FOCUSED;
2568     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item);
2569     expect(TRUE, r);
2570 
2571     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2572     expect(0, r);
2573 
2574     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2575     expect(0, r);
2576 
2577     item.stateMask = LVIS_FOCUSED;
2578     item.state     = LVIS_FOCUSED;
2579     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 1, (LPARAM)&item);
2580     expect(TRUE, r);
2581 
2582     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2583     expect(-1, r);
2584 
2585     /* need to reset focused item first */
2586     item.stateMask = LVIS_FOCUSED;
2587     item.state     = 0;
2588     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2589     expect(TRUE, r);
2590 
2591     item.stateMask = LVIS_FOCUSED;
2592     item.state     = LVIS_FOCUSED;
2593     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item);
2594     expect(TRUE, r);
2595 
2596     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2597     expect(2, r);
2598 
2599     item.stateMask = LVIS_FOCUSED;
2600     item.state     = 0;
2601     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2602     expect(TRUE, r);
2603 
2604     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2605     expect(2, r);
2606 
2607     /* 2. same tests, with LVM_SETITEM */
2608     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2609     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SINGLESEL);
2610 
2611     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2612     expect(2, r);
2613 
2614     item.stateMask = LVIS_FOCUSED;
2615     item.state     = LVIS_FOCUSED;
2616     item.mask      = LVIF_STATE;
2617     item.iItem = item.iSubItem = 0;
2618     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2619     expect(TRUE, r);
2620 
2621     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2622     expect(0, r);
2623 
2624     /* it's not updated if already set */
2625     item.stateMask = LVIS_FOCUSED;
2626     item.state     = LVIS_FOCUSED;
2627     item.mask      = LVIF_STATE;
2628     item.iItem     = 1;
2629     item.iSubItem  = 0;
2630     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2631     expect(TRUE, r);
2632 
2633     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2634     expect(0, r);
2635 
2636     r = SendMessageA(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2637     expect(0, r);
2638 
2639     item.stateMask = LVIS_FOCUSED;
2640     item.state     = LVIS_FOCUSED;
2641     item.mask      = LVIF_STATE;
2642     item.iItem     = 1;
2643     item.iSubItem  = 0;
2644     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2645     expect(TRUE, r);
2646 
2647     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2648     expect(-1, r);
2649 
2650     /* need to reset focused item first */
2651     item.stateMask = LVIS_FOCUSED;
2652     item.state     = 0;
2653     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2654     expect(TRUE, r);
2655 
2656     item.stateMask = LVIS_FOCUSED;
2657     item.state     = LVIS_FOCUSED;
2658     item.mask      = LVIF_STATE;
2659     item.iItem     = 2;
2660     item.iSubItem  = 0;
2661     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
2662     expect(TRUE, r);
2663 
2664     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2665     expect(2, r);
2666 
2667     item.stateMask = LVIS_FOCUSED;
2668     item.state     = 0;
2669     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2670     expect(TRUE, r);
2671 
2672     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2673     expect(2, r);
2674 
2675     DestroyWindow(hwnd);
2676 }
2677 
2678 static void test_subitem_rect(void)
2679 {
2680     HWND hwnd;
2681     DWORD r;
2682     LVCOLUMNA col;
2683     RECT rect, rect2;
2684     INT arr[3];
2685 
2686     /* test LVM_GETSUBITEMRECT for header */
2687     hwnd = create_listview_control(LVS_REPORT);
2688     ok(hwnd != NULL, "failed to create a listview window\n");
2689     /* add some columns */
2690     memset(&col, 0, sizeof(LVCOLUMNA));
2691     col.mask = LVCF_WIDTH;
2692     col.cx = 100;
2693     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
2694     expect(0, r);
2695     col.cx = 150;
2696     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col);
2697     expect(1, r);
2698     col.cx = 200;
2699     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col);
2700     expect(2, r);
2701     /* item = -1 means header, subitem index is 1 based */
2702     SetRect(&rect, LVIR_BOUNDS, 0, 0, 0);
2703     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2704     expect(0, r);
2705 
2706     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2707     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2708     expect(1, r);
2709 
2710     expect(100, rect.left);
2711     expect(250, rect.right);
2712     expect(3, rect.top);
2713 
2714     SetRect(&rect, LVIR_BOUNDS, 2, 0, 0);
2715     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2716     expect(1, r);
2717 
2718     expect(250, rect.left);
2719     expect(450, rect.right);
2720     expect(3, rect.top);
2721 
2722     /* item LVS_REPORT padding isn't applied to subitems */
2723     insert_item(hwnd, 0);
2724 
2725     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2726     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2727     expect(1, r);
2728     expect(100, rect.left);
2729     expect(250, rect.right);
2730 
2731     SetRect(&rect, LVIR_ICON, 1, 0, 0);
2732     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2733     expect(1, r);
2734     /* no icon attached - zero width rectangle, with no left padding */
2735     expect(100, rect.left);
2736     expect(100, rect.right);
2737 
2738     SetRect(&rect, LVIR_LABEL, 1, 0, 0);
2739     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2740     expect(1, r);
2741     /* same as full LVIR_BOUNDS */
2742     expect(100, rect.left);
2743     expect(250, rect.right);
2744 
2745     r = SendMessageA(hwnd, LVM_SCROLL, 10, 0);
2746     ok(r, "got %d\n", r);
2747 
2748     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2749     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2750     expect(1, r);
2751     expect(90, rect.left);
2752     expect(240, rect.right);
2753 
2754     SendMessageA(hwnd, LVM_SCROLL, -10, 0);
2755 
2756     /* test header interaction */
2757     subclass_header(hwnd);
2758     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2759 
2760     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2761     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2762     expect(1, r);
2763 
2764     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2765     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2766     expect(1, r);
2767 
2768     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2769     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -10, (LPARAM)&rect);
2770     expect(1, r);
2771 
2772     SetRect(&rect, LVIR_BOUNDS, 1, 0, 0);
2773     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 20, (LPARAM)&rect);
2774     expect(1, r);
2775 
2776     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getsubitemrect_seq, "LVM_GETSUBITEMRECT negative index", FALSE);
2777 
2778     DestroyWindow(hwnd);
2779 
2780     /* test subitem rects after re-arranging columns */
2781     hwnd = create_listview_control(LVS_REPORT);
2782     ok(hwnd != NULL, "failed to create a listview window\n");
2783     memset(&col, 0, sizeof(LVCOLUMNA));
2784     col.mask = LVCF_WIDTH;
2785 
2786     col.cx = 100;
2787     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
2788     expect(0, r);
2789 
2790     col.cx = 200;
2791     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 1, (LPARAM)&col);
2792     expect(1, r);
2793 
2794     col.cx = 300;
2795     r = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 2, (LPARAM)&col);
2796     expect(2, r);
2797 
2798     insert_item(hwnd, 0);
2799     insert_item(hwnd, 1);
2800 
2801     /* wrong item is refused for main item */
2802     SetRect(&rect, LVIR_BOUNDS, 0, -1, -1);
2803     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect);
2804     expect(FALSE, r);
2805 
2806     /* for subitems rectangle is calculated even if there's no item added */
2807     SetRect(&rect, LVIR_BOUNDS, 1, -1, -1);
2808     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect);
2809     expect(TRUE, r);
2810 
2811     SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1);
2812     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 2, (LPARAM)&rect2);
2813     expect(TRUE, r);
2814     expect(rect.right, rect2.right);
2815     expect(rect.left, rect2.left);
2816     expect(rect.bottom, rect2.top);
2817     ok(rect2.bottom > rect2.top, "expected not zero height\n");
2818 
2819     arr[0] = 1; arr[1] = 0; arr[2] = 2;
2820     r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 3, (LPARAM)arr);
2821     expect(TRUE, r);
2822 
2823     SetRect(&rect, LVIR_BOUNDS, 0, -1, -1);
2824     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2825     expect(TRUE, r);
2826     expect(0, rect.left);
2827     expect(600, rect.right);
2828 
2829     SetRect(&rect, LVIR_BOUNDS, 1, -1, -1);
2830     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2831     expect(TRUE, r);
2832     expect(0, rect.left);
2833     expect(200, rect.right);
2834 
2835     SetRect(&rect2, LVIR_BOUNDS, 1, -1, -1);
2836     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 1, (LPARAM)&rect2);
2837     expect(TRUE, r);
2838     expect(0, rect2.left);
2839     expect(200, rect2.right);
2840     /* items are of the same height */
2841     ok(rect2.top > 0, "expected positive item height\n");
2842     expect(rect.bottom, rect2.top);
2843     expect(rect.bottom * 2 - rect.top, rect2.bottom);
2844 
2845     SetRect(&rect, LVIR_BOUNDS, 2, -1, -1);
2846     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2847     expect(TRUE, r);
2848     expect(300, rect.left);
2849     expect(600, rect.right);
2850 
2851     DestroyWindow(hwnd);
2852 
2853     /* try it for non LVS_REPORT style */
2854     hwnd = CreateWindowA(WC_LISTVIEWA, "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2855                          GetModuleHandleA(NULL), 0);
2856     SetRect(&rect, LVIR_BOUNDS, 1, -10, -10);
2857     r = SendMessageA(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2858     expect(0, r);
2859     /* rect is unchanged */
2860     expect(0, rect.left);
2861     expect(-10, rect.right);
2862     expect(1, rect.top);
2863     expect(-10, rect.bottom);
2864     DestroyWindow(hwnd);
2865 }
2866 
2867 /* comparison callback for test_sorting */
2868 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2869 {
2870     if (first == second) return 0;
2871     return (first > second ? 1 : -1);
2872 }
2873 
2874 static void test_sorting(void)
2875 {
2876     HWND hwnd;
2877     LVITEMA item = {0};
2878     INT r;
2879     LONG_PTR style;
2880     static CHAR names[][5] = {"A", "B", "C", "D", "0"};
2881     CHAR buff[10];
2882 
2883     hwnd = create_listview_control(LVS_REPORT);
2884     ok(hwnd != NULL, "failed to create a listview window\n");
2885 
2886     /* insert some items */
2887     item.mask = LVIF_PARAM | LVIF_STATE;
2888     item.state = LVIS_SELECTED;
2889     item.iItem = 0;
2890     item.iSubItem = 0;
2891     item.lParam = 3;
2892     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2893     expect(0, r);
2894 
2895     item.mask = LVIF_PARAM;
2896     item.iItem = 1;
2897     item.iSubItem = 0;
2898     item.lParam = 2;
2899     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2900     expect(1, r);
2901 
2902     item.mask = LVIF_STATE | LVIF_PARAM;
2903     item.state = LVIS_SELECTED;
2904     item.iItem = 2;
2905     item.iSubItem = 0;
2906     item.lParam = 4;
2907     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2908     expect(2, r);
2909 
2910     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2911     expect(-1, r);
2912 
2913     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2914     expect(2, r);
2915 
2916     r = SendMessageA(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2917     expect(TRUE, r);
2918 
2919     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2920     expect(2, r);
2921     r = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2922     expect(-1, r);
2923     r = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2924     expect(0, r);
2925     r = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2926     expect(LVIS_SELECTED, r);
2927     r = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2928     expect(LVIS_SELECTED, r);
2929 
2930     DestroyWindow(hwnd);
2931 
2932     /* switch to LVS_SORTASCENDING when some items added */
2933     hwnd = create_listview_control(LVS_REPORT);
2934     ok(hwnd != NULL, "failed to create a listview window\n");
2935 
2936     item.mask = LVIF_TEXT;
2937     item.iItem = 0;
2938     item.iSubItem = 0;
2939     item.pszText = names[1];
2940     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2941     expect(0, r);
2942 
2943     item.mask = LVIF_TEXT;
2944     item.iItem = 1;
2945     item.iSubItem = 0;
2946     item.pszText = names[2];
2947     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2948     expect(1, r);
2949 
2950     item.mask = LVIF_TEXT;
2951     item.iItem = 2;
2952     item.iSubItem = 0;
2953     item.pszText = names[0];
2954     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2955     expect(2, r);
2956 
2957     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2958     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2959     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2960     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2961 
2962     /* no sorting performed when switched to LVS_SORTASCENDING */
2963     item.mask = LVIF_TEXT;
2964     item.iItem = 0;
2965     item.pszText = buff;
2966     item.cchTextMax = sizeof(buff);
2967     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
2968     expect(TRUE, r);
2969     ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2970 
2971     item.iItem = 1;
2972     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
2973     expect(TRUE, r);
2974     ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2975 
2976     item.iItem = 2;
2977     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
2978     expect(TRUE, r);
2979     ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2980 
2981     /* adding new item doesn't resort list */
2982     item.mask = LVIF_TEXT;
2983     item.iItem = 3;
2984     item.iSubItem = 0;
2985     item.pszText = names[3];
2986     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
2987     expect(3, r);
2988 
2989     item.mask = LVIF_TEXT;
2990     item.iItem = 0;
2991     item.pszText = buff;
2992     item.cchTextMax = sizeof(buff);
2993     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
2994     expect(TRUE, r);
2995     ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2996 
2997     item.iItem = 1;
2998     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
2999     expect(TRUE, r);
3000     ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
3001 
3002     item.iItem = 2;
3003     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3004     expect(TRUE, r);
3005     ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
3006 
3007     item.iItem = 3;
3008     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3009     expect(TRUE, r);
3010     ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
3011 
3012     /* corner case - item should be placed at first position */
3013     item.mask = LVIF_TEXT;
3014     item.iItem = 4;
3015     item.iSubItem = 0;
3016     item.pszText = names[4];
3017     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
3018     expect(0, r);
3019 
3020     item.iItem = 0;
3021     item.pszText = buff;
3022     item.cchTextMax = sizeof(buff);
3023     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3024     expect(TRUE, r);
3025     ok(lstrcmpA(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
3026 
3027     item.iItem = 1;
3028     item.pszText = buff;
3029     item.cchTextMax = sizeof(buff);
3030     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3031     expect(TRUE, r);
3032     ok(lstrcmpA(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
3033 
3034     item.iItem = 2;
3035     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3036     expect(TRUE, r);
3037     ok(lstrcmpA(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
3038 
3039     item.iItem = 3;
3040     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3041     expect(TRUE, r);
3042     ok(lstrcmpA(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
3043 
3044     item.iItem = 4;
3045     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
3046     expect(TRUE, r);
3047     ok(lstrcmpA(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
3048 
3049     DestroyWindow(hwnd);
3050 }
3051 
3052 static void test_ownerdata(void)
3053 {
3054     static char test_str[] = "test";
3055 
3056     HWND hwnd;
3057     LONG_PTR style, ret;
3058     DWORD res;
3059     LVITEMA item;
3060 
3061     /* it isn't possible to set LVS_OWNERDATA after creation */
3062     if (g_is_below_5)
3063     {
3064         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
3065     }
3066     else
3067     {
3068         hwnd = create_listview_control(LVS_REPORT);
3069         ok(hwnd != NULL, "failed to create a listview window\n");
3070         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3071         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
3072 
3073         flush_sequences(sequences, NUM_MSG_SEQUENCES);
3074 
3075         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
3076         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
3077         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
3078                 "try to switch to LVS_OWNERDATA seq", FALSE);
3079 
3080         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3081         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
3082         DestroyWindow(hwnd);
3083     }
3084 
3085     /* try to set LVS_OWNERDATA after creation just having it */
3086     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3087     ok(hwnd != NULL, "failed to create a listview window\n");
3088     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3089     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
3090 
3091     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3092 
3093     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
3094     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
3095     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
3096                 "try to switch to LVS_OWNERDATA seq", FALSE);
3097     DestroyWindow(hwnd);
3098 
3099     /* try to remove LVS_OWNERDATA after creation just having it */
3100     if (g_is_below_5)
3101     {
3102         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
3103     }
3104     else
3105     {
3106         hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3107         ok(hwnd != NULL, "failed to create a listview window\n");
3108         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3109         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
3110 
3111         flush_sequences(sequences, NUM_MSG_SEQUENCES);
3112 
3113         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
3114         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
3115         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
3116                 "try to switch to LVS_OWNERDATA seq", FALSE);
3117         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3118         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
3119         DestroyWindow(hwnd);
3120     }
3121 
3122     /* try select an item */
3123     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3124     ok(hwnd != NULL, "failed to create a listview window\n");
3125     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3126     expect(1, res);
3127     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
3128     expect(0, res);
3129     memset(&item, 0, sizeof(item));
3130     item.stateMask = LVIS_SELECTED;
3131     item.state     = LVIS_SELECTED;
3132     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3133     expect(TRUE, res);
3134     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
3135     expect(1, res);
3136     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
3137     expect(1, res);
3138     DestroyWindow(hwnd);
3139 
3140     /* LVM_SETITEM and LVM_SETITEMTEXT is unsupported on LVS_OWNERDATA */
3141     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3142     ok(hwnd != NULL, "failed to create a listview window\n");
3143     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3144     expect(1, res);
3145     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
3146     expect(1, res);
3147     memset(&item, 0, sizeof(item));
3148     item.mask = LVIF_STATE;
3149     item.iItem = 0;
3150     item.stateMask = LVIS_SELECTED;
3151     item.state     = LVIS_SELECTED;
3152     res = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
3153     expect(FALSE, res);
3154     memset(&item, 0, sizeof(item));
3155     item.pszText = test_str;
3156     res = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3157     expect(FALSE, res);
3158     DestroyWindow(hwnd);
3159 
3160     /* check notifications after focused/selected changed */
3161     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3162     ok(hwnd != NULL, "failed to create a listview window\n");
3163     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
3164     expect(1, res);
3165 
3166     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3167 
3168     memset(&item, 0, sizeof(item));
3169     item.stateMask = LVIS_SELECTED;
3170     item.state     = LVIS_SELECTED;
3171     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3172     expect(TRUE, res);
3173 
3174     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq,
3175                 "ownerdata select notification", TRUE);
3176 
3177     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3178 
3179     memset(&item, 0, sizeof(item));
3180     item.stateMask = LVIS_FOCUSED;
3181     item.state     = LVIS_FOCUSED;
3182     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3183     expect(TRUE, res);
3184 
3185     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_select_focus_parent_seq,
3186                 "ownerdata focus notification", TRUE);
3187 
3188     /* select all, check notifications */
3189     item.stateMask = LVIS_SELECTED;
3190     item.state     = 0;
3191     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3192     expect(TRUE, res);
3193 
3194     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3195 
3196     item.stateMask = LVIS_SELECTED;
3197     item.state     = LVIS_SELECTED;
3198 
3199     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3200     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3201     expect(TRUE, res);
3202     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3203     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3204     ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
3205     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3206     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3207     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3208     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3209 
3210     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3211                 "ownerdata select all notification", FALSE);
3212 
3213     /* select all again, note that all items are selected already */
3214     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3215     item.stateMask = LVIS_SELECTED;
3216     item.state     = LVIS_SELECTED;
3217 
3218     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3219     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3220     expect(TRUE, res);
3221     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3222     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3223     ok(g_nmlistview.uNewState == LVIS_SELECTED, "got new state 0x%08x\n", g_nmlistview.uNewState);
3224     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3225     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3226     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3227     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3228 
3229     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3230                 "ownerdata select all notification", FALSE);
3231 
3232     /* deselect all */
3233     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3234     item.stateMask = LVIS_SELECTED;
3235     item.state     = 0;
3236 
3237     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3238     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3239     expect(TRUE, res);
3240     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3241     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3242     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3243     ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3244     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3245     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3246     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3247 
3248     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
3249                 "ownerdata deselect all notification", TRUE);
3250 
3251     /* nothing selected, deselect all again */
3252     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3253     item.stateMask = LVIS_SELECTED;
3254     item.state     = 0;
3255 
3256     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3257     expect(TRUE, res);
3258 
3259     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "ownerdata deselect all notification", FALSE);
3260 
3261     /* select one, then deselect all */
3262     item.stateMask = LVIS_SELECTED;
3263     item.state     = LVIS_SELECTED;
3264     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3265     expect(TRUE, res);
3266     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3267     item.stateMask = LVIS_SELECTED;
3268     item.state     = 0;
3269 
3270     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3271     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3272     expect(TRUE, res);
3273     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3274     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3275     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3276     ok(g_nmlistview.uOldState == LVIS_SELECTED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3277     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3278     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3279     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3280 
3281     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
3282                 "ownerdata select all notification", TRUE);
3283 
3284     /* remove focused, try to focus all */
3285     item.stateMask = LVIS_FOCUSED;
3286     item.state     = LVIS_FOCUSED;
3287     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3288     expect(TRUE, res);
3289     item.stateMask = LVIS_FOCUSED;
3290     item.state     = 0;
3291     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3292     expect(TRUE, res);
3293     item.stateMask = LVIS_FOCUSED;
3294     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
3295     expect(0, res);
3296 
3297     /* setting all to focused returns failure value */
3298     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3299     item.stateMask = LVIS_FOCUSED;
3300     item.state     = LVIS_FOCUSED;
3301 
3302     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3303     expect(FALSE, res);
3304 
3305     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3306                 "ownerdata focus all notification", FALSE);
3307 
3308     /* focus single item, remove all */
3309     item.stateMask = LVIS_FOCUSED;
3310     item.state     = LVIS_FOCUSED;
3311     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3312     expect(TRUE, res);
3313     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3314     item.stateMask = LVIS_FOCUSED;
3315     item.state     = 0;
3316 
3317     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3318     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3319     expect(TRUE, res);
3320     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3321     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3322     ok(g_nmlistview.uNewState == 0, "got new state 0x%08x\n", g_nmlistview.uNewState);
3323     ok(g_nmlistview.uOldState == LVIS_FOCUSED, "got old state 0x%08x\n", g_nmlistview.uOldState);
3324     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3325     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3326     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3327 
3328     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
3329                 "ownerdata remove focus all notification", TRUE);
3330 
3331     /* set all cut */
3332     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3333     item.stateMask = LVIS_CUT;
3334     item.state     = LVIS_CUT;
3335 
3336     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3337     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3338     expect(TRUE, res);
3339     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3340     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3341     ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState);
3342     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3343     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3344     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3345     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3346 
3347     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3348                 "ownerdata cut all notification", FALSE);
3349 
3350     /* all marked cut, try again */
3351     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3352     item.stateMask = LVIS_CUT;
3353     item.state     = LVIS_CUT;
3354 
3355     memset(&g_nmlistview, 0xcc, sizeof(g_nmlistview));
3356     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
3357     expect(TRUE, res);
3358     ok(g_nmlistview.iItem == -1, "got item %d\n", g_nmlistview.iItem);
3359     ok(g_nmlistview.iSubItem == 0, "got subitem %d\n", g_nmlistview.iSubItem);
3360     ok(g_nmlistview.uNewState == LVIS_CUT, "got new state 0x%08x\n", g_nmlistview.uNewState);
3361     ok(g_nmlistview.uOldState == 0, "got old state 0x%08x\n", g_nmlistview.uOldState);
3362     ok(g_nmlistview.uChanged == LVIF_STATE, "got changed 0x%08x\n", g_nmlistview.uChanged);
3363     ok(g_nmlistview.ptAction.x == 0 && g_nmlistview.ptAction.y == 0, "got wrong ptAction value\n");
3364     ok(g_nmlistview.lParam == 0, "got wrong lparam\n");
3365 
3366     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
3367                 "ownerdata cut all notification #2", FALSE);
3368 
3369     DestroyWindow(hwnd);
3370 
3371     /* check notifications on LVM_GETITEM */
3372     /* zero callback mask */
3373     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3374     ok(hwnd != NULL, "failed to create a listview window\n");
3375     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3376     expect(1, res);
3377 
3378     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3379 
3380     memset(&item, 0, sizeof(item));
3381     item.stateMask = LVIS_SELECTED;
3382     item.mask      = LVIF_STATE;
3383     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3384     expect(TRUE, res);
3385 
3386     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3387                 "ownerdata getitem selected state 1", FALSE);
3388 
3389     /* non zero callback mask but not we asking for */
3390     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
3391     expect(TRUE, res);
3392 
3393     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3394 
3395     memset(&item, 0, sizeof(item));
3396     item.stateMask = LVIS_SELECTED;
3397     item.mask      = LVIF_STATE;
3398     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3399     expect(TRUE, res);
3400 
3401     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3402                 "ownerdata getitem selected state 2", FALSE);
3403 
3404     /* LVIS_OVERLAYMASK callback mask, asking for index */
3405     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3406 
3407     memset(&item, 0, sizeof(item));
3408     item.stateMask = LVIS_OVERLAYMASK;
3409     item.mask      = LVIF_STATE;
3410     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3411     expect(TRUE, res);
3412 
3413     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
3414                 "ownerdata getitem selected state 2", FALSE);
3415 
3416     DestroyWindow(hwnd);
3417 
3418     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
3419     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING | LVS_REPORT);
3420     ok(hwnd != NULL, "failed to create a listview window\n");
3421     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3422     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3423     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
3424     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
3425     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3426     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
3427     DestroyWindow(hwnd);
3428     /* apparently it's allowed to switch these style on after creation */
3429     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3430     ok(hwnd != NULL, "failed to create a listview window\n");
3431     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3432     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3433     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
3434     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3435     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
3436     DestroyWindow(hwnd);
3437 
3438     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3439     ok(hwnd != NULL, "failed to create a listview window\n");
3440     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3441     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
3442     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
3443     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3444     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
3445     DestroyWindow(hwnd);
3446 
3447     /* The focused item is updated after the invalidation */
3448     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3449     ok(hwnd != NULL, "failed to create a listview window\n");
3450     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 3, 0);
3451     expect(TRUE, res);
3452 
3453     memset(&item, 0, sizeof(item));
3454     item.stateMask = LVIS_FOCUSED;
3455     item.state     = LVIS_FOCUSED;
3456     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
3457     expect(TRUE, res);
3458 
3459     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3460     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0);
3461     expect(TRUE, res);
3462     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3463                 "ownerdata setitemcount", FALSE);
3464 
3465     res = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
3466     expect(-1, res);
3467     DestroyWindow(hwnd);
3468 }
3469 
3470 static void test_norecompute(void)
3471 {
3472     static CHAR testA[] = "test";
3473     CHAR buff[10];
3474     LVITEMA item;
3475     HWND hwnd;
3476     DWORD res;
3477 
3478     /* self containing control */
3479     hwnd = create_listview_control(LVS_REPORT);
3480     ok(hwnd != NULL, "failed to create a listview window\n");
3481     memset(&item, 0, sizeof(item));
3482     item.mask = LVIF_TEXT | LVIF_STATE;
3483     item.iItem = 0;
3484     item.stateMask = LVIS_SELECTED;
3485     item.state     = LVIS_SELECTED;
3486     item.pszText   = testA;
3487     res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3488     expect(0, res);
3489     /* retrieve with LVIF_NORECOMPUTE */
3490     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3491     item.iItem = 0;
3492     item.pszText    = buff;
3493     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3494     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3495     expect(TRUE, res);
3496     ok(lstrcmpA(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
3497 
3498     item.mask = LVIF_TEXT;
3499     item.iItem = 1;
3500     item.pszText = LPSTR_TEXTCALLBACKA;
3501     res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3502     expect(1, res);
3503 
3504     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3505     item.iItem = 1;
3506     item.pszText    = buff;
3507     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3508 
3509     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3510     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3511     expect(TRUE, res);
3512     ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n",
3513        LPSTR_TEXTCALLBACKA, (VOID*)item.pszText);
3514     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
3515 
3516     DestroyWindow(hwnd);
3517 
3518     /* LVS_OWNERDATA */
3519     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3520     ok(hwnd != NULL, "failed to create a listview window\n");
3521 
3522     item.mask = LVIF_STATE;
3523     item.stateMask = LVIS_SELECTED;
3524     item.state     = LVIS_SELECTED;
3525     item.iItem = 0;
3526     res = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3527     expect(0, res);
3528 
3529     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
3530     item.iItem = 0;
3531     item.pszText    = buff;
3532     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
3533     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3534     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
3535     expect(TRUE, res);
3536     ok(item.pszText == LPSTR_TEXTCALLBACKA, "Expected (%p), got (%p)\n",
3537        LPSTR_TEXTCALLBACKA, (VOID*)item.pszText);
3538     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
3539 
3540     DestroyWindow(hwnd);
3541 }
3542 
3543 static void test_nosortheader(void)
3544 {
3545     HWND hwnd, header;
3546     LONG_PTR style;
3547 
3548     hwnd = create_listview_control(LVS_REPORT);
3549     ok(hwnd != NULL, "failed to create a listview window\n");
3550 
3551     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
3552     ok(IsWindow(header), "header expected\n");
3553 
3554     style = GetWindowLongPtrA(header, GWL_STYLE);
3555     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
3556 
3557     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3558     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
3559     /* HDS_BUTTONS retained */
3560     style = GetWindowLongPtrA(header, GWL_STYLE);
3561     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
3562 
3563     DestroyWindow(hwnd);
3564 
3565     /* create with LVS_NOSORTHEADER */
3566     hwnd = create_listview_control(LVS_NOSORTHEADER | LVS_REPORT);
3567     ok(hwnd != NULL, "failed to create a listview window\n");
3568 
3569     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
3570     ok(IsWindow(header), "header expected\n");
3571 
3572     style = GetWindowLongPtrA(header, GWL_STYLE);
3573     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
3574 
3575     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3576     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
3577     /* not changed here */
3578     style = GetWindowLongPtrA(header, GWL_STYLE);
3579     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
3580 
3581     DestroyWindow(hwnd);
3582 }
3583 
3584 static void test_setredraw(void)
3585 {
3586     HWND hwnd;
3587     DWORD_PTR style;
3588     DWORD ret;
3589     HDC hdc;
3590     RECT rect;
3591 
3592     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
3593     ok(hwnd != NULL, "failed to create a listview window\n");
3594 
3595     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
3596        ListView seems to handle it internally without DefWinProc */
3597 
3598     /* default value first */
3599     ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
3600     expect(0, ret);
3601     /* disable */
3602     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3603     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
3604     ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3605     expect(0, ret);
3606     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
3607     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
3608     ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
3609     expect(0, ret);
3610 
3611     /* check update rect after redrawing */
3612     ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3613     expect(0, ret);
3614     InvalidateRect(hwnd, NULL, FALSE);
3615     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
3616     rect.right = rect.bottom = 1;
3617     GetUpdateRect(hwnd, &rect, FALSE);
3618     expect(0, rect.right);
3619     expect(0, rect.bottom);
3620 
3621     /* WM_ERASEBKGND */
3622     hdc = GetWindowDC(hwndparent);
3623     ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
3624     expect(TRUE, ret);
3625     ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3626     expect(0, ret);
3627     ret = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
3628     expect(TRUE, ret);
3629     ret = SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0);
3630     expect(0, ret);
3631     ReleaseDC(hwndparent, hdc);
3632 
3633     /* check notification messages to show that repainting is disabled */
3634     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
3635     expect(TRUE, ret);
3636     ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3637     expect(0, ret);
3638     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3639 
3640     InvalidateRect(hwnd, NULL, TRUE);
3641     UpdateWindow(hwnd);
3642     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3643                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
3644 
3645     ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
3646     expect(TRUE, ret);
3647     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3648     InvalidateRect(hwnd, NULL, TRUE);
3649     UpdateWindow(hwnd);
3650     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
3651                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
3652 
3653     /* message isn't forwarded to header */
3654     subclass_header(hwnd);
3655     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3656     ret = SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0);
3657     expect(0, ret);
3658     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
3659                 "WM_SETREDRAW: not forwarded to header", FALSE);
3660 
3661     DestroyWindow(hwnd);
3662 }
3663 
3664 static void test_hittest(void)
3665 {
3666     HWND hwnd;
3667     DWORD r;
3668     RECT bounds;
3669     LVITEMA item;
3670     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
3671     POINT pos;
3672     INT x, y, i;
3673     WORD vert;
3674     HIMAGELIST himl, himl2;
3675     HBITMAP hbmp;
3676 
3677     hwnd = create_listview_control(LVS_REPORT);
3678     ok(hwnd != NULL, "failed to create a listview window\n");
3679 
3680     /* LVS_REPORT with a single subitem (2 columns) */
3681     insert_column(hwnd, 0);
3682     insert_column(hwnd, 1);
3683     insert_item(hwnd, 0);
3684 
3685     item.iSubItem = 0;
3686     /* the only purpose of that line is to be as long as a half item rect */
3687     item.pszText  = text;
3688     r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
3689     expect(TRUE, r);
3690 
3691     r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3692     expect(TRUE, r);
3693     r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
3694     expect(TRUE, r);
3695 
3696     SetRect(&bounds, LVIR_BOUNDS, 0, 0, 0);
3697     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
3698     expect(1, r);
3699     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
3700     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
3701     r = SendMessageA(hwnd, LVM_GETITEMSPACING, TRUE, 0);
3702     vert = HIWORD(r);
3703     ok(bounds.bottom - bounds.top == vert,
3704         "Vertical spacing inconsistent (%d != %d)\n", bounds.bottom - bounds.top, vert);
3705     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
3706     expect(TRUE, r);
3707 
3708     /* LVS_EX_FULLROWSELECT not set, no icons attached */
3709 
3710     /* outside columns by x position - valid is [0, 199] */
3711     x = -1;
3712     y = pos.y + (bounds.bottom - bounds.top) / 2;
3713     test_lvm_hittest(hwnd, x, y, -1, LVHT_TOLEFT, 0, FALSE, FALSE);
3714     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3715 
3716     x = pos.x + 50; /* column half width */
3717     y = pos.y + (bounds.bottom - bounds.top) / 2;
3718     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE);
3719     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3720     x = pos.x + 150; /* outside column */
3721     y = pos.y + (bounds.bottom - bounds.top) / 2;
3722     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3723     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3724     y = (bounds.bottom - bounds.top) / 2;
3725     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3726     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3727     /* outside possible client rectangle (to right) */
3728     x = pos.x + 500;
3729     y = pos.y + (bounds.bottom - bounds.top) / 2;
3730     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3731     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3732     y = (bounds.bottom - bounds.top) / 2;
3733     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3734     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3735     /* subitem returned with -1 item too */
3736     x = pos.x + 150;
3737     y = bounds.top - vert;
3738     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3739     test_lvm_subitemhittest(hwnd, x, y - vert + 1, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3740     /* return values appear to underflow with negative indices */
3741     i = -2;
3742     y = y - vert;
3743     while (i > -10) {
3744         test_lvm_subitemhittest(hwnd, x, y, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE);
3745         test_lvm_subitemhittest(hwnd, x, y - vert + 1, i, 1, LVHT_ONITEMLABEL, TRUE, FALSE, TRUE);
3746         y = y - vert;
3747         i--;
3748     }
3749     /* parent client area is 100x100 by default */
3750     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
3751     x = pos.x + 150; /* outside column */
3752     y = pos.y + (bounds.bottom - bounds.top) / 2;
3753     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE);
3754     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3755     y = (bounds.bottom - bounds.top) / 2;
3756     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE);
3757     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3758     /* the same with LVS_EX_FULLROWSELECT */
3759     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
3760     x = pos.x + 150; /* outside column */
3761     y = pos.y + (bounds.bottom - bounds.top) / 2;
3762     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE);
3763     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3764     y = (bounds.bottom - bounds.top) / 2;
3765     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3766     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
3767     x = pos.x + 150; /* outside column */
3768     y = pos.y + (bounds.bottom - bounds.top) / 2;
3769     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3770     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3771     y = (bounds.bottom - bounds.top) / 2;
3772     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3773     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE);
3774     /* outside possible client rectangle (to right) */
3775     x = pos.x + 500;
3776     y = pos.y + (bounds.bottom - bounds.top) / 2;
3777     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE);
3778     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3779     y = (bounds.bottom - bounds.top) / 2;
3780     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE);
3781     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE);
3782     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
3783     himl = pImageList_Create(16, 16, 0, 4, 4);
3784     ok(himl != NULL, "failed to create imagelist\n");
3785     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
3786     ok(hbmp != NULL, "failed to create bitmap\n");
3787     r = pImageList_Add(himl, hbmp, 0);
3788     ok(r == 0, "should be zero\n");
3789     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
3790     ok(hbmp != NULL, "failed to create bitmap\n");
3791     r = pImageList_Add(himl, hbmp, 0);
3792     ok(r == 1, "should be one\n");
3793 
3794     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
3795     expect(0, r);
3796 
3797     item.mask = LVIF_IMAGE;
3798     item.iImage = 0;
3799     item.iItem = 0;
3800     item.iSubItem = 0;
3801     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
3802     expect(TRUE, r);
3803     /* on state icon */
3804     x = pos.x + 8;
3805     y = pos.y + (bounds.bottom - bounds.top) / 2;
3806     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
3807     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3808     y = (bounds.bottom - bounds.top) / 2;
3809     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3810 
3811     /* state icons indices are 1 based, check with valid index */
3812     item.mask = LVIF_STATE;
3813     item.state = INDEXTOSTATEIMAGEMASK(1);
3814     item.stateMask = LVIS_STATEIMAGEMASK;
3815     item.iItem = 0;
3816     item.iSubItem = 0;
3817     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
3818     expect(TRUE, r);
3819     /* on state icon */
3820     x = pos.x + 8;
3821     y = pos.y + (bounds.bottom - bounds.top) / 2;
3822     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE);
3823     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3824     y = (bounds.bottom - bounds.top) / 2;
3825     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE);
3826 
3827     himl2 = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
3828     ok(himl2 == himl, "should return handle\n");
3829 
3830     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
3831     expect(0, r);
3832     /* on item icon */
3833     x = pos.x + 8;
3834     y = pos.y + (bounds.bottom - bounds.top) / 2;
3835     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE);
3836     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
3837     y = (bounds.bottom - bounds.top) / 2;
3838     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE);
3839 
3840     DestroyWindow(hwnd);
3841 }
3842 
3843 static void test_getviewrect(void)
3844 {
3845     HWND hwnd;
3846     DWORD r;
3847     RECT rect;
3848     LVITEMA item;
3849 
3850     hwnd = create_listview_control(LVS_REPORT);
3851     ok(hwnd != NULL, "failed to create a listview window\n");
3852 
3853     /* empty */
3854     r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3855     expect(TRUE, r);
3856 
3857     insert_column(hwnd, 0);
3858     insert_column(hwnd, 1);
3859 
3860     memset(&item, 0, sizeof(item));
3861     item.iItem = 0;
3862     item.iSubItem = 0;
3863     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3864     ok(!r, "got %d\n", r);
3865 
3866     r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3867     expect(TRUE, r);
3868     r = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3869     expect(TRUE, r);
3870 
3871     SetRect(&rect, -1, -1, -1, -1);
3872     r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3873     expect(TRUE, r);
3874     /* left is set to (2e31-1) - XP SP2 */
3875     expect(0, rect.right);
3876     expect(0, rect.top);
3877     expect(0, rect.bottom);
3878 
3879     /* switch to LVS_ICON */
3880     SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_REPORT);
3881 
3882     SetRect(&rect, -1, -1, -1, -1);
3883     r = SendMessageA(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3884     expect(TRUE, r);
3885     expect(0, rect.left);
3886     expect(0, rect.top);
3887     /* precise value differs for 2k, XP and Vista */
3888     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3889     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3890 
3891     DestroyWindow(hwnd);
3892 }
3893 
3894 static void test_getitemposition(void)
3895 {
3896     HWND hwnd, header;
3897     DWORD r;
3898     POINT pt;
3899     RECT rect;
3900 
3901     hwnd = create_listview_control(LVS_REPORT);
3902     ok(hwnd != NULL, "failed to create a listview window\n");
3903     header = subclass_header(hwnd);
3904 
3905     /* LVS_REPORT, single item, no columns added */
3906     insert_item(hwnd, 0);
3907 
3908     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3909 
3910     pt.x = pt.y = -1;
3911     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3912     expect(TRUE, r);
3913     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3914 
3915     /* LVS_REPORT, single item, single column */
3916     insert_column(hwnd, 0);
3917 
3918     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3919 
3920     pt.x = pt.y = -1;
3921     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3922     expect(TRUE, r);
3923     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3924 
3925     SetRectEmpty(&rect);
3926     r = SendMessageA(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3927     ok(r, "got %d\n", r);
3928     /* some padding? */
3929     expect(2, pt.x);
3930     /* offset by header height */
3931     expect(rect.bottom - rect.top, pt.y);
3932 
3933     DestroyWindow(hwnd);
3934 }
3935 
3936 static void test_columnscreation(void)
3937 {
3938     HWND hwnd, header;
3939     DWORD r;
3940 
3941     hwnd = create_listview_control(LVS_REPORT);
3942     ok(hwnd != NULL, "failed to create a listview window\n");
3943 
3944     insert_item(hwnd, 0);
3945 
3946     /* headers columns aren't created automatically */
3947     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
3948     ok(IsWindow(header), "Expected header handle\n");
3949     r = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0);
3950     expect(0, r);
3951 
3952     DestroyWindow(hwnd);
3953 }
3954 
3955 static void test_getitemrect(void)
3956 {
3957     HWND hwnd;
3958     HIMAGELIST himl, himl_ret;
3959     HBITMAP hbm;
3960     RECT rect;
3961     DWORD r;
3962     LVITEMA item;
3963     LVCOLUMNA col;
3964     INT order[2];
3965     POINT pt;
3966 
3967     /* rectangle isn't empty for empty text items */
3968     hwnd = create_listview_control(LVS_LIST);
3969     memset(&item, 0, sizeof(item));
3970     item.mask = 0;
3971     item.iItem = 0;
3972     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3973     expect(0, r);
3974     rect.left = LVIR_LABEL;
3975     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3976     expect(TRUE, r);
3977     expect(0, rect.left);
3978     expect(0, rect.top);
3979     /* estimate it as width / height ratio */
3980 todo_wine
3981     ok((rect.right / rect.bottom) >= 5, "got right %d, bottom %d\n", rect.right, rect.bottom);
3982     DestroyWindow(hwnd);
3983 
3984     hwnd = create_listview_control(LVS_REPORT);
3985     ok(hwnd != NULL, "failed to create a listview window\n");
3986 
3987     /* empty item */
3988     memset(&item, 0, sizeof(item));
3989     item.iItem = 0;
3990     item.iSubItem = 0;
3991     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3992     expect(0, r);
3993 
3994     SetRect(&rect, LVIR_BOUNDS, -1, -1, -1);
3995     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3996     expect(TRUE, r);
3997 
3998     /* zero width rectangle with no padding */
3999     expect(0, rect.left);
4000     expect(0, rect.right);
4001 
4002     insert_column(hwnd, 0);
4003     insert_column(hwnd, 1);
4004 
4005     col.mask = LVCF_WIDTH;
4006     col.cx   = 50;
4007     r = SendMessageA(hwnd, LVM_SETCOLUMNA, 0, (LPARAM)&col);
4008     expect(TRUE, r);
4009 
4010     col.mask = LVCF_WIDTH;
4011     col.cx   = 100;
4012     r = SendMessageA(hwnd, LVM_SETCOLUMNA, 1, (LPARAM)&col);
4013     expect(TRUE, r);
4014 
4015     SetRect(&rect, LVIR_BOUNDS, -1, -1, -1);
4016     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4017     expect(TRUE, r);
4018 
4019     /* still no left padding */
4020     expect(0, rect.left);
4021     expect(150, rect.right);
4022 
4023     SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1);
4024     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4025     expect(TRUE, r);
4026     /* padding */
4027     expect(2, rect.left);
4028 
4029     SetRect(&rect, LVIR_LABEL, -1, -1, -1);
4030     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4031     expect(TRUE, r);
4032     /* padding, column width */
4033     expect(2, rect.left);
4034     expect(50, rect.right);
4035 
4036     /* no icons attached */
4037     SetRect(&rect, LVIR_ICON, -1, -1, -1);
4038     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4039     expect(TRUE, r);
4040     /* padding */
4041     expect(2, rect.left);
4042     expect(2, rect.right);
4043 
4044     /* change order */
4045     order[0] = 1; order[1] = 0;
4046     r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
4047     expect(TRUE, r);
4048     pt.x = -1;
4049     r = SendMessageA(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
4050     expect(TRUE, r);
4051     /* 1 indexed column width + padding */
4052     expect(102, pt.x);
4053     /* rect is at zero too */
4054     SetRect(&rect, LVIR_BOUNDS, -1, -1, -1);
4055     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4056     expect(TRUE, r);
4057     expect(0, rect.left);
4058     /* just width sum */
4059     expect(150, rect.right);
4060 
4061     SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1);
4062     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4063     expect(TRUE, r);
4064     /* column width + padding */
4065     expect(102, rect.left);
4066 
4067     /* back to initial order */
4068     order[0] = 0; order[1] = 1;
4069     r = SendMessageA(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
4070     expect(TRUE, r);
4071 
4072     /* state icons */
4073     himl = pImageList_Create(16, 16, 0, 2, 2);
4074     ok(himl != NULL, "failed to create imagelist\n");
4075     hbm = CreateBitmap(16, 16, 1, 1, NULL);
4076     ok(hbm != NULL, "failed to create bitmap\n");
4077     r = pImageList_Add(himl, hbm, 0);
4078     expect(0, r);
4079     hbm = CreateBitmap(16, 16, 1, 1, NULL);
4080     ok(hbm != NULL, "failed to create bitmap\n");
4081     r = pImageList_Add(himl, hbm, 0);
4082     expect(1, r);
4083 
4084     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
4085     expect(0, r);
4086 
4087     item.mask = LVIF_STATE;
4088     item.state = INDEXTOSTATEIMAGEMASK(1);
4089     item.stateMask = LVIS_STATEIMAGEMASK;
4090     item.iItem = 0;
4091     item.iSubItem = 0;
4092     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
4093     expect(TRUE, r);
4094 
4095     /* icon bounds */
4096     SetRect(&rect, LVIR_ICON, -1, -1, -1);
4097     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4098     expect(TRUE, r);
4099     /* padding + stateicon width */
4100     expect(18, rect.left);
4101     expect(18, rect.right);
4102     /* label bounds */
4103     SetRect(&rect, LVIR_LABEL, -1, -1, -1);
4104     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4105     expect(TRUE, r);
4106     /* padding + stateicon width -> column width */
4107     expect(18, rect.left);
4108     expect(50, rect.right);
4109 
4110     himl_ret = (HIMAGELIST)SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, 0);
4111     ok(himl_ret == himl, "got %p, expected %p\n", himl_ret, himl);
4112 
4113     r = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
4114     expect(0, r);
4115 
4116     item.mask = LVIF_STATE | LVIF_IMAGE;
4117     item.iImage = 1;
4118     item.state = 0;
4119     item.stateMask = ~0;
4120     item.iItem = 0;
4121     item.iSubItem = 0;
4122     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
4123     expect(TRUE, r);
4124 
4125     /* icon bounds */
4126     SetRect(&rect, LVIR_ICON, -1, -1, -1);
4127     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4128     expect(TRUE, r);
4129     /* padding, icon width */
4130     expect(2, rect.left);
4131     expect(18, rect.right);
4132     /* label bounds */
4133     SetRect(&rect, LVIR_LABEL, -1, -1, -1);
4134     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4135     expect(TRUE, r);
4136     /* padding + icon width -> column width */
4137     expect(18, rect.left);
4138     expect(50, rect.right);
4139 
4140     /* select bounds */
4141     SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1);
4142     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4143     expect(TRUE, r);
4144     /* padding, column width */
4145     expect(2, rect.left);
4146     expect(50, rect.right);
4147 
4148     /* try with indentation */
4149     item.mask = LVIF_INDENT;
4150     item.iIndent = 1;
4151     item.iItem = 0;
4152     item.iSubItem = 0;
4153     r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
4154     expect(TRUE, r);
4155 
4156     /* bounds */
4157     SetRect(&rect, LVIR_BOUNDS, -1, -1, -1);
4158     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4159     expect(TRUE, r);
4160     /* padding + 1 icon width, column width */
4161     expect(0, rect.left);
4162     expect(150, rect.right);
4163 
4164     /* select bounds */
4165     SetRect(&rect, LVIR_SELECTBOUNDS, -1, -1, -1);
4166     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4167     expect(TRUE, r);
4168     /* padding + 1 icon width, column width */
4169     expect(2 + 16, rect.left);
4170     expect(50, rect.right);
4171 
4172     /* label bounds */
4173     SetRect(&rect, LVIR_LABEL, -1, -1, -1);
4174     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4175     expect(TRUE, r);
4176     /* padding + 2 icon widths, column width */
4177     expect(2 + 16*2, rect.left);
4178     expect(50, rect.right);
4179 
4180     /* icon bounds */
4181     SetRect(&rect, LVIR_ICON, -1, -1, -1);
4182     r = SendMessageA(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
4183     expect(TRUE, r);
4184     /* padding + 1 icon width indentation, icon width */
4185     expect(2 + 16, rect.left);
4186     expect(34, rect.right);
4187 
4188     DestroyWindow(hwnd);
4189 }
4190 
4191 static void test_editbox(void)
4192 {
4193     static CHAR testitemA[]  = "testitem";
4194     static CHAR testitem1A[] = "testitem_quitelongname";
4195     static CHAR testitem2A[] = "testITEM_quitelongname";
4196     static CHAR buffer[25];
4197     HWND hwnd, hwndedit, hwndedit2, header;
4198     LVITEMA item;
4199     INT r;
4200 
4201     hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
4202     ok(hwnd != NULL, "failed to create a listview window\n");
4203 
4204     insert_column(hwnd, 0);
4205 
4206     memset(&item, 0, sizeof(item));
4207     item.mask = LVIF_TEXT;
4208     item.pszText = testitemA;
4209     item.iItem = 0;
4210     item.iSubItem = 0;
4211     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
4212     expect(0, r);
4213 
4214     /* test notifications without edit created */
4215     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4216     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)0xdeadbeef);
4217     expect(0, r);
4218     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4219                 "edit box WM_COMMAND (EN_SETFOCUS), no edit created", FALSE);
4220     /* same thing but with valid window */
4221     hwndedit = CreateWindowA(WC_EDITA, "Test edit", WS_VISIBLE | WS_CHILD, 0, 0, 20,
4222                 10, hwnd, (HMENU)1, (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE), 0);
4223     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4224     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_SETFOCUS), (LPARAM)hwndedit);
4225     expect(0, r);
4226     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4227                 "edit box WM_COMMAND (EN_SETFOCUS), no edit created #2", FALSE);
4228     DestroyWindow(hwndedit);
4229 
4230     /* setting focus is necessary */
4231     SetFocus(hwnd);
4232     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4233     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4234 
4235     /* test children Z-order after Edit box created */
4236     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4237     ok(IsWindow(header), "Expected header to be created\n");
4238     ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
4239     ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
4240 
4241     /* modify initial string */
4242     r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
4243     expect(TRUE, r);
4244 
4245     /* edit window is resized and repositioned,
4246        check again for Z-order - it should be preserved */
4247     ok(GetTopWindow(hwnd) == header, "Expected header to be on top\n");
4248     ok(GetNextWindow(header, GW_HWNDNEXT) == hwndedit, "got %p\n", GetNextWindow(header, GW_HWNDNEXT));
4249 
4250     /* return focus to listview */
4251     SetFocus(hwnd);
4252 
4253     memset(&item, 0, sizeof(item));
4254     item.mask = LVIF_TEXT;
4255     item.pszText = buffer;
4256     item.cchTextMax = sizeof(buffer);
4257     item.iItem = 0;
4258     item.iSubItem = 0;
4259     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
4260     expect(TRUE, r);
4261 
4262     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
4263 
4264     /* send LVM_EDITLABEL on already created edit */
4265     SetFocus(hwnd);
4266     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4267     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4268     /* focus will be set to edit */
4269     ok(GetFocus() == hwndedit, "Expected Edit window to be focused\n");
4270     hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4271     ok(IsWindow(hwndedit2), "Expected Edit window to be created\n");
4272 
4273     /* creating label disabled when control isn't focused */
4274     SetFocus(0);
4275     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4276     todo_wine ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4277 
4278     /* check EN_KILLFOCUS handling */
4279     memset(&item, 0, sizeof(item));
4280     item.pszText = testitemA;
4281     item.iItem = 0;
4282     item.iSubItem = 0;
4283     r = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
4284     expect(TRUE, r);
4285 
4286     SetFocus(hwnd);
4287     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4288     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4289     /* modify edit and notify control that it lost focus */
4290     r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem1A);
4291     expect(TRUE, r);
4292     g_editbox_disp_info.item.pszText = NULL;
4293     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4294     expect(0, r);
4295     ok(g_editbox_disp_info.item.pszText != NULL, "expected notification with not null text\n");
4296 
4297     memset(&item, 0, sizeof(item));
4298     item.pszText = buffer;
4299     item.cchTextMax = sizeof(buffer);
4300     item.iItem = 0;
4301     item.iSubItem = 0;
4302     r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4303     expect(lstrlenA(item.pszText), r);
4304     ok(strcmp(buffer, testitem1A) == 0, "Expected item text to change\n");
4305     ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
4306 
4307     /* change item name to differ in casing only */
4308     SetFocus(hwnd);
4309     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4310     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4311     /* modify edit and notify control that it lost focus */
4312     r = SendMessageA(hwndedit, WM_SETTEXT, 0, (LPARAM)testitem2A);
4313     expect(TRUE, r);
4314     g_editbox_disp_info.item.pszText = NULL;
4315     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4316     expect(0, r);
4317     ok(g_editbox_disp_info.item.pszText != NULL, "got %p\n", g_editbox_disp_info.item.pszText);
4318 
4319     memset(&item, 0, sizeof(item));
4320     item.pszText = buffer;
4321     item.cchTextMax = sizeof(buffer);
4322     item.iItem = 0;
4323     item.iSubItem = 0;
4324     r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4325     expect(lstrlenA(item.pszText), r);
4326     ok(strcmp(buffer, testitem2A) == 0, "got %s, expected %s\n", buffer, testitem2A);
4327     ok(!IsWindow(hwndedit), "Expected Edit window to be freed\n");
4328 
4329     /* end edit without saving */
4330     SetFocus(hwnd);
4331     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4332     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4333     r = SendMessageA(hwndedit, WM_KEYDOWN, VK_ESCAPE, 0);
4334     expect(0, r);
4335     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4336                 "edit box - end edit, no change, escape", TRUE);
4337     /* end edit with saving */
4338     SetFocus(hwnd);
4339     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4340     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4341     r = SendMessageA(hwndedit, WM_KEYDOWN, VK_RETURN, 0);
4342     expect(0, r);
4343     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4344                 "edit box - end edit, no change, return", TRUE);
4345 
4346     memset(&item, 0, sizeof(item));
4347     item.pszText = buffer;
4348     item.cchTextMax = sizeof(buffer);
4349     item.iItem = 0;
4350     item.iSubItem = 0;
4351     r = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
4352     expect(lstrlenA(item.pszText), r);
4353     ok(strcmp(buffer, testitem2A) == 0, "Expected item text to change\n");
4354 
4355     /* LVM_EDITLABEL with -1 destroys current edit */
4356     hwndedit = (HWND)SendMessageA(hwnd, LVM_GETEDITCONTROL, 0, 0);
4357     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4358     /* no edit present */
4359     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0);
4360     ok(hwndedit == NULL, "Expected Edit window not to be created\n");
4361     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4362     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4363     /* edit present */
4364     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4365     hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -1, 0);
4366     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4367     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4368     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4369     /* check another negative value */
4370     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4371     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4372     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4373     hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, -2, 0);
4374     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4375     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4376     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4377     /* and value greater than max item index */
4378     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4379     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4380     ok(GetFocus() == hwndedit, "Expected Edit to be focused\n");
4381     r = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
4382     hwndedit2 = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, r, 0);
4383     ok(hwndedit2 == NULL, "Expected Edit window not to be created\n");
4384     ok(!IsWindow(hwndedit), "Expected Edit window to be destroyed\n");
4385     ok(GetFocus() == hwnd, "Expected List to be focused\n");
4386 
4387     /* messaging tests */
4388     SetFocus(hwnd);
4389     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4390     blockEdit = FALSE;
4391     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4392     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4393     /* testing only sizing messages */
4394     ok_sequence(sequences, EDITBOX_SEQ_INDEX, editbox_create_pos,
4395                 "edit box create - sizing", FALSE);
4396 
4397     /* WM_COMMAND with EN_KILLFOCUS isn't forwarded to parent */
4398     SetFocus(hwnd);
4399     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4400     ok(IsWindow(hwndedit), "Expected Edit window to be created\n");
4401     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4402     r = SendMessageA(hwnd, WM_COMMAND, MAKEWPARAM(0, EN_KILLFOCUS), (LPARAM)hwndedit);
4403     expect(0, r);
4404     ok_sequence(sequences, PARENT_SEQ_INDEX, edit_end_nochange,
4405                 "edit box WM_COMMAND (EN_KILLFOCUS)", TRUE);
4406 
4407     DestroyWindow(hwnd);
4408 }
4409 
4410 static void test_notifyformat(void)
4411 {
4412     HWND hwnd, header;
4413     DWORD r;
4414 
4415     hwnd = create_listview_control(LVS_REPORT);
4416     ok(hwnd != NULL, "failed to create a listview window\n");
4417 
4418     /* CCM_GETUNICODEFORMAT == LVM_GETUNICODEFORMAT,
4419        CCM_SETUNICODEFORMAT == LVM_SETUNICODEFORMAT */
4420     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4421     expect(0, r);
4422     SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
4423     /* set */
4424     r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 1, 0);
4425     expect(0, r);
4426     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4427     ok(r == 1, "Unexpected return value %d.\n", r);
4428     r = SendMessageA(hwnd, LVM_SETUNICODEFORMAT, 0, 0);
4429     expect(1, r);
4430     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4431     expect(0, r);
4432 
4433     DestroyWindow(hwnd);
4434 
4435     /* test failure in parent WM_NOTIFYFORMAT  */
4436     notifyFormat = 0;
4437     hwnd = create_listview_control(LVS_REPORT);
4438     ok(hwnd != NULL, "failed to create a listview window\n");
4439     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4440     ok(IsWindow(header), "expected header to be created\n");
4441     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4442     expect(0, r);
4443     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4444     ok( r == 1, "Expected 1, got %d\n", r );
4445     r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_QUERY);
4446     ok(r != 0, "Expected valid format\n");
4447 
4448     notifyFormat = NFR_UNICODE;
4449     r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
4450     expect(NFR_UNICODE, r);
4451     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4452     expect(1, r);
4453     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4454     ok( r == 1, "Expected 1, got %d\n", r );
4455 
4456     notifyFormat = NFR_ANSI;
4457     r = SendMessageA(hwnd, WM_NOTIFYFORMAT, 0, NF_REQUERY);
4458     expect(NFR_ANSI, r);
4459     r = SendMessageA(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4460     expect(0, r);
4461     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4462     ok( r == 1, "Expected 1, got %d\n", r );
4463 
4464     DestroyWindow(hwnd);
4465 
4466     hwndparentW = create_parent_window(TRUE);
4467     ok(IsWindow(hwndparentW), "Unicode parent creation failed\n");
4468     if (!IsWindow(hwndparentW))  return;
4469 
4470     notifyFormat = -1;
4471     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4472     ok(hwnd != NULL, "failed to create a listview window\n");
4473     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4474     ok(IsWindow(header), "expected header to be created\n");
4475     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4476     expect(1, r);
4477     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4478     expect(1, r);
4479     DestroyWindow(hwnd);
4480     /* receiving error code defaulting to ansi */
4481     notifyFormat = 0;
4482     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4483     ok(hwnd != NULL, "failed to create a listview window\n");
4484     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4485     ok(IsWindow(header), "expected header to be created\n");
4486     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4487     expect(0, r);
4488     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4489     expect(1, r);
4490     DestroyWindow(hwnd);
4491     /* receiving ansi code from unicode window, use it */
4492     notifyFormat = NFR_ANSI;
4493     hwnd = create_listview_controlW(LVS_REPORT, hwndparentW);
4494     ok(hwnd != NULL, "failed to create a listview window\n");
4495     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4496     ok(IsWindow(header), "expected header to be created\n");
4497     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4498     expect(0, r);
4499     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4500     expect(1, r);
4501     DestroyWindow(hwnd);
4502     /* unicode listview with ansi parent window */
4503     notifyFormat = -1;
4504     hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
4505     ok(hwnd != NULL, "failed to create a listview window\n");
4506     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4507     ok(IsWindow(header), "expected header to be created\n");
4508     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4509     expect(0, r);
4510     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4511     expect(1, r);
4512     DestroyWindow(hwnd);
4513     /* unicode listview with ansi parent window, return error code */
4514     notifyFormat = 0;
4515     hwnd = create_listview_controlW(LVS_REPORT, hwndparent);
4516     ok(hwnd != NULL, "failed to create a listview window\n");
4517     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
4518     ok(IsWindow(header), "expected header to be created\n");
4519     r = SendMessageW(hwnd, LVM_GETUNICODEFORMAT, 0, 0);
4520     expect(0, r);
4521     r = SendMessageA(header, HDM_GETUNICODEFORMAT, 0, 0);
4522     expect(1, r);
4523     DestroyWindow(hwnd);
4524 
4525     DestroyWindow(hwndparentW);
4526 }
4527 
4528 static void test_indentation(void)
4529 {
4530     HWND hwnd;
4531     LVITEMA item;
4532     DWORD r;
4533 
4534     hwnd = create_listview_control(LVS_REPORT);
4535     ok(hwnd != NULL, "failed to create a listview window\n");
4536 
4537     memset(&item, 0, sizeof(item));
4538     item.mask = LVIF_INDENT;
4539     item.iItem = 0;
4540     item.iIndent = I_INDENTCALLBACK;
4541     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
4542     expect(0, r);
4543 
4544     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4545 
4546     item.iItem = 0;
4547     item.mask = LVIF_INDENT;
4548     r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
4549     expect(TRUE, r);
4550 
4551     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
4552                 "get indent dispinfo", FALSE);
4553 
4554     DestroyWindow(hwnd);
4555 }
4556 
4557 static INT CALLBACK DummyCompareEx(LPARAM first, LPARAM second, LPARAM param)
4558 {
4559     return 0;
4560 }
4561 
4562 static BOOL is_below_comctl_5(void)
4563 {
4564     HWND hwnd;
4565     BOOL ret;
4566 
4567     hwnd = create_listview_control(LVS_REPORT);
4568     ok(hwnd != NULL, "failed to create a listview window\n");
4569     insert_item(hwnd, 0);
4570 
4571     ret = SendMessageA(hwnd, LVM_SORTITEMSEX, 0, (LPARAM)&DummyCompareEx);
4572 
4573     DestroyWindow(hwnd);
4574 
4575     return !ret;
4576 }
4577 
4578 static void test_get_set_view(void)
4579 {
4580     HWND hwnd;
4581     DWORD ret;
4582     DWORD_PTR style;
4583 
4584     /* test style->view mapping */
4585     hwnd = create_listview_control(LVS_REPORT);
4586     ok(hwnd != NULL, "failed to create a listview window\n");
4587 
4588     ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
4589     expect(LV_VIEW_DETAILS, ret);
4590 
4591     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4592     /* LVS_ICON == 0 */
4593     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_REPORT);
4594     ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
4595     expect(LV_VIEW_ICON, ret);
4596 
4597     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4598     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SMALLICON);
4599     ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
4600     expect(LV_VIEW_SMALLICON, ret);
4601 
4602     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4603     SetWindowLongPtrA(hwnd, GWL_STYLE, (style & ~LVS_SMALLICON) | LVS_LIST);
4604     ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
4605     expect(LV_VIEW_LIST, ret);
4606 
4607     /* switching view doesn't touch window style */
4608     ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_DETAILS, 0);
4609     expect(1, ret);
4610     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4611     ok(style & LVS_LIST, "Expected style to be preserved\n");
4612     ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_ICON, 0);
4613     expect(1, ret);
4614     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4615     ok(style & LVS_LIST, "Expected style to be preserved\n");
4616     ret = SendMessageA(hwnd, LVM_SETVIEW, LV_VIEW_SMALLICON, 0);
4617     expect(1, ret);
4618     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4619     ok(style & LVS_LIST, "Expected style to be preserved\n");
4620 
4621     /* now change window style to see if view is remapped */
4622     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
4623     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SHOWSELALWAYS);
4624     ret = SendMessageA(hwnd, LVM_GETVIEW, 0, 0);
4625     expect(LV_VIEW_SMALLICON, ret);
4626 
4627     DestroyWindow(hwnd);
4628 }
4629 
4630 static void test_canceleditlabel(void)
4631 {
4632     HWND hwnd, hwndedit;
4633     DWORD ret;
4634     CHAR buff[10];
4635     LVITEMA itema;
4636     static CHAR test[] = "test";
4637     static const CHAR test1[] = "test1";
4638 
4639     hwnd = create_listview_control(LVS_EDITLABELS | LVS_REPORT);
4640     ok(hwnd != NULL, "failed to create a listview window\n");
4641 
4642     insert_item(hwnd, 0);
4643 
4644     /* try without edit created */
4645     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4646     ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4647     expect(TRUE, ret);
4648     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
4649                 "cancel edit label without edit", FALSE);
4650 
4651     /* cancel without data change */
4652     SetFocus(hwnd);
4653     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4654     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
4655     ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4656     expect(TRUE, ret);
4657     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
4658 
4659     /* cancel after data change */
4660     memset(&itema, 0, sizeof(itema));
4661     itema.pszText = test;
4662     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema);
4663     expect(TRUE, ret);
4664     SetFocus(hwnd);
4665     hwndedit = (HWND)SendMessageA(hwnd, LVM_EDITLABELA, 0, 0);
4666     ok(IsWindow(hwndedit), "Expected edit control to be created\n");
4667     ret = SetWindowTextA(hwndedit, test1);
4668     expect(1, ret);
4669     ret = SendMessageA(hwnd, LVM_CANCELEDITLABEL, 0, 0);
4670     expect(TRUE, ret);
4671     ok(!IsWindow(hwndedit), "Expected edit control to be destroyed\n");
4672     memset(&itema, 0, sizeof(itema));
4673     itema.pszText = buff;
4674     itema.cchTextMax = sizeof(buff)/sizeof(CHAR);
4675     ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&itema);
4676     expect(5, ret);
4677     ok(strcmp(buff, test1) == 0, "Expected label text not to change\n");
4678 
4679     DestroyWindow(hwnd);
4680 }
4681 
4682 static void test_mapidindex(void)
4683 {
4684     HWND hwnd;
4685     INT ret;
4686 
4687     /* LVM_MAPINDEXTOID unsupported with LVS_OWNERDATA */
4688     hwnd = create_listview_control(LVS_OWNERDATA | LVS_REPORT);
4689     ok(hwnd != NULL, "failed to create a listview window\n");
4690     insert_item(hwnd, 0);
4691     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0);
4692     expect(-1, ret);
4693     DestroyWindow(hwnd);
4694 
4695     hwnd = create_listview_control(LVS_REPORT);
4696     ok(hwnd != NULL, "failed to create a listview window\n");
4697 
4698     /* LVM_MAPINDEXTOID with invalid index */
4699     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0);
4700     expect(-1, ret);
4701 
4702     insert_item(hwnd, 0);
4703     insert_item(hwnd, 1);
4704 
4705     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, -1, 0);
4706     expect(-1, ret);
4707     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 2, 0);
4708     expect(-1, ret);
4709 
4710     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0);
4711     expect(0, ret);
4712     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0);
4713     expect(1, ret);
4714     /* remove 0 indexed item, id retained */
4715     SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
4716     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 0, 0);
4717     expect(1, ret);
4718     /* new id starts from previous value */
4719     insert_item(hwnd, 1);
4720     ret = SendMessageA(hwnd, LVM_MAPINDEXTOID, 1, 0);
4721     expect(2, ret);
4722 
4723     /* get index by id */
4724     ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, -1, 0);
4725     expect(-1, ret);
4726     ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 0, 0);
4727     expect(-1, ret);
4728     ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 1, 0);
4729     expect(0, ret);
4730     ret = SendMessageA(hwnd, LVM_MAPIDTOINDEX, 2, 0);
4731     expect(1, ret);
4732 
4733     DestroyWindow(hwnd);
4734 }
4735 
4736 static void test_getitemspacing(void)
4737 {
4738     HWND hwnd;
4739     DWORD ret;
4740     INT cx, cy;
4741     HIMAGELIST himl40, himl80;
4742 
4743     cx = GetSystemMetrics(SM_CXICONSPACING) - GetSystemMetrics(SM_CXICON);
4744     cy = GetSystemMetrics(SM_CYICONSPACING) - GetSystemMetrics(SM_CYICON);
4745 
4746     /* LVS_ICON */
4747     hwnd = create_listview_control(LVS_ICON);
4748     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4749     expect(cx, LOWORD(ret));
4750     expect(cy, HIWORD(ret));
4751 
4752     /* now try with icons */
4753     himl40 = pImageList_Create(40, 40, 0, 4, 4);
4754     ok(himl40 != NULL, "failed to create imagelist\n");
4755     himl80 = pImageList_Create(80, 80, 0, 4, 4);
4756     ok(himl80 != NULL, "failed to create imagelist\n");
4757     ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40);
4758     expect(0, ret);
4759 
4760     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4761     /* spacing + icon size returned */
4762     expect(cx + 40, LOWORD(ret));
4763     expect(cy + 40, HIWORD(ret));
4764     /* try changing icon size */
4765     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl80);
4766 
4767     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4768     /* spacing + icon size returned */
4769     expect(cx + 80, LOWORD(ret));
4770     expect(cy + 80, HIWORD(ret));
4771 
4772     /* set own icon spacing */
4773     ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(100, 100));
4774     expect(cx + 80, LOWORD(ret));
4775     expect(cy + 80, HIWORD(ret));
4776 
4777     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4778     /* set size returned */
4779     expect(100, LOWORD(ret));
4780     expect(100, HIWORD(ret));
4781 
4782     /* now change image list - icon spacing should be unaffected */
4783     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40);
4784 
4785     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4786     /* set size returned */
4787     expect(100, LOWORD(ret));
4788     expect(100, HIWORD(ret));
4789 
4790     /* spacing = 0 - keep previous value */
4791     ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(0, -1));
4792     expect(100, LOWORD(ret));
4793     expect(100, HIWORD(ret));
4794 
4795     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4796     expect(100, LOWORD(ret));
4797 
4798     expect(0xFFFF, HIWORD(ret));
4799 
4800     if (sizeof(void*) == 8)
4801     {
4802         /* NOTE: -1 is not treated the same as (DWORD)-1 by 64bit listview */
4803         ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, (DWORD)-1);
4804         expect(100, LOWORD(ret));
4805         expect(0xFFFF, HIWORD(ret));
4806 
4807         ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1);
4808         expect(0xFFFF, LOWORD(ret));
4809         expect(0xFFFF, HIWORD(ret));
4810     }
4811     else
4812     {
4813         ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, -1);
4814         expect(100, LOWORD(ret));
4815         expect(0xFFFF, HIWORD(ret));
4816     }
4817     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4818     /* spacing + icon size returned */
4819     expect(cx + 40, LOWORD(ret));
4820     expect(cy + 40, HIWORD(ret));
4821 
4822     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0);
4823     pImageList_Destroy(himl80);
4824     DestroyWindow(hwnd);
4825     /* LVS_SMALLICON */
4826     hwnd = create_listview_control(LVS_SMALLICON);
4827     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4828     expect(cx, LOWORD(ret));
4829     expect(cy, HIWORD(ret));
4830 
4831     /* spacing does not depend on selected view type */
4832     ret = SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl40);
4833     expect(0, ret);
4834 
4835     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4836     /* spacing + icon size returned */
4837     expect(cx + 40, LOWORD(ret));
4838     expect(cy + 40, HIWORD(ret));
4839 
4840     SendMessageA(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, 0);
4841     pImageList_Destroy(himl40);
4842     DestroyWindow(hwnd);
4843     /* LVS_REPORT */
4844     hwnd = create_listview_control(LVS_REPORT);
4845     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4846     expect(cx, LOWORD(ret));
4847     expect(cy, HIWORD(ret));
4848 
4849     DestroyWindow(hwnd);
4850     /* LVS_LIST */
4851     hwnd = create_listview_control(LVS_LIST);
4852     ret = SendMessageA(hwnd, LVM_GETITEMSPACING, FALSE, 0);
4853     expect(cx, LOWORD(ret));
4854     expect(cy, HIWORD(ret));
4855 
4856     DestroyWindow(hwnd);
4857 }
4858 
4859 static INT get_current_font_height(HWND listview)
4860 {
4861     TEXTMETRICA tm;
4862     HFONT hfont;
4863     HWND hwnd;
4864     HDC hdc;
4865 
4866     hwnd = (HWND)SendMessageA(listview, LVM_GETHEADER, 0, 0);
4867     if (!hwnd)
4868         hwnd = listview;
4869 
4870     hfont = (HFONT)SendMessageA(hwnd, WM_GETFONT, 0, 0);
4871     if (!hfont) {
4872         hdc = GetDC(hwnd);
4873         GetTextMetricsA(hdc, &tm);
4874         ReleaseDC(hwnd, hdc);
4875     }
4876     else {
4877         HFONT oldfont;
4878 
4879         hdc = GetDC(0);
4880         oldfont = SelectObject(hdc, hfont);
4881         GetTextMetricsA(hdc, &tm);
4882         SelectObject(hdc, oldfont);
4883         ReleaseDC(0, hdc);
4884     }
4885 
4886     return tm.tmHeight;
4887 }
4888 
4889 static void test_getcolumnwidth(void)
4890 {
4891     HWND hwnd;
4892     INT ret;
4893     DWORD_PTR style;
4894     LVCOLUMNA col;
4895     LVITEMA itema;
4896     INT height;
4897 
4898     /* default column width */
4899     hwnd = create_listview_control(LVS_ICON);
4900     ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4901     expect(0, ret);
4902     style = GetWindowLongA(hwnd, GWL_STYLE);
4903     SetWindowLongA(hwnd, GWL_STYLE, style | LVS_LIST);
4904     ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4905     todo_wine expect(8, ret);
4906     style = GetWindowLongA(hwnd, GWL_STYLE) & ~LVS_LIST;
4907     SetWindowLongA(hwnd, GWL_STYLE, style | LVS_REPORT);
4908     col.mask = 0;
4909     ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
4910     expect(0, ret);
4911     ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4912     expect(10, ret);
4913     DestroyWindow(hwnd);
4914 
4915     /* default column width with item added */
4916     hwnd = create_listview_control(LVS_LIST);
4917     memset(&itema, 0, sizeof(itema));
4918     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
4919     ok(!ret, "got %d\n", ret);
4920     ret = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
4921     height = get_current_font_height(hwnd);
4922     ok((ret / height) >= 6, "got width %d, height %d\n", ret, height);
4923     DestroyWindow(hwnd);
4924 }
4925 
4926 static void test_scrollnotify(void)
4927 {
4928     HWND hwnd;
4929     DWORD ret;
4930 
4931     hwnd = create_listview_control(LVS_REPORT);
4932 
4933     insert_column(hwnd, 0);
4934     insert_column(hwnd, 1);
4935     insert_item(hwnd, 0);
4936 
4937     /* make it scrollable - resize */
4938     ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
4939     expect(TRUE, ret);
4940     ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
4941     expect(TRUE, ret);
4942 
4943     /* try with dummy call */
4944     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4945     ret = SendMessageA(hwnd, LVM_SCROLL, 0, 0);
4946     expect(TRUE, ret);
4947     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4948                 "scroll notify 1", TRUE);
4949 
4950     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4951     ret = SendMessageA(hwnd, LVM_SCROLL, 1, 0);
4952     expect(TRUE, ret);
4953     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4954                 "scroll notify 2", TRUE);
4955 
4956     flush_sequences(sequences, NUM_MSG_SEQUENCES);
4957     ret = SendMessageA(hwnd, LVM_SCROLL, 1, 1);
4958     expect(TRUE, ret);
4959     ok_sequence(sequences, PARENT_SEQ_INDEX, scroll_parent_seq,
4960                 "scroll notify 3", TRUE);
4961 
4962     DestroyWindow(hwnd);
4963 }
4964 
4965 static void test_LVS_EX_TRANSPARENTBKGND(void)
4966 {
4967     HWND hwnd;
4968     DWORD ret;
4969     HDC hdc;
4970 
4971     hwnd = create_listview_control(LVS_REPORT);
4972 
4973     ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4974     expect(TRUE, ret);
4975 
4976     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4977                                                     LVS_EX_TRANSPARENTBKGND);
4978 
4979     ret = SendMessageA(hwnd, LVM_GETBKCOLOR, 0, 0);
4980     if (ret != CLR_NONE)
4981     {
4982         win_skip("LVS_EX_TRANSPARENTBKGND unsupported\n");
4983         DestroyWindow(hwnd);
4984         return;
4985     }
4986 
4987     /* try to set some back color and check this style bit */
4988     ret = SendMessageA(hwnd, LVM_SETBKCOLOR, 0, RGB(0, 0, 0));
4989     expect(TRUE, ret);
4990     ret = SendMessageA(hwnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
4991     ok(!(ret & LVS_EX_TRANSPARENTBKGND), "Expected LVS_EX_TRANSPARENTBKGND to unset\n");
4992 
4993     /* now test what this style actually does */
4994     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTBKGND,
4995                                                     LVS_EX_TRANSPARENTBKGND);
4996 
4997     hdc = GetWindowDC(hwndparent);
4998 
4999     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5000     SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
5001     ok_sequence(sequences, PARENT_SEQ_INDEX, lvs_ex_transparentbkgnd_seq,
5002                 "LVS_EX_TRANSPARENTBKGND parent", FALSE);
5003 
5004     ReleaseDC(hwndparent, hdc);
5005 
5006     DestroyWindow(hwnd);
5007 }
5008 
5009 static void test_approximate_viewrect(void)
5010 {
5011     static CHAR test[] = "abracadabra, a very long item label";
5012     DWORD item_width, item_height, header_height;
5013     static CHAR column_header[] = "Header";
5014     unsigned const column_width = 100;
5015     DWORD ret, item_count;
5016     HIMAGELIST himl;
5017     LVITEMA itema;
5018     LVCOLUMNA col;
5019     HBITMAP hbmp;
5020     HWND hwnd;
5021 
5022     /* LVS_ICON */
5023     hwnd = create_listview_control(LVS_ICON);
5024     himl = pImageList_Create(40, 40, 0, 4, 4);
5025     ok(himl != NULL, "failed to create imagelist\n");
5026     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
5027     ok(hbmp != NULL, "failed to create bitmap\n");
5028     ret = pImageList_Add(himl, hbmp, 0);
5029     expect(0, ret);
5030     ret = SendMessageA(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
5031     expect(0, ret);
5032 
5033     itema.mask = LVIF_IMAGE;
5034     itema.iImage = 0;
5035     itema.iItem = 0;
5036     itema.iSubItem = 0;
5037     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
5038     expect(0, ret);
5039 
5040     ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(75, 75));
5041     ok(ret != 0, "Unexpected return value %#x.\n", ret);
5042 
5043     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
5044     expect(MAKELONG(77,827), ret);
5045 
5046     ret = SendMessageA(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(50, 50));
5047     ok(ret != 0, "got 0\n");
5048 
5049     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 11, MAKELPARAM(100,100));
5050     expect(MAKELONG(102,302), ret);
5051 
5052     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
5053     expect(MAKELONG(52,52), ret);
5054 
5055     itema.pszText = test;
5056     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&itema);
5057     expect(TRUE, ret);
5058     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, MAKELPARAM(100,100));
5059     expect(MAKELONG(52,52), ret);
5060 
5061     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100,100));
5062     expect(MAKELONG(52,2), ret);
5063     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, MAKELPARAM(100,100));
5064     expect(MAKELONG(52,52), ret);
5065     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELPARAM(100,100));
5066     expect(MAKELONG(102,52), ret);
5067     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 3, MAKELPARAM(100,100));
5068     expect(MAKELONG(102,102), ret);
5069     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 4, MAKELPARAM(100,100));
5070     expect(MAKELONG(102,102), ret);
5071     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 5, MAKELPARAM(100,100));
5072     expect(MAKELONG(102,152), ret);
5073     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 6, MAKELPARAM(100,100));
5074     expect(MAKELONG(102,152), ret);
5075     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 7, MAKELPARAM(160,100));
5076     expect(MAKELONG(152,152), ret);
5077 
5078     DestroyWindow(hwnd);
5079 
5080     /* LVS_REPORT */
5081     hwnd = create_listview_control(LVS_REPORT);
5082 
5083     /* Empty control without columns */
5084     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, MAKELPARAM(100, 100));
5085 todo_wine
5086     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5087     ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
5088 
5089     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0);
5090     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5091 todo_wine
5092     ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
5093 
5094     header_height = HIWORD(ret);
5095 
5096     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0);
5097     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5098 todo_wine
5099     ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret));
5100 
5101     item_height = HIWORD(ret) - header_height;
5102 
5103     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0);
5104     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5105     ok(HIWORD(ret) == (header_height - 2 * item_height), "Unexpected height %d.\n", HIWORD(ret)) ;
5106 
5107     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0);
5108     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5109     ok(HIWORD(ret) == header_height, "Unexpected height.\n");
5110     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0);
5111     ok(LOWORD(ret) == 0, "Unexpected width %d.\n", LOWORD(ret));
5112     ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5113 
5114     /* Insert column */
5115     col.mask = LVCF_TEXT | LVCF_WIDTH;
5116     col.pszText = column_header;
5117     col.cx = column_width;
5118     ret = SendMessageA(hwnd, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
5119     ok(ret == 0, "Unexpected return value %d.\n", ret);
5120 
5121     /* Empty control with column */
5122     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0);
5123 todo_wine {
5124     ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret));
5125     ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
5126 }
5127     header_height = HIWORD(ret);
5128     item_width = LOWORD(ret);
5129 
5130     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0);
5131     ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5132 todo_wine
5133     ok(HIWORD(ret) > header_height, "Unexpected height %d.\n", HIWORD(ret));
5134 
5135     item_height = HIWORD(ret) - header_height;
5136 
5137     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0);
5138     ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5139     ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5140 
5141     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0);
5142     ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5143     ok(HIWORD(ret) == header_height, "Unexpected height %d.\n", HIWORD(ret));
5144 
5145     ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0);
5146     ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5147     ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5148 
5149     for (item_count = 1; item_count <= 2; ++item_count)
5150     {
5151         itema.mask = LVIF_TEXT;
5152         itema.iItem = 0;
5153         itema.iSubItem = 0;
5154         itema.pszText = test;
5155         ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&itema);
5156         ok(ret == 0, "Unexpected return value %d.\n", ret);
5157 
5158         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 0, 0);
5159         ok(LOWORD(ret) >= column_width, "Unexpected width %d.\n", LOWORD(ret));
5160     todo_wine
5161         ok(HIWORD(ret) != 0, "Unexpected height %d.\n", HIWORD(ret));
5162 
5163         header_height = HIWORD(ret);
5164         item_width = LOWORD(ret);
5165 
5166         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 1, 0);
5167         ok(LOWORD(ret) == item_width, "Unexpected width %d, item %d\n", LOWORD(ret), item_count - 1);
5168         ok(HIWORD(ret) > header_height, "Unexpected height %d. item %d.\n", HIWORD(ret),  item_count - 1);
5169 
5170         item_height = HIWORD(ret) - header_height;
5171 
5172         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, 0);
5173         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5174     todo_wine
5175         ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5176 
5177         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -1, 0);
5178         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5179         ok(HIWORD(ret) == header_height + item_count * item_height, "Unexpected height %d.\n", HIWORD(ret));
5180 
5181         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, 0);
5182         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5183         ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5184 
5185         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, 2, MAKELONG(item_width * 2, header_height + 3 * item_height));
5186         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5187         ok(HIWORD(ret) == header_height + 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5188 
5189         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(item_width * 2, 0));
5190         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5191     todo_wine
5192         ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5193 
5194         ret = SendMessageA(hwnd, LVM_APPROXIMATEVIEWRECT, -2, MAKELONG(-1, -1));
5195         ok(LOWORD(ret) == item_width, "Unexpected width %d.\n", LOWORD(ret));
5196     todo_wine
5197         ok(HIWORD(ret) == header_height - 2 * item_height, "Unexpected height %d.\n", HIWORD(ret));
5198     }
5199 
5200     DestroyWindow(hwnd);
5201 
5202 }
5203 
5204 static void test_finditem(void)
5205 {
5206     LVFINDINFOA fi;
5207     static char f[5];
5208     HWND hwnd;
5209     INT r;
5210 
5211     hwnd = create_listview_control(LVS_REPORT);
5212     insert_item(hwnd, 0);
5213 
5214     memset(&fi, 0, sizeof(fi));
5215 
5216     /* full string search, inserted text was "foo" */
5217     strcpy(f, "foo");
5218     fi.flags = LVFI_STRING;
5219     fi.psz = f;
5220     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5221     expect(0, r);
5222 
5223     fi.flags = LVFI_STRING | LVFI_PARTIAL;
5224     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5225     expect(0, r);
5226 
5227     fi.flags = LVFI_PARTIAL;
5228     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5229     expect(0, r);
5230 
5231     /* partial string search, inserted text was "foo" */
5232     strcpy(f, "fo");
5233     fi.flags = LVFI_STRING | LVFI_PARTIAL;
5234     fi.psz = f;
5235     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5236     expect(0, r);
5237 
5238     fi.flags = LVFI_STRING;
5239     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5240     expect(-1, r);
5241 
5242     fi.flags = LVFI_PARTIAL;
5243     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5244     expect(0, r);
5245 
5246     /* partial string search, part after start char */
5247     strcpy(f, "oo");
5248     fi.flags = LVFI_STRING | LVFI_PARTIAL;
5249     fi.psz = f;
5250     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5251     expect(-1, r);
5252 
5253     /* try with LVFI_SUBSTRING */
5254     strcpy(f, "fo");
5255     fi.flags = LVFI_SUBSTRING;
5256     fi.psz = f;
5257     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5258     expect(0, r);
5259     strcpy(f, "f");
5260     fi.flags = LVFI_SUBSTRING;
5261     fi.psz = f;
5262     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5263     expect(0, r);
5264     strcpy(f, "o");
5265     fi.flags = LVFI_SUBSTRING;
5266     fi.psz = f;
5267     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5268     expect(-1, r);
5269 
5270     strcpy(f, "o");
5271     fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL;
5272     fi.psz = f;
5273     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5274     expect(-1, r);
5275 
5276     strcpy(f, "f");
5277     fi.flags = LVFI_SUBSTRING | LVFI_STRING;
5278     fi.psz = f;
5279     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5280     expect(0, r);
5281 
5282     fi.flags = LVFI_SUBSTRING | LVFI_PARTIAL;
5283     r = SendMessageA(hwnd, LVM_FINDITEMA, -1, (LPARAM)&fi);
5284     expect(0, r);
5285 
5286     DestroyWindow(hwnd);
5287 }
5288 
5289 static void test_LVS_EX_HEADERINALLVIEWS(void)
5290 {
5291     HWND hwnd, header;
5292     DWORD style;
5293 
5294     hwnd = create_listview_control(LVS_ICON);
5295 
5296     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
5297                                                     LVS_EX_HEADERINALLVIEWS);
5298 
5299     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5300     if (!IsWindow(header))
5301     {
5302         win_skip("LVS_EX_HEADERINALLVIEWS unsupported\n");
5303         DestroyWindow(hwnd);
5304         return;
5305     }
5306 
5307     /* LVS_NOCOLUMNHEADER works as before */
5308     style = GetWindowLongA(hwnd, GWL_STYLE);
5309     SetWindowLongW(hwnd, GWL_STYLE, style | LVS_NOCOLUMNHEADER);
5310     style = GetWindowLongA(header, GWL_STYLE);
5311     ok(style & HDS_HIDDEN, "Expected HDS_HIDDEN\n");
5312     style = GetWindowLongA(hwnd, GWL_STYLE);
5313     SetWindowLongW(hwnd, GWL_STYLE, style & ~LVS_NOCOLUMNHEADER);
5314     style = GetWindowLongA(header, GWL_STYLE);
5315     ok(!(style & HDS_HIDDEN), "Expected HDS_HIDDEN to be unset\n");
5316 
5317     /* try to remove style */
5318     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS, 0);
5319     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5320     ok(IsWindow(header), "Expected header to be created\n");
5321     style = GetWindowLongA(header, GWL_STYLE);
5322     ok(!(style & HDS_HIDDEN), "HDS_HIDDEN not expected\n");
5323 
5324     DestroyWindow(hwnd);
5325 
5326     /* check other styles */
5327     hwnd = create_listview_control(LVS_LIST);
5328     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
5329                                                     LVS_EX_HEADERINALLVIEWS);
5330     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5331     ok(IsWindow(header), "Expected header to be created\n");
5332     DestroyWindow(hwnd);
5333 
5334     hwnd = create_listview_control(LVS_SMALLICON);
5335     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
5336                                                     LVS_EX_HEADERINALLVIEWS);
5337     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5338     ok(IsWindow(header), "Expected header to be created\n");
5339     DestroyWindow(hwnd);
5340 
5341     hwnd = create_listview_control(LVS_REPORT);
5342     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_HEADERINALLVIEWS,
5343                                                     LVS_EX_HEADERINALLVIEWS);
5344     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5345     ok(IsWindow(header), "Expected header to be created\n");
5346     DestroyWindow(hwnd);
5347 }
5348 
5349 static void test_hover(void)
5350 {
5351     HWND hwnd, fg;
5352     DWORD r;
5353 
5354     hwnd = create_listview_control(LVS_ICON);
5355     SetForegroundWindow(hwndparent);
5356     fg = GetForegroundWindow();
5357     if (fg != hwndparent)
5358     {
5359         skip("Window is not in the foreground. Skipping hover tests.\n");
5360         DestroyWindow(hwnd);
5361         return;
5362     }
5363 
5364     /* test WM_MOUSEHOVER forwarding */
5365     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5366     r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0);
5367     expect(0, r);
5368     ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER allow test", TRUE);
5369     g_block_hover = TRUE;
5370     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5371     r = SendMessageA(hwnd, WM_MOUSEHOVER, 0, 0);
5372     expect(0, r);
5373     ok_sequence(sequences, PARENT_SEQ_INDEX, hover_parent, "NM_HOVER block test", TRUE);
5374     g_block_hover = FALSE;
5375 
5376     r = SendMessageA(hwnd, LVM_SETHOVERTIME, 0, 500);
5377     expect(HOVER_DEFAULT, r);
5378     r = SendMessageA(hwnd, LVM_GETHOVERTIME, 0, 0);
5379     expect(500, r);
5380 
5381     DestroyWindow(hwnd);
5382 }
5383 
5384 static void test_destroynotify(void)
5385 {
5386     HWND hwnd;
5387     BOOL ret;
5388 
5389     hwnd = create_listview_control(LVS_REPORT);
5390     ok(hwnd != NULL, "failed to create listview window\n");
5391 
5392     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5393     DestroyWindow(hwnd);
5394     ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_destroy, "check destroy order", FALSE);
5395 
5396     /* same for ownerdata list */
5397     hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA);
5398     ok(hwnd != NULL, "failed to create listview window\n");
5399 
5400     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5401     DestroyWindow(hwnd);
5402     ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_destroy, "check destroy order, ownerdata", FALSE);
5403 
5404     hwnd = create_listview_control(LVS_REPORT|LVS_OWNERDATA);
5405     ok(hwnd != NULL, "failed to create listview window\n");
5406 
5407     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5408     ret = SendMessageA(hwnd, LVM_DELETEALLITEMS, 0, 0);
5409     ok(ret == TRUE, "got %d\n", ret);
5410     ok_sequence(sequences, COMBINED_SEQ_INDEX, listview_ownerdata_deleteall, "deleteall ownerdata", FALSE);
5411     DestroyWindow(hwnd);
5412 }
5413 
5414 static void test_header_notification(void)
5415 {
5416     static char textA[] = "newtext";
5417     HWND list, header;
5418     HDITEMA item;
5419     NMHEADERA nmh;
5420     LVCOLUMNA col;
5421     DWORD ret;
5422     BOOL r;
5423 
5424     list = create_listview_control(LVS_REPORT);
5425     ok(list != NULL, "failed to create listview window\n");
5426 
5427     memset(&col, 0, sizeof(col));
5428     col.mask = LVCF_WIDTH;
5429     col.cx = 100;
5430     ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
5431     expect(0, ret);
5432 
5433     /* check list parent notification after header item changed,
5434        this test should be placed before header subclassing to avoid
5435        Listview -> Header messages to be logged */
5436     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5437 
5438     col.mask = LVCF_TEXT;
5439     col.pszText = textA;
5440     r = SendMessageA(list, LVM_SETCOLUMNA, 0, (LPARAM)&col);
5441     expect(TRUE, r);
5442 
5443     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_changed_seq,
5444                 "header notify, listview", FALSE);
5445     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5446                 "header notify, parent", FALSE);
5447 
5448     header = subclass_header(list);
5449 
5450     ret = SendMessageA(header, HDM_GETITEMCOUNT, 0, 0);
5451     expect(1, ret);
5452 
5453     memset(&item, 0, sizeof(item));
5454     item.mask = HDI_WIDTH;
5455     ret = SendMessageA(header, HDM_GETITEMA, 0, (LPARAM)&item);
5456     expect(1, ret);
5457     expect(100, item.cxy);
5458 
5459     nmh.hdr.hwndFrom = header;
5460     nmh.hdr.idFrom = GetWindowLongPtrA(header, GWLP_ID);
5461     nmh.hdr.code = HDN_ITEMCHANGEDA;
5462     nmh.iItem = 0;
5463     nmh.iButton = 0;
5464     item.mask = HDI_WIDTH;
5465     item.cxy = 50;
5466     nmh.pitem = &item;
5467     ret = SendMessageA(list, WM_NOTIFY, 0, (LPARAM)&nmh);
5468     expect(0, ret);
5469 
5470     DestroyWindow(list);
5471 }
5472 
5473 static void test_header_notification2(void)
5474 {
5475     static char textA[] = "newtext";
5476     HWND list, header;
5477     HDITEMW itemW;
5478     NMHEADERW nmhdr;
5479     LVCOLUMNA col;
5480     DWORD ret;
5481     WCHAR buffer[100];
5482     struct message parent_header_notify_seq[] = {
5483         { WM_NOTIFY, sent|id, 0, 0, 0 },
5484         { 0 }
5485     };
5486 
5487     list = create_listview_control(LVS_REPORT);
5488     ok(list != NULL, "failed to create listview window\n");
5489 
5490     memset(&col, 0, sizeof(col));
5491     col.mask = LVCF_WIDTH | LVCF_TEXT;
5492     col.cx = 100;
5493     col.pszText = textA;
5494     ret = SendMessageA(list, LVM_INSERTCOLUMNA, 0, (LPARAM)&col);
5495     expect(0, ret);
5496 
5497     header = (HWND)SendMessageA(list, LVM_GETHEADER, 0, 0);
5498     ok(header != 0, "No header\n");
5499     memset(&itemW, 0, sizeof(itemW));
5500     itemW.mask = HDI_WIDTH | HDI_ORDER | HDI_TEXT;
5501     itemW.pszText = buffer;
5502     itemW.cchTextMax = sizeof(buffer);
5503     ret = SendMessageW(header, HDM_GETITEMW, 0, (LPARAM)&itemW);
5504     expect(1, ret);
5505 
5506     nmhdr.hdr.hwndFrom = header;
5507     nmhdr.hdr.idFrom = GetWindowLongPtrW(header, GWLP_ID);
5508     nmhdr.iItem = 0;
5509     nmhdr.iButton = 0;
5510     nmhdr.pitem = &itemW;
5511 
5512     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5513     nmhdr.hdr.code = HDN_ITEMCHANGINGW;
5514     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5515     ok(ret == 0, "got %d\n", ret);
5516     parent_header_notify_seq[0].id = HDN_ITEMCHANGINGA;
5517     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5518                 "header notify, parent", TRUE);
5519     todo_wine
5520     ok(nmhdr.hdr.code == HDN_ITEMCHANGINGA, "Expected ANSI notification code\n");
5521     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5522     nmhdr.hdr.code = HDN_ITEMCHANGEDW;
5523     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5524     ok(ret == 0, "got %d\n", ret);
5525     parent_header_notify_seq[0].id = HDN_ITEMCHANGEDA;
5526     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5527                 "header notify, parent", TRUE);
5528     todo_wine
5529     ok(nmhdr.hdr.code == HDN_ITEMCHANGEDA, "Expected ANSI notification code\n");
5530     /* HDN_ITEMCLICK sets focus to list, which generates messages we don't want to check */
5531     SetFocus(list);
5532     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5533     nmhdr.hdr.code = HDN_ITEMCLICKW;
5534     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5535     ok(ret == 0, "got %d\n", ret);
5536     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_click_seq,
5537                 "header notify, parent", FALSE);
5538     ok(nmhdr.hdr.code == HDN_ITEMCLICKA, "Expected ANSI notification code\n");
5539     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5540     nmhdr.hdr.code = HDN_ITEMDBLCLICKW;
5541     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5542     ok(ret == 0, "got %d\n", ret);
5543     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5544                 "header notify, parent", FALSE);
5545     ok(nmhdr.hdr.code == HDN_ITEMDBLCLICKW, "Expected Unicode notification code\n");
5546     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5547     nmhdr.hdr.code = HDN_DIVIDERDBLCLICKW;
5548     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5549     ok(ret == 0, "got %d\n", ret);
5550     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_divider_dclick_seq,
5551                 "header notify, parent", TRUE);
5552     ok(nmhdr.hdr.code == HDN_DIVIDERDBLCLICKA, "Expected ANSI notification code\n");
5553     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5554     nmhdr.hdr.code = HDN_BEGINTRACKW;
5555     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5556     ok(ret == 0, "got %d\n", ret);
5557     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5558                 "header notify, parent", FALSE);
5559     ok(nmhdr.hdr.code == HDN_BEGINTRACKW, "Expected Unicode notification code\n");
5560     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5561     nmhdr.hdr.code = HDN_ENDTRACKW;
5562     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5563     ok(ret == 0, "got %d\n", ret);
5564     parent_header_notify_seq[0].id = HDN_ENDTRACKA;
5565     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5566                 "header notify, parent", FALSE);
5567     ok(nmhdr.hdr.code == HDN_ENDTRACKA, "Expected ANSI notification code\n");
5568     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5569     nmhdr.hdr.code = HDN_TRACKW;
5570     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5571     ok(ret == 0, "got %d\n", ret);
5572     parent_header_notify_seq[0].id = HDN_TRACKA;
5573     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5574                 "header notify, parent", FALSE);
5575     ok(nmhdr.hdr.code == HDN_TRACKA, "Expected ANSI notification code\n");
5576     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5577     nmhdr.hdr.code = HDN_BEGINDRAG;
5578     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5579     ok(ret == 1, "got %d\n", ret);
5580     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5581                 "header notify, parent", FALSE);
5582     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5583     nmhdr.hdr.code = HDN_ENDDRAG;
5584     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5585     ok(ret == 0, "got %d\n", ret);
5586     parent_header_notify_seq[0].id = HDN_ENDDRAG;
5587     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5588                 "header notify, parent", FALSE);
5589     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5590     nmhdr.hdr.code = HDN_FILTERCHANGE;
5591     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5592     ok(ret == 0, "got %d\n", ret);
5593     parent_header_notify_seq[0].id = HDN_FILTERCHANGE;
5594     parent_header_notify_seq[0].flags |= optional; /* NT4 does not send this message */
5595     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_header_notify_seq,
5596                 "header notify, parent", FALSE);
5597     parent_header_notify_seq[0].flags &= ~optional;
5598     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5599     nmhdr.hdr.code = HDN_BEGINFILTEREDIT;
5600     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5601     ok(ret == 0, "got %d\n", ret);
5602     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5603                 "header notify, parent", FALSE);
5604     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5605     nmhdr.hdr.code = HDN_ENDFILTEREDIT;
5606     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5607     ok(ret == 0, "got %d\n", ret);
5608     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5609                 "header notify, parent", FALSE);
5610     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5611     nmhdr.hdr.code = HDN_ITEMSTATEICONCLICK;
5612     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5613     ok(ret == 0, "got %d\n", ret);
5614     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5615                 "header notify, parent", FALSE);
5616     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5617     nmhdr.hdr.code = HDN_ITEMKEYDOWN;
5618     ret = SendMessageW(list, WM_NOTIFY, 0, (LPARAM)&nmhdr);
5619     ok(ret == 0, "got %d\n", ret);
5620     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
5621                 "header notify, parent", FALSE);
5622 
5623     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5624 
5625     DestroyWindow(list);
5626 }
5627 
5628 static void test_createdragimage(void)
5629 {
5630     HIMAGELIST himl;
5631     POINT pt;
5632     HWND list;
5633 
5634     list = create_listview_control(LVS_ICON);
5635     ok(list != NULL, "failed to create listview window\n");
5636 
5637     insert_item(list, 0);
5638 
5639     /* NULL point */
5640     himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, 0);
5641     ok(himl == NULL, "got %p\n", himl);
5642 
5643     himl = (HIMAGELIST)SendMessageA(list, LVM_CREATEDRAGIMAGE, 0, (LPARAM)&pt);
5644     ok(himl != NULL, "got %p\n", himl);
5645     pImageList_Destroy(himl);
5646 
5647     DestroyWindow(list);
5648 }
5649 
5650 static void test_dispinfo(void)
5651 {
5652     static const char testA[] = "TEST";
5653     WCHAR buff[10];
5654     LVITEMA item;
5655     HWND hwnd;
5656     DWORD ret;
5657 
5658     hwnd = create_listview_control(LVS_ICON);
5659     ok(hwnd != NULL, "failed to create listview window\n");
5660 
5661     insert_item(hwnd, 0);
5662 
5663     memset(&item, 0, sizeof(item));
5664     item.pszText = LPSTR_TEXTCALLBACKA;
5665     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
5666     expect(1, ret);
5667 
5668     g_disp_A_to_W = TRUE;
5669     item.pszText = (char*)buff;
5670     item.cchTextMax = sizeof(buff)/sizeof(WCHAR);
5671     ret = SendMessageA(hwnd, LVM_GETITEMTEXTA, 0, (LPARAM)&item);
5672     ok(ret == sizeof(testA)-1, "got %d, expected 4\n", ret);
5673     g_disp_A_to_W = FALSE;
5674 
5675     ok(memcmp(item.pszText, testA, sizeof(testA)) == 0,
5676         "got %s, expected %s\n", item.pszText, testA);
5677 
5678     DestroyWindow(hwnd);
5679 }
5680 
5681 static void test_LVM_SETITEMTEXT(void)
5682 {
5683     static char testA[] = "TEST";
5684     LVITEMA item;
5685     HWND hwnd;
5686     DWORD ret;
5687 
5688     hwnd = create_listview_control(LVS_ICON);
5689     ok(hwnd != NULL, "failed to create listview window\n");
5690 
5691     insert_item(hwnd, 0);
5692 
5693     /* null item pointer */
5694     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, 0);
5695     expect(FALSE, ret);
5696 
5697     ret = SendMessageA(hwnd, LVM_SETITEMTEXTW, 0, 0);
5698     expect(FALSE, ret);
5699 
5700     /* index out of bounds */
5701     item.pszText = testA;
5702     item.cchTextMax = 0; /* ignored */
5703     item.iSubItem = 0;
5704 
5705     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 1, (LPARAM)&item);
5706     expect(FALSE, ret);
5707 
5708     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, -1, (LPARAM)&item);
5709     expect(FALSE, ret);
5710 
5711     ret = SendMessageA(hwnd, LVM_SETITEMTEXTA, 0, (LPARAM)&item);
5712     expect(TRUE, ret);
5713 
5714     DestroyWindow(hwnd);
5715 }
5716 
5717 static void test_LVM_REDRAWITEMS(void)
5718 {
5719     HWND list;
5720     DWORD ret;
5721 
5722     list = create_listview_control(LVS_ICON);
5723     ok(list != NULL, "failed to create listview window\n");
5724 
5725     ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0);
5726     expect(TRUE, ret);
5727 
5728     insert_item(list, 0);
5729 
5730     ret = SendMessageA(list, LVM_REDRAWITEMS, -1, 0);
5731     expect(TRUE, ret);
5732 
5733     ret = SendMessageA(list, LVM_REDRAWITEMS, 0, -1);
5734     expect(TRUE, ret);
5735 
5736     ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 0);
5737     expect(TRUE, ret);
5738 
5739     ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 1);
5740     expect(TRUE, ret);
5741 
5742     ret = SendMessageA(list, LVM_REDRAWITEMS, 0, 2);
5743     expect(TRUE, ret);
5744 
5745     ret = SendMessageA(list, LVM_REDRAWITEMS, 1, 0);
5746     expect(TRUE, ret);
5747 
5748     ret = SendMessageA(list, LVM_REDRAWITEMS, 2, 3);
5749     expect(TRUE, ret);
5750 
5751     DestroyWindow(list);
5752 }
5753 
5754 static void test_imagelists(void)
5755 {
5756     HWND hwnd, header;
5757     HIMAGELIST himl1, himl2, himl3;
5758     LRESULT ret;
5759 
5760     himl1 = pImageList_Create(40, 40, 0, 4, 4);
5761     himl2 = pImageList_Create(40, 40, 0, 4, 4);
5762     himl3 = pImageList_Create(40, 40, 0, 4, 4);
5763     ok(himl1 != NULL, "Failed to create imagelist\n");
5764     ok(himl2 != NULL, "Failed to create imagelist\n");
5765     ok(himl3 != NULL, "Failed to create imagelist\n");
5766 
5767     hwnd = create_listview_control(LVS_REPORT | LVS_SHAREIMAGELISTS);
5768     header = subclass_header(hwnd);
5769 
5770     ok(header != NULL, "Expected header\n");
5771     ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0);
5772     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5773 
5774     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5775 
5776     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1);
5777     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5778     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5779                 "set normal image list", FALSE);
5780 
5781     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5782 
5783     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2);
5784     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5785     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5786                 "set state image list", TRUE);
5787 
5788     ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0);
5789     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5790 
5791     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5792 
5793     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3);
5794     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5795     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_header_set_imagelist,
5796                 "set small image list", FALSE);
5797 
5798     ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0);
5799     ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret);
5800     DestroyWindow(hwnd);
5801 
5802     hwnd = create_listview_control(WS_VISIBLE | LVS_ICON);
5803 
5804     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5805 
5806     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)himl1);
5807     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5808     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5809                 "set normal image list", FALSE);
5810 
5811     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5812 
5813     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl2);
5814     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5815     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5816                 "set state image list", FALSE);
5817 
5818     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5819 
5820     ret = SendMessageW(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl3);
5821     ok(ret == 0, "Expected no imagelist, got %p\n", (HIMAGELIST)ret);
5822     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_set_imagelist,
5823                 "set small image list", FALSE);
5824 
5825     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5826     ok(header == NULL, "Expected no header, got %p\n", header);
5827 
5828     SetWindowLongPtrA(hwnd, GWL_STYLE, GetWindowLongPtrA(hwnd, GWL_STYLE) | LVS_REPORT);
5829 
5830     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5831     ok(header != NULL, "Expected header, got NULL\n");
5832 
5833     ret = SendMessageA(header, HDM_GETIMAGELIST, 0, 0);
5834     ok((HIMAGELIST)ret == himl3, "Expected imagelist %p, got %p\n", himl3, (HIMAGELIST)ret);
5835 
5836     DestroyWindow(hwnd);
5837 }
5838 
5839 static void test_deleteitem(void)
5840 {
5841     LVITEMA item;
5842     UINT state;
5843     HWND hwnd;
5844     BOOL ret;
5845 
5846     hwnd = create_listview_control(LVS_REPORT);
5847 
5848     insert_item(hwnd, 0);
5849     insert_item(hwnd, 0);
5850     insert_item(hwnd, 0);
5851     insert_item(hwnd, 0);
5852     insert_item(hwnd, 0);
5853 
5854     g_focus_test_LVN_DELETEITEM = TRUE;
5855 
5856     /* delete focused item (not the last index) */
5857     item.stateMask = LVIS_FOCUSED;
5858     item.state = LVIS_FOCUSED;
5859     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 2, (LPARAM)&item);
5860     ok(ret == TRUE, "got %d\n", ret);
5861     ret = SendMessageA(hwnd, LVM_DELETEITEM, 2, 0);
5862     ok(ret == TRUE, "got %d\n", ret);
5863     /* next item gets focus */
5864     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED);
5865     ok(state == LVIS_FOCUSED, "got %x\n", state);
5866 
5867     /* focus last item and delete it */
5868     item.stateMask = LVIS_FOCUSED;
5869     item.state = LVIS_FOCUSED;
5870     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 3, (LPARAM)&item);
5871     ok(ret == TRUE, "got %d\n", ret);
5872     ret = SendMessageA(hwnd, LVM_DELETEITEM, 3, 0);
5873     ok(ret == TRUE, "got %d\n", ret);
5874     /* new last item gets focus */
5875     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 2, LVIS_FOCUSED);
5876     ok(state == LVIS_FOCUSED, "got %x\n", state);
5877 
5878     /* focus first item and delete it */
5879     item.stateMask = LVIS_FOCUSED;
5880     item.state = LVIS_FOCUSED;
5881     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
5882     ok(ret == TRUE, "got %d\n", ret);
5883     ret = SendMessageA(hwnd, LVM_DELETEITEM, 0, 0);
5884     ok(ret == TRUE, "got %d\n", ret);
5885     /* new first item gets focus */
5886     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
5887     ok(state == LVIS_FOCUSED, "got %x\n", state);
5888 
5889     g_focus_test_LVN_DELETEITEM = FALSE;
5890 
5891     DestroyWindow(hwnd);
5892 }
5893 
5894 static void test_insertitem(void)
5895 {
5896     LVITEMA item;
5897     UINT state;
5898     HWND hwnd;
5899     INT ret;
5900 
5901     hwnd = create_listview_control(LVS_REPORT);
5902 
5903     /* insert item 0 focused */
5904     item.mask = LVIF_STATE;
5905     item.state = LVIS_FOCUSED;
5906     item.stateMask = LVIS_FOCUSED;
5907     item.iItem = 0;
5908     item.iSubItem = 0;
5909     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5910     ok(ret == 0, "got %d\n", ret);
5911 
5912     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
5913     ok(state == LVIS_FOCUSED, "got %x\n", state);
5914 
5915     flush_sequences(sequences, NUM_MSG_SEQUENCES);
5916 
5917     /* insert item 1, focus shift */
5918     item.mask = LVIF_STATE;
5919     item.state = LVIS_FOCUSED;
5920     item.stateMask = LVIS_FOCUSED;
5921     item.iItem = 1;
5922     item.iSubItem = 0;
5923     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5924     ok(ret == 1, "got %d\n", ret);
5925 
5926     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_insert_focused_seq, "insert focused", TRUE);
5927 
5928     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
5929     ok(state == LVIS_FOCUSED, "got %x\n", state);
5930 
5931     /* insert item 2, no focus shift */
5932     item.mask = LVIF_STATE;
5933     item.state = 0;
5934     item.stateMask = LVIS_FOCUSED;
5935     item.iItem = 2;
5936     item.iSubItem = 0;
5937     ret = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
5938     ok(ret == 2, "got %d\n", ret);
5939 
5940     state = SendMessageA(hwnd, LVM_GETITEMSTATE, 1, LVIS_FOCUSED);
5941     ok(state == LVIS_FOCUSED, "got %x\n", state);
5942 
5943     DestroyWindow(hwnd);
5944 }
5945 
5946 static void test_header_proc(void)
5947 {
5948     HWND hwnd, header, hdr;
5949     WNDPROC proc1, proc2;
5950 
5951     hwnd = create_listview_control(LVS_REPORT);
5952 
5953     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
5954     ok(header != NULL, "got %p\n", header);
5955 
5956     hdr = CreateWindowExA(0, WC_HEADERA, NULL,
5957 			     WS_BORDER|WS_VISIBLE|HDS_BUTTONS|HDS_HORZ,
5958 			     0, 0, 0, 0,
5959 			     NULL, NULL, NULL, NULL);
5960     ok(hdr != NULL, "got %p\n", hdr);
5961 
5962     proc1 = (WNDPROC)GetWindowLongPtrW(header, GWLP_WNDPROC);
5963     proc2 = (WNDPROC)GetWindowLongPtrW(hdr, GWLP_WNDPROC);
5964     ok(proc1 == proc2, "got %p, expected %p\n", proc1, proc2);
5965 
5966     DestroyWindow(hdr);
5967     DestroyWindow(hwnd);
5968 }
5969 
5970 static void flush_events(void)
5971 {
5972     MSG msg;
5973     int diff = 200;
5974     int min_timeout = 100;
5975     DWORD time = GetTickCount() + diff;
5976 
5977     while (diff > 0)
5978     {
5979         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
5980         while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
5981         diff = time - GetTickCount();
5982     }
5983 }
5984 
5985 static void test_oneclickactivate(void)
5986 {
5987     TRACKMOUSEEVENT track;
5988     char item1[] = "item1";
5989     LVITEMA item;
5990     HWND hwnd, fg;
5991     RECT rect;
5992     INT r;
5993     POINT orig_pos;
5994 
5995     hwnd = CreateWindowExA(0, WC_LISTVIEWA, "foo", WS_VISIBLE|WS_CHILD|LVS_LIST,
5996             10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
5997     ok(hwnd != NULL, "failed to create listview window\n");
5998     r = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_ONECLICKACTIVATE);
5999     ok(r == 0, "should return zero\n");
6000 
6001     SetForegroundWindow(hwndparent);
6002     flush_events();
6003     fg = GetForegroundWindow();
6004     if (fg != hwndparent)
6005     {
6006         skip("Window is not in the foreground. Skipping oneclickactivate tests.\n");
6007         DestroyWindow(hwnd);
6008         return;
6009     }
6010 
6011     item.mask = LVIF_TEXT;
6012     item.iItem = 0;
6013     item.iSubItem = 0;
6014     item.iImage = 0;
6015     item.pszText = item1;
6016     r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
6017     ok(r == 0, "should not fail\n");
6018 
6019     GetWindowRect(hwnd, &rect);
6020     GetCursorPos(&orig_pos);
6021     SetCursorPos(rect.left+5, rect.top+5);
6022     flush_events();
6023     r = SendMessageA(hwnd, WM_MOUSEMOVE, MAKELONG(1, 1), 0);
6024     expect(0, r);
6025 
6026     track.cbSize = sizeof(track);
6027     track.dwFlags = TME_QUERY;
6028     p_TrackMouseEvent(&track);
6029     ok(track.hwndTrack == hwnd, "hwndTrack != hwnd\n");
6030     ok(track.dwFlags == TME_LEAVE, "dwFlags = %x\n", track.dwFlags);
6031 
6032     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
6033     expect(0, r);
6034     r = SendMessageA(hwnd, WM_MOUSEHOVER, MAKELONG(1, 1), 0);
6035     expect(0, r);
6036     r = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
6037     expect(1, r);
6038 
6039     DestroyWindow(hwnd);
6040     SetCursorPos(orig_pos.x, orig_pos.y);
6041 }
6042 
6043 static void test_callback_mask(void)
6044 {
6045     LVITEMA item;
6046     DWORD mask;
6047     HWND hwnd;
6048     BOOL ret;
6049 
6050     hwnd = create_listview_control(LVS_REPORT);
6051 
6052     ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 0);
6053     ok(ret, "got %d\n", ret);
6054 
6055     ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, ~0u, 1);
6056     ok(ret, "got %d\n", ret);
6057 
6058     mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0);
6059     ok(mask == ~0u, "got 0x%08x\n", mask);
6060 
6061     DestroyWindow(hwnd);
6062 
6063     /* LVS_OWNERDATA, mask LVIS_FOCUSED */
6064     hwnd = create_listview_control(LVS_REPORT | LVS_OWNERDATA);
6065 
6066     mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0);
6067     ok(mask == 0, "Unexpected callback mask %#x.\n", mask);
6068 
6069     ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_FOCUSED, 0);
6070     ok(ret, "Failed to set callback mask, %d\n", ret);
6071 
6072     mask = SendMessageA(hwnd, LVM_GETCALLBACKMASK, 0, 0);
6073     ok(mask == LVIS_FOCUSED, "Unexpected callback mask %#x.\n", mask);
6074 
6075     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
6076     ok(ret, "Failed to set item count.\n");
6077 
6078     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6079     ok(ret == -1, "Unexpected selection mark, %d\n", ret);
6080 
6081     item.stateMask = LVIS_FOCUSED;
6082     item.state = LVIS_FOCUSED;
6083     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
6084     ok(ret, "Failed to set item state.\n");
6085 
6086     flush_sequences(sequences, NUM_MSG_SEQUENCES);
6087 
6088     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6089 todo_wine
6090     ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
6091 
6092     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6093 todo_wine
6094     ok(ret == 0, "Unexpected selection mark, %d\n", ret);
6095 
6096     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0);
6097     ok(ret, "Failed to set item count.\n");
6098 
6099     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6100     ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
6101 
6102     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6103     ok(ret == -1, "Unexpected selection mark, %d\n", ret);
6104 
6105     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
6106     ok(ret, "Failed to set item count.\n");
6107 
6108     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6109     ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
6110 
6111     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 1", FALSE);
6112 
6113     /* LVS_OWNDERDATA, empty mask */
6114     ret = SendMessageA(hwnd, LVM_SETCALLBACKMASK, 0, 0);
6115     ok(ret, "Failed to set callback mask, %d\n", ret);
6116 
6117     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
6118     ok(ret, "Failed to set item count.\n");
6119 
6120     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6121     ok(ret == -1, "Unexpected selection mark, %d\n", ret);
6122 
6123     item.stateMask = LVIS_FOCUSED;
6124     item.state = LVIS_FOCUSED;
6125     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
6126     ok(ret, "Failed to set item state.\n");
6127 
6128     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6129     ok(ret == 0, "Unexpected selection mark, %d\n", ret);
6130 
6131     flush_sequences(sequences, NUM_MSG_SEQUENCES);
6132 
6133     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6134     ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
6135 
6136     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 0, 0);
6137     ok(ret, "Failed to set item count.\n");
6138 
6139     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6140     ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
6141 
6142     ret = SendMessageA(hwnd, LVM_GETSELECTIONMARK, 0, 0);
6143 todo_wine
6144     ok(ret == -1, "Unexpected selection mark, %d\n", ret);
6145 
6146     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
6147     ok(ret, "Failed to set item count.\n");
6148 
6149     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6150     ok(ret == -1, "Unexpected focused item, ret %d\n", ret);
6151 
6152     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "parent seq, owner data/focus 2", FALSE);
6153 
6154     /* 2 items, focus on index 0, reduce to 1 item. */
6155     flush_sequences(sequences, NUM_MSG_SEQUENCES);
6156 
6157     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 2, 0);
6158     ok(ret, "Failed to set item count.\n");
6159 
6160     ret = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
6161     ok(ret, "Failed to set item state.\n");
6162 
6163     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6164     ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
6165 
6166     ret = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
6167     ok(ret, "Failed to set item count.\n");
6168 
6169     ret = SendMessageA(hwnd, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
6170     ok(ret == 0, "Unexpected focused item, ret %d\n", ret);
6171 
6172     ok_sequence(sequences, PARENT_SEQ_INDEX, parent_focus_change_ownerdata_seq,
6173         "parent seq, owner data/focus 3", TRUE);
6174 
6175     DestroyWindow(hwnd);
6176 }
6177 
6178 static void test_state_image(void)
6179 {
6180     static const DWORD styles[] =
6181     {
6182         LVS_ICON,
6183         LVS_REPORT,
6184         LVS_SMALLICON,
6185         LVS_LIST,
6186     };
6187     int i;
6188 
6189     for (i = 0; i < sizeof(styles)/sizeof(styles[0]); i++)
6190     {
6191         static char text[] = "Item";
6192         static char subtext[] = "Subitem";
6193         char buff[16];
6194         LVITEMA item;
6195         HWND hwnd;
6196         int r;
6197 
6198         hwnd = create_listview_control(styles[i]);
6199 
6200         insert_column(hwnd, 0);
6201         insert_column(hwnd, 1);
6202 
6203         item.mask = LVIF_TEXT | LVIF_PARAM;
6204         item.iItem = 0;
6205         item.iSubItem = 0;
6206         item.pszText = text;
6207         item.lParam = 123456;
6208         r = SendMessageA(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
6209         ok(r == 0, "Failed to insert an item.\n");
6210 
6211         item.mask = LVIF_STATE;
6212         item.state = INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED;
6213         item.stateMask = LVIS_STATEIMAGEMASK | LVIS_SELECTED | LVIS_FOCUSED;
6214         item.iItem = 0;
6215         item.iSubItem = 0;
6216         r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
6217         ok(r, "Failed to set item state.\n");
6218 
6219         item.mask = LVIF_TEXT;
6220         item.iItem = 0;
6221         item.iSubItem = 1;
6222         item.pszText = subtext;
6223         r = SendMessageA(hwnd, LVM_SETITEMA, 0, (LPARAM)&item);
6224         ok(r, "Failed to set subitem text.\n");
6225 
6226         item.mask = LVIF_STATE | LVIF_PARAM;
6227         item.stateMask = ~0u;
6228         item.state = 0;
6229         item.iItem = 0;
6230         item.iSubItem = 0;
6231         item.lParam = 0;
6232         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6233         ok(r, "Failed to get item state.\n");
6234         ok(item.state == (INDEXTOSTATEIMAGEMASK(1) | LVIS_SELECTED | LVIS_FOCUSED),
6235             "Unexpected item state %#x.\n", item.state);
6236         ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
6237 
6238         item.mask = 0;
6239         item.stateMask = ~0u;
6240         item.state = INDEXTOSTATEIMAGEMASK(2);
6241         item.iItem = 0;
6242         item.iSubItem = 1;
6243         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6244         ok(r, "Failed to get subitem state.\n");
6245         ok(item.state == INDEXTOSTATEIMAGEMASK(2), "Unexpected state %#x.\n", item.state);
6246 
6247         item.mask = LVIF_STATE | LVIF_PARAM;
6248         item.stateMask = ~0u;
6249         item.state = INDEXTOSTATEIMAGEMASK(2);
6250         item.iItem = 0;
6251         item.iSubItem = 1;
6252         item.lParam = 0;
6253         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6254         ok(r, "Failed to get subitem state.\n");
6255         ok(item.state == 0, "Unexpected state %#x.\n", item.state);
6256         ok(item.lParam == 123456, "Unexpected lParam %ld.\n", item.lParam);
6257 
6258         item.mask = LVIF_STATE;
6259         item.stateMask = LVIS_FOCUSED;
6260         item.state = 0;
6261         item.iItem = 0;
6262         item.iSubItem = 1;
6263         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6264         ok(r, "Failed to get subitem state.\n");
6265         ok(item.state == 0, "Unexpected state %#x.\n", item.state);
6266 
6267         item.mask = LVIF_STATE;
6268         item.stateMask = ~0u;
6269         item.state = INDEXTOSTATEIMAGEMASK(2);
6270         item.iItem = 0;
6271         item.iSubItem = 2;
6272         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6273         ok(r, "Failed to get subitem state.\n");
6274     todo_wine
6275         ok(item.state == 0, "Unexpected state %#x.\n", item.state);
6276 
6277         item.mask = LVIF_TEXT;
6278         item.iItem = 0;
6279         item.iSubItem = 1;
6280         item.pszText = buff;
6281         item.cchTextMax = sizeof(buff);
6282         r = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
6283         ok(r, "Failed to get subitem text %d.\n", r);
6284         ok(!strcmp(buff, subtext), "Unexpected subitem text %s.\n", buff);
6285 
6286         DestroyWindow(hwnd);
6287     }
6288 }
6289 
6290 static void test_LVSCW_AUTOSIZE(void)
6291 {
6292     int width, width2;
6293     HWND hwnd;
6294     BOOL ret;
6295 
6296     hwnd = create_listview_control(LVS_REPORT);
6297     ok(hwnd != NULL, "failed to create a listview window\n");
6298 
6299     insert_column(hwnd, 0);
6300     insert_column(hwnd, 1);
6301     insert_item(hwnd, 0);
6302 
6303     ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
6304     ok(ret, "Failed to set column width.\n");
6305 
6306     width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
6307     ok(width > 0, "Unexpected column width %d.\n", width);
6308 
6309     /* Turn on checkboxes. */
6310     ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
6311     ok(ret == 0, "Unexpected previous extended style.\n");
6312 
6313     ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
6314     ok(ret, "Failed to set column width.\n");
6315 
6316     width2 = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
6317     ok(width2 > 0, "Unexpected column width %d.\n", width2);
6318     ok(width2 > width, "Expected increased column width.\n");
6319 
6320     /* Turn off checkboxes. */
6321     ret = SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
6322     ok(ret == LVS_EX_CHECKBOXES, "Unexpected previous extended style.\n");
6323 
6324     ret = SendMessageA(hwnd, LVM_SETCOLUMNWIDTH, 0, LVSCW_AUTOSIZE);
6325     ok(ret, "Failed to set column width.\n");
6326 
6327     width = SendMessageA(hwnd, LVM_GETCOLUMNWIDTH, 0, 0);
6328     ok(width > 0, "Unexpected column width %d.\n", width2);
6329     ok(width2 > width, "Expected reduced column width.\n");
6330 
6331     DestroyWindow(hwnd);
6332 }
6333 
6334 START_TEST(listview)
6335 {
6336     ULONG_PTR ctx_cookie;
6337     HANDLE hCtx;
6338 
6339     init_functions();
6340 
6341     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
6342 
6343     hwndparent = create_parent_window(FALSE);
6344     flush_sequences(sequences, NUM_MSG_SEQUENCES);
6345 
6346     g_is_below_5 = is_below_comctl_5();
6347 
6348     test_header_notification();
6349     test_header_notification2();
6350     test_images();
6351     test_checkboxes();
6352     test_items();
6353     test_create(FALSE);
6354     test_redraw();
6355     test_customdraw();
6356     test_icon_spacing();
6357     test_color();
6358     test_item_count();
6359     test_item_position();
6360     test_columns();
6361     test_getorigin();
6362     test_multiselect();
6363     test_getitemrect();
6364     test_subitem_rect();
6365     test_sorting();
6366     test_ownerdata();
6367     test_norecompute();
6368     test_nosortheader();
6369     test_setredraw();
6370     test_hittest();
6371     test_getviewrect();
6372     test_getitemposition();
6373     test_columnscreation();
6374     test_editbox();
6375     test_notifyformat();
6376     test_indentation();
6377     test_getitemspacing();
6378     test_getcolumnwidth();
6379     test_approximate_viewrect();
6380     test_finditem();
6381     test_hover();
6382     test_destroynotify();
6383     test_createdragimage();
6384     test_dispinfo();
6385     test_LVM_SETITEMTEXT();
6386     test_LVM_REDRAWITEMS();
6387     test_imagelists();
6388     test_deleteitem();
6389     test_insertitem();
6390     test_header_proc();
6391     test_oneclickactivate();
6392     test_callback_mask();
6393     test_state_image();
6394     test_LVSCW_AUTOSIZE();
6395 
6396     if (!load_v6_module(&ctx_cookie, &hCtx))
6397     {
6398         DestroyWindow(hwndparent);
6399         return;
6400     }
6401 
6402     init_functions();
6403 
6404     /* comctl32 version 6 tests start here */
6405     test_get_set_view();
6406     test_canceleditlabel();
6407     test_mapidindex();
6408     test_scrollnotify();
6409     test_LVS_EX_TRANSPARENTBKGND();
6410     test_LVS_EX_HEADERINALLVIEWS();
6411     test_deleteitem();
6412     test_multiselect();
6413     test_insertitem();
6414     test_header_proc();
6415     test_images();
6416     test_checkboxes();
6417     test_items();
6418     test_create(TRUE);
6419     test_color();
6420     test_columns();
6421     test_sorting();
6422     test_ownerdata();
6423     test_norecompute();
6424     test_nosortheader();
6425     test_columnscreation();
6426     test_indentation();
6427     test_finditem();
6428     test_hover();
6429     test_destroynotify();
6430     test_createdragimage();
6431     test_dispinfo();
6432     test_LVM_SETITEMTEXT();
6433     test_LVM_REDRAWITEMS();
6434     test_oneclickactivate();
6435     test_state_image();
6436     test_LVSCW_AUTOSIZE();
6437 
6438     unload_v6_module(ctx_cookie, hCtx);
6439 
6440     DestroyWindow(hwndparent);
6441 }
6442