~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/comctl32/tests/listview.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * ListView tests
  3  *
  4  * Copyright 2006 Mike McCormack for CodeWeavers
  5  * Copyright 2007 George Gov
  6  * Copyright 2009 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 #define PARENT_SEQ_INDEX       0
 32 #define PARENT_FULL_SEQ_INDEX  1
 33 #define LISTVIEW_SEQ_INDEX     2
 34 #define EDITBOX_SEQ_INDEX      3
 35 #define NUM_MSG_SEQUENCES      4
 36 
 37 #define LISTVIEW_ID 0
 38 #define HEADER_ID   1
 39 
 40 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
 41 #define expect2(expected1, expected2, got1, got2) ok(expected1 == got1 && expected2 == got2, \
 42        "expected (%d,%d), got (%d,%d)\n", expected1, expected2, got1, got2)
 43 
 44 static const WCHAR testparentclassW[] =
 45     {'L','i','s','t','v','i','e','w',' ','t','e','s','t',' ','p','a','r','e','n','t','W', 0};
 46 
 47 HWND hwndparent, hwndparentW;
 48 /* prevents edit box creation, LVN_BEGINLABELEDIT return value */
 49 BOOL blockEdit;
 50 /* dumps LVN_ITEMCHANGED message data */
 51 static BOOL g_dump_itemchanged;
 52 /* format reported to control:
 53    -1 falls to defproc, anything else returned */
 54 INT  notifyFormat;
 55 /* indicates we're running < 5.80 version */
 56 BOOL g_is_below_5;
 57 
 58 static HWND subclass_editbox(HWND hwndListview);
 59 
 60 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
 61 
 62 static const struct message create_ownerdrawfixed_parent_seq[] = {
 63     { WM_NOTIFYFORMAT, sent },
 64     { WM_QUERYUISTATE, sent|optional }, /* Win2K and higher */
 65     { WM_MEASUREITEM, sent },
 66     { WM_PARENTNOTIFY, sent },
 67     { 0 }
 68 };
 69 
 70 static const struct message redraw_listview_seq[] = {
 71     { WM_PAINT,      sent|id,            0, 0, LISTVIEW_ID },
 72     { WM_PAINT,      sent|id,            0, 0, HEADER_ID },
 73     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, HEADER_ID },
 74     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, HEADER_ID },
 75     { WM_NOTIFY,     sent|id|defwinproc, 0, 0, LISTVIEW_ID },
 76     { WM_NCPAINT,    sent|id|defwinproc, 0, 0, LISTVIEW_ID },
 77     { WM_ERASEBKGND, sent|id|defwinproc|optional, 0, 0, LISTVIEW_ID },
 78     { 0 }
 79 };
 80 
 81 static const struct message listview_icon_spacing_seq[] = {
 82     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(20, 30) },
 83     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(25, 35) },
 84     { LVM_SETICONSPACING, sent|lparam, 0, MAKELPARAM(-1, -1) },
 85     { 0 }
 86 };
 87 
 88 static const struct message listview_color_seq[] = {
 89     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(0,0,0) },
 90     { LVM_GETBKCOLOR,     sent },
 91     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(0,0,0) },
 92     { LVM_GETTEXTCOLOR,   sent },
 93     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(0,0,0) },
 94     { LVM_GETTEXTBKCOLOR, sent },
 95 
 96     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(100,50,200) },
 97     { LVM_GETBKCOLOR,     sent },
 98     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(100,50,200) },
 99     { LVM_GETTEXTCOLOR,   sent },
100     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(100,50,200) },
101     { LVM_GETTEXTBKCOLOR, sent },
102 
103     { LVM_SETBKCOLOR,     sent|lparam, 0, CLR_NONE },
104     { LVM_GETBKCOLOR,     sent },
105     { LVM_SETTEXTCOLOR,   sent|lparam, 0, CLR_NONE },
106     { LVM_GETTEXTCOLOR,   sent },
107     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, CLR_NONE },
108     { LVM_GETTEXTBKCOLOR, sent },
109 
110     { LVM_SETBKCOLOR,     sent|lparam, 0, RGB(255,255,255) },
111     { LVM_GETBKCOLOR,     sent },
112     { LVM_SETTEXTCOLOR,   sent|lparam, 0, RGB(255,255,255) },
113     { LVM_GETTEXTCOLOR,   sent },
114     { LVM_SETTEXTBKCOLOR, sent|lparam, 0, RGB(255,255,255) },
115     { LVM_GETTEXTBKCOLOR, sent },
116     { 0 }
117 };
118 
119 static const struct message listview_item_count_seq[] = {
120     { LVM_GETITEMCOUNT,   sent },
121     { LVM_INSERTITEM,     sent },
122     { LVM_INSERTITEM,     sent },
123     { LVM_INSERTITEM,     sent },
124     { LVM_GETITEMCOUNT,   sent },
125     { LVM_DELETEITEM,     sent|wparam, 2 },
126     { WM_NCPAINT,         sent|optional },
127     { WM_ERASEBKGND,      sent|optional },
128     { LVM_GETITEMCOUNT,   sent },
129     { LVM_DELETEALLITEMS, sent },
130     { LVM_GETITEMCOUNT,   sent },
131     { LVM_INSERTITEM,     sent },
132     { LVM_INSERTITEM,     sent },
133     { LVM_GETITEMCOUNT,   sent },
134     { LVM_INSERTITEM,     sent },
135     { LVM_GETITEMCOUNT,   sent },
136     { 0 }
137 };
138 
139 static const struct message listview_itempos_seq[] = {
140     { LVM_INSERTITEM,      sent },
141     { LVM_INSERTITEM,      sent },
142     { LVM_INSERTITEM,      sent },
143     { LVM_SETITEMPOSITION, sent|wparam|lparam, 1, MAKELPARAM(10,5) },
144     { WM_NCPAINT,          sent|optional },
145     { WM_ERASEBKGND,       sent|optional },
146     { LVM_GETITEMPOSITION, sent|wparam,        1 },
147     { LVM_SETITEMPOSITION, sent|wparam|lparam, 2, MAKELPARAM(0,0) },
148     { LVM_GETITEMPOSITION, sent|wparam,        2 },
149     { LVM_SETITEMPOSITION, sent|wparam|lparam, 0, MAKELPARAM(20,20) },
150     { LVM_GETITEMPOSITION, sent|wparam,        0 },
151     { 0 }
152 };
153 
154 static const struct message listview_ownerdata_switchto_seq[] = {
155     { WM_STYLECHANGING,    sent },
156     { WM_STYLECHANGED,     sent },
157     { 0 }
158 };
159 
160 static const struct message listview_getorderarray_seq[] = {
161     { LVM_GETCOLUMNORDERARRAY, sent|id|wparam, 2, 0, LISTVIEW_ID },
162     { HDM_GETORDERARRAY,       sent|id|wparam, 2, 0, HEADER_ID },
163     { 0 }
164 };
165 
166 static const struct message empty_seq[] = {
167     { 0 }
168 };
169 
170 static const struct message forward_erasebkgnd_parent_seq[] = {
171     { WM_ERASEBKGND, sent },
172     { 0 }
173 };
174 
175 static const struct message ownderdata_select_focus_parent_seq[] = {
176     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
177     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
178     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA }, /* version 4.7x */
179     { 0 }
180 };
181 
182 static const struct message ownerdata_setstate_all_parent_seq[] = {
183     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
184     { 0 }
185 };
186 
187 static const struct message ownerdata_defocus_all_parent_seq[] = {
188     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
189     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
190     { WM_NOTIFY, sent|id|optional, 0, 0, LVN_GETDISPINFOA },
191     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
192     { 0 }
193 };
194 
195 static const struct message ownerdata_deselect_all_parent_seq[] = {
196     { WM_NOTIFY, sent|id, 0, 0, LVN_ODCACHEHINT },
197     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
198     { 0 }
199 };
200 
201 static const struct message select_all_parent_seq[] = {
202     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
203     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
204 
205     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
206     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
207 
208     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
209     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
210 
211     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
212     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
213 
214     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
215     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED },
216     { 0 }
217 };
218 
219 static const struct message textcallback_set_again_parent_seq[] = {
220     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGING },
221     { WM_NOTIFY, sent|id, 0, 0, LVN_ITEMCHANGED  },
222     { 0 }
223 };
224 
225 static const struct message single_getdispinfo_parent_seq[] = {
226     { WM_NOTIFY, sent|id, 0, 0, LVN_GETDISPINFOA },
227     { 0 }
228 };
229 
230 static const struct message getitemposition_seq1[] = {
231     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
232     { 0 }
233 };
234 
235 static const struct message getitemposition_seq2[] = {
236     { LVM_GETITEMPOSITION, sent|id, 0, 0, LISTVIEW_ID },
237     { HDM_GETITEMRECT, sent|id, 0, 0, HEADER_ID },
238     { 0 }
239 };
240 
241 static const struct message editbox_create_pos[] = {
242     /* sequence sent after LVN_BEGINLABELEDIT */
243     /* next two are 4.7x specific */
244     { WM_WINDOWPOSCHANGING, sent },
245     { WM_WINDOWPOSCHANGED, sent|optional },
246 
247     { WM_WINDOWPOSCHANGING, sent|optional },
248     { WM_NCCALCSIZE, sent },
249     { WM_WINDOWPOSCHANGED, sent },
250     { WM_MOVE, sent|defwinproc },
251     { WM_SIZE, sent|defwinproc },
252     /* the rest is todo, skipped in 4.7x */
253     { WM_WINDOWPOSCHANGING, sent|optional },
254     { WM_WINDOWPOSCHANGED, sent|optional },
255     { 0 }
256 };
257 
258 static const struct message scroll_parent_seq[] = {
259     { WM_NOTIFY, sent|id, 0, 0, LVN_BEGINSCROLL },
260     { WM_NOTIFY, sent|id, 0, 0, LVN_ENDSCROLL },
261     { 0 }
262 };
263 
264 static const struct message setredraw_seq[] = {
265     { WM_SETREDRAW, sent|id|wparam, FALSE, 0, LISTVIEW_ID },
266     { 0 }
267 };
268 
269 static const struct message lvs_ex_transparentbkgnd_seq[] = {
270     { WM_PRINTCLIENT, sent|lparam, 0, PRF_ERASEBKGND },
271     { 0 }
272 };
273 
274 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
275 {
276     static LONG defwndproc_counter = 0;
277     LRESULT ret;
278     struct message msg;
279 
280     msg.message = message;
281     msg.flags = sent|wparam|lparam;
282     if (defwndproc_counter) msg.flags |= defwinproc;
283     msg.wParam = wParam;
284     msg.lParam = lParam;
285     if (message == WM_NOTIFY && lParam) msg.id = ((NMHDR*)lParam)->code;
286 
287     /* log system messages, except for painting */
288     if (message < WM_USER &&
289         message != WM_PAINT &&
290         message != WM_ERASEBKGND &&
291         message != WM_NCPAINT &&
292         message != WM_NCHITTEST &&
293         message != WM_GETTEXT &&
294         message != WM_GETICON &&
295         message != WM_DEVICECHANGE)
296     {
297         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
298 
299         add_message(sequences, PARENT_SEQ_INDEX, &msg);
300     }
301     add_message(sequences, PARENT_FULL_SEQ_INDEX, &msg);
302 
303     switch (message)
304     {
305       case WM_NOTIFY:
306       {
307           switch (((NMHDR*)lParam)->code)
308           {
309           case LVN_BEGINLABELEDIT:
310               /* subclass edit box */
311               if (!blockEdit)
312                   subclass_editbox(((NMHDR*)lParam)->hwndFrom);
313 
314               return blockEdit;
315 
316           case LVN_ENDLABELEDIT:
317               /* always accept new item text */
318               return TRUE;
319           case LVN_BEGINSCROLL:
320           case LVN_ENDSCROLL:
321               {
322               NMLVSCROLL *pScroll = (NMLVSCROLL*)lParam;
323 
324               trace("LVN_%sSCROLL: (%d,%d)\n", pScroll->hdr.code == LVN_BEGINSCROLL ?
325                                                "BEGIN" : "END", pScroll->dx, pScroll->dy);
326               }
327               break;
328           case LVN_ITEMCHANGED:
329               if (g_dump_itemchanged)
330               {
331                   NMLISTVIEW *nmlv = (NMLISTVIEW*)lParam;
332                   trace("LVN_ITEMCHANGED: item=%d,new=%x,old=%x,changed=%x\n",
333                          nmlv->iItem, nmlv->uNewState, nmlv->uOldState, nmlv->uChanged);
334               }
335               break;
336           }
337           break;
338       }
339       case WM_NOTIFYFORMAT:
340       {
341           /* force to return format */
342           if (lParam == NF_QUERY && notifyFormat != -1) return notifyFormat;
343           break;
344       }
345     }
346 
347     defwndproc_counter++;
348     ret = DefWindowProcA(hwnd, message, wParam, lParam);
349     defwndproc_counter--;
350 
351     return ret;
352 }
353 
354 static BOOL register_parent_wnd_class(BOOL Unicode)
355 {
356     WNDCLASSA clsA;
357     WNDCLASSW clsW;
358 
359     if (Unicode)
360     {
361         clsW.style = 0;
362         clsW.lpfnWndProc = parent_wnd_proc;
363         clsW.cbClsExtra = 0;
364         clsW.cbWndExtra = 0;
365         clsW.hInstance = GetModuleHandleW(NULL);
366         clsW.hIcon = 0;
367         clsW.hCursor = LoadCursorA(0, IDC_ARROW);
368         clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
369         clsW.lpszMenuName = NULL;
370         clsW.lpszClassName = testparentclassW;
371     }
372     else
373     {
374         clsA.style = 0;
375         clsA.lpfnWndProc = parent_wnd_proc;
376         clsA.cbClsExtra = 0;
377         clsA.cbWndExtra = 0;
378         clsA.hInstance = GetModuleHandleA(NULL);
379         clsA.hIcon = 0;
380         clsA.hCursor = LoadCursorA(0, IDC_ARROW);
381         clsA.hbrBackground = GetStockObject(WHITE_BRUSH);
382         clsA.lpszMenuName = NULL;
383         clsA.lpszClassName = "Listview test parent class";
384     }
385 
386     return Unicode ? RegisterClassW(&clsW) : RegisterClassA(&clsA);
387 }
388 
389 static HWND create_parent_window(BOOL Unicode)
390 {
391     static const WCHAR nameW[] = {'t','e','s','t','p','a','r','e','n','t','n','a','m','e','W'};
392     HWND hwnd;
393 
394     if (!register_parent_wnd_class(Unicode))
395         return NULL;
396 
397     blockEdit = FALSE;
398     notifyFormat = -1;
399 
400     if (Unicode)
401         hwnd = CreateWindowExW(0, testparentclassW, nameW,
402                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
403                                WS_MAXIMIZEBOX | WS_VISIBLE,
404                                0, 0, 100, 100,
405                                GetDesktopWindow(), NULL, GetModuleHandleW(NULL), NULL);
406     else
407         hwnd = CreateWindowExA(0, "Listview test parent class",
408                                "Listview test parent window",
409                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
410                                WS_MAXIMIZEBOX | WS_VISIBLE,
411                                0, 0, 100, 100,
412                                GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
413     SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
414     return hwnd;
415 }
416 
417 static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
418 {
419     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
420     static LONG defwndproc_counter = 0;
421     LRESULT ret;
422     struct message msg;
423 
424     trace("listview: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
425 
426     /* some debug output for style changing */
427     if ((message == WM_STYLECHANGING ||
428          message == WM_STYLECHANGED) && lParam)
429     {
430         STYLESTRUCT *style = (STYLESTRUCT*)lParam;
431         trace("\told style: 0x%08x, new style: 0x%08x\n", style->styleOld, style->styleNew);
432     }
433 
434     msg.message = message;
435     msg.flags = sent|wparam|lparam;
436     if (defwndproc_counter) msg.flags |= defwinproc;
437     msg.wParam = wParam;
438     msg.lParam = lParam;
439     msg.id = LISTVIEW_ID;
440     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
441 
442     defwndproc_counter++;
443     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
444     defwndproc_counter--;
445     return ret;
446 }
447 
448 static HWND create_listview_control(DWORD style)
449 {
450     WNDPROC oldproc;
451     HWND hwnd;
452     RECT rect;
453 
454     GetClientRect(hwndparent, &rect);
455     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
456                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
457                            0, 0, rect.right, rect.bottom,
458                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
459     ok(hwnd != NULL, "gle=%d\n", GetLastError());
460 
461     if (!hwnd) return NULL;
462 
463     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
464                                         (LONG_PTR)listview_subclass_proc);
465     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
466 
467     return hwnd;
468 }
469 
470 /* unicode listview window with specified parent */
471 static HWND create_listview_controlW(DWORD style, HWND parent)
472 {
473     WNDPROC oldproc;
474     HWND hwnd;
475     RECT rect;
476     static const WCHAR nameW[] = {'f','o','o',0};
477 
478     GetClientRect(parent, &rect);
479     hwnd = CreateWindowExW(0, WC_LISTVIEWW, nameW,
480                            WS_CHILD | WS_BORDER | WS_VISIBLE | LVS_REPORT | style,
481                            0, 0, rect.right, rect.bottom,
482                            parent, NULL, GetModuleHandleW(NULL), NULL);
483     ok(hwnd != NULL, "gle=%d\n", GetLastError());
484 
485     if (!hwnd) return NULL;
486 
487     oldproc = (WNDPROC)SetWindowLongPtrW(hwnd, GWLP_WNDPROC,
488                                         (LONG_PTR)listview_subclass_proc);
489     SetWindowLongPtrW(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
490 
491     return hwnd;
492 }
493 
494 static HWND create_custom_listview_control(DWORD style)
495 {
496     WNDPROC oldproc;
497     HWND hwnd;
498     RECT rect;
499 
500     GetClientRect(hwndparent, &rect);
501     hwnd = CreateWindowExA(0, WC_LISTVIEW, "foo",
502                            WS_CHILD | WS_BORDER | WS_VISIBLE | style,
503                            0, 0, rect.right, rect.bottom,
504                            hwndparent, NULL, GetModuleHandleA(NULL), NULL);
505     ok(hwnd != NULL, "gle=%d\n", GetLastError());
506 
507     if (!hwnd) return NULL;
508 
509     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
510                                          (LONG_PTR)listview_subclass_proc);
511     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
512 
513     return hwnd;
514 }
515 
516 static LRESULT WINAPI header_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
517 {
518     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
519     static LONG defwndproc_counter = 0;
520     LRESULT ret;
521     struct message msg;
522 
523     trace("header: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
524 
525     msg.message = message;
526     msg.flags = sent|wparam|lparam;
527     if (defwndproc_counter) msg.flags |= defwinproc;
528     msg.wParam = wParam;
529     msg.lParam = lParam;
530     msg.id = HEADER_ID;
531     add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
532 
533     defwndproc_counter++;
534     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
535     defwndproc_counter--;
536     return ret;
537 }
538 
539 static HWND subclass_header(HWND hwndListview)
540 {
541     WNDPROC oldproc;
542     HWND hwnd;
543 
544     hwnd = ListView_GetHeader(hwndListview);
545     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
546                                          (LONG_PTR)header_subclass_proc);
547     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
548 
549     return hwnd;
550 }
551 
552 static LRESULT WINAPI editbox_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
553 {
554     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
555     static LONG defwndproc_counter = 0;
556     LRESULT ret;
557     struct message msg;
558 
559     msg.message = message;
560     msg.flags = sent|wparam|lparam;
561     if (defwndproc_counter) msg.flags |= defwinproc;
562     msg.wParam = wParam;
563     msg.lParam = lParam;
564 
565     /* all we need is sizing */
566     if (message == WM_WINDOWPOSCHANGING ||
567         message == WM_NCCALCSIZE ||
568         message == WM_WINDOWPOSCHANGED ||
569         message == WM_MOVE ||
570         message == WM_SIZE)
571     {
572         add_message(sequences, EDITBOX_SEQ_INDEX, &msg);
573     }
574 
575     defwndproc_counter++;
576     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
577     defwndproc_counter--;
578     return ret;
579 }
580 
581 static HWND subclass_editbox(HWND hwndListview)
582 {
583     WNDPROC oldproc;
584     HWND hwnd;
585 
586     hwnd = (HWND)SendMessage(hwndListview, LVM_GETEDITCONTROL, 0, 0);
587     oldproc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC,
588                                          (LONG_PTR)editbox_subclass_proc);
589     SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)oldproc);
590 
591     return hwnd;
592 }
593 
594 /* Performs a single LVM_HITTEST test */
595 static void test_lvm_hittest(HWND hwnd, INT x, INT y, INT item, UINT flags, UINT broken_flags,
596                              BOOL todo_item, BOOL todo_flags, int line)
597 {
598     LVHITTESTINFO lpht;
599     DWORD ret;
600 
601     lpht.pt.x = x;
602     lpht.pt.y = y;
603     lpht.iSubItem = 10;
604 
605     trace("hittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
606     ret = SendMessage(hwnd, LVM_HITTEST, 0, (LPARAM)&lpht);
607 
608     if (todo_item)
609     {
610         todo_wine
611         {
612             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
613             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
614             ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
615         }
616     }
617     else
618     {
619         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
620         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
621         ok_(__FILE__, line)(lpht.iSubItem == 10, "Expected subitem not overwrited\n");
622     }
623 
624     if (todo_flags)
625     {
626         todo_wine
627             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
628     }
629     else if (broken_flags)
630         ok_(__FILE__, line)(lpht.flags == flags || broken(lpht.flags == broken_flags),
631                             "Expected flags %x, got %x\n", flags, lpht.flags);
632     else
633         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
634 }
635 
636 /* Performs a single LVM_SUBITEMHITTEST test */
637 static void test_lvm_subitemhittest(HWND hwnd, INT x, INT y, INT item, INT subitem, UINT flags,
638                                     BOOL todo_item, BOOL todo_subitem, BOOL todo_flags, int line)
639 {
640     LVHITTESTINFO lpht;
641     DWORD ret;
642 
643     lpht.pt.x = x;
644     lpht.pt.y = y;
645 
646     trace("subhittesting pt=(%d,%d)\n", lpht.pt.x, lpht.pt.y);
647     ret = SendMessage(hwnd, LVM_SUBITEMHITTEST, 0, (LPARAM)&lpht);
648 
649     if (todo_item)
650     {
651         todo_wine
652         {
653             ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
654             ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
655         }
656     }
657     else
658     {
659         ok_(__FILE__, line)(ret == item, "Expected %d item, got %d\n", item, ret);
660         ok_(__FILE__, line)(lpht.iItem == item, "Expected %d item, got %d\n", item, lpht.iItem);
661     }
662 
663     if (todo_subitem)
664     {
665         todo_wine
666             ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
667     }
668     else
669         ok_(__FILE__, line)(lpht.iSubItem == subitem, "Expected subitem %d, got %d\n", subitem, lpht.iSubItem);
670 
671     if (todo_flags)
672     {
673         todo_wine
674             ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
675     }
676     else
677         ok_(__FILE__, line)(lpht.flags == flags, "Expected flags %x, got %x\n", flags, lpht.flags);
678 }
679 
680 static void test_images(void)
681 {
682     HWND hwnd;
683     DWORD r;
684     LVITEM item;
685     HIMAGELIST himl;
686     HBITMAP hbmp;
687     RECT r1, r2;
688     static CHAR hello[] = "hello";
689 
690     himl = ImageList_Create(40, 40, 0, 4, 4);
691     ok(himl != NULL, "failed to create imagelist\n");
692 
693     hbmp = CreateBitmap(40, 40, 1, 1, NULL);
694     ok(hbmp != NULL, "failed to create bitmap\n");
695 
696     r = ImageList_Add(himl, hbmp, 0);
697     ok(r == 0, "should be zero\n");
698 
699     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_OWNERDRAWFIXED, 
700                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
701     ok(hwnd != NULL, "failed to create listview window\n");
702 
703     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
704                     LVS_EX_UNDERLINEHOT | LVS_EX_FLATSB | LVS_EX_ONECLICKACTIVATE);
705 
706     ok(r == 0, "should return zero\n");
707 
708     r = SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)himl);
709     ok(r == 0, "should return zero\n");
710 
711     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELONG(100,50));
712     /* returns dimensions */
713 
714     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
715     ok(r == 0, "should be zero items\n");
716 
717     item.mask = LVIF_IMAGE | LVIF_TEXT;
718     item.iItem = 0;
719     item.iSubItem = 1;
720     item.iImage = 0;
721     item.pszText = 0;
722     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
723     ok(r == -1, "should fail\n");
724 
725     item.iSubItem = 0;
726     item.pszText = hello;
727     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
728     ok(r == 0, "should not fail\n");
729 
730     memset(&r1, 0, sizeof r1);
731     r1.left = LVIR_ICON;
732     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r1);
733 
734     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
735     ok(r == TRUE, "should not fail\n");
736 
737     item.iSubItem = 0;
738     item.pszText = hello;
739     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
740     ok(r == 0, "should not fail\n");
741 
742     memset(&r2, 0, sizeof r2);
743     r2.left = LVIR_ICON;
744     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM) &r2);
745 
746     ok(!memcmp(&r1, &r2, sizeof r1), "rectangle should be the same\n");
747 
748     DestroyWindow(hwnd);
749 }
750 
751 static void test_checkboxes(void)
752 {
753     HWND hwnd;
754     LVITEMA item;
755     DWORD r;
756     static CHAR text[]  = "Text",
757                 text2[] = "Text2",
758                 text3[] = "Text3";
759 
760     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT, 
761                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
762     ok(hwnd != NULL, "failed to create listview window\n");
763 
764     /* first without LVS_EX_CHECKBOXES set and an item and check that state is preserved */
765     item.mask = LVIF_TEXT | LVIF_STATE;
766     item.stateMask = 0xffff;
767     item.state = 0xfccc;
768     item.iItem = 0;
769     item.iSubItem = 0;
770     item.pszText = text;
771     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
772     ok(r == 0, "ret %d\n", r);
773 
774     item.iItem = 0;
775     item.mask = LVIF_STATE;
776     item.stateMask = 0xffff;
777     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
778     ok(item.state == 0xfccc, "state %x\n", item.state);
779 
780     /* Don't set LVIF_STATE */
781     item.mask = LVIF_TEXT;
782     item.stateMask = 0xffff;
783     item.state = 0xfccc;
784     item.iItem = 1;
785     item.iSubItem = 0;
786     item.pszText = text;
787     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
788     ok(r == 1, "ret %d\n", r);
789 
790     item.iItem = 1;
791     item.mask = LVIF_STATE;
792     item.stateMask = 0xffff;
793     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
794     ok(item.state == 0, "state %x\n", item.state);
795 
796     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
797     ok(r == 0, "should return zero\n");
798 
799     /* Having turned on checkboxes, check that all existing items are set to 0x1000 (unchecked) */
800     item.iItem = 0;
801     item.mask = LVIF_STATE;
802     item.stateMask = 0xffff;
803     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
804     if (item.state != 0x1ccc)
805     {
806         win_skip("LVS_EX_CHECKBOXES style is unavailable. Skipping.\n");
807         DestroyWindow(hwnd);
808         return;
809     }
810 
811     /* Now add an item without specifying a state and check that its state goes to 0x1000 */
812     item.iItem = 2;
813     item.mask = LVIF_TEXT;
814     item.state = 0;
815     item.pszText = text2;
816     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
817     ok(r == 2, "ret %d\n", r);
818 
819     item.iItem = 2;
820     item.mask = LVIF_STATE;
821     item.stateMask = 0xffff;
822     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
823     ok(item.state == 0x1000, "state %x\n", item.state);
824 
825     /* Add a further item this time specifying a state and still its state goes to 0x1000 */
826     item.iItem = 3;
827     item.mask = LVIF_TEXT | LVIF_STATE;
828     item.stateMask = 0xffff;
829     item.state = 0x2aaa;
830     item.pszText = text3;
831     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
832     ok(r == 3, "ret %d\n", r);
833 
834     item.iItem = 3;
835     item.mask = LVIF_STATE;
836     item.stateMask = 0xffff;
837     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
838     ok(item.state == 0x1aaa, "state %x\n", item.state);
839 
840     /* Set an item's state to checked */
841     item.iItem = 3;
842     item.mask = LVIF_STATE;
843     item.stateMask = 0xf000;
844     item.state = 0x2000;
845     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
846 
847     item.iItem = 3;
848     item.mask = LVIF_STATE;
849     item.stateMask = 0xffff;
850     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
851     ok(item.state == 0x2aaa, "state %x\n", item.state);
852 
853     /* Check that only the bits we asked for are returned,
854      * and that all the others are set to zero
855      */
856     item.iItem = 3;
857     item.mask = LVIF_STATE;
858     item.stateMask = 0xf000;
859     item.state = 0xffff;
860     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
861     ok(item.state == 0x2000, "state %x\n", item.state);
862 
863     /* Set the style again and check that doesn't change an item's state */
864     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
865     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
866 
867     item.iItem = 3;
868     item.mask = LVIF_STATE;
869     item.stateMask = 0xffff;
870     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
871     ok(item.state == 0x2aaa, "state %x\n", item.state);
872 
873     /* Unsetting the checkbox extended style doesn't change an item's state */
874     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, 0);
875     ok(r == LVS_EX_CHECKBOXES, "ret %x\n", r);
876 
877     item.iItem = 3;
878     item.mask = LVIF_STATE;
879     item.stateMask = 0xffff;
880     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
881     ok(item.state == 0x2aaa, "state %x\n", item.state);
882 
883     /* Now setting the style again will change an item's state */
884     r = SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
885     ok(r == 0, "ret %x\n", r);
886 
887     item.iItem = 3;
888     item.mask = LVIF_STATE;
889     item.stateMask = 0xffff;
890     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
891     ok(item.state == 0x1aaa, "state %x\n", item.state);
892 
893     /* Toggle checkbox tests (bug 9934) */
894     memset (&item, 0xcc, sizeof(item));
895     item.mask = LVIF_STATE;
896     item.iItem = 3;
897     item.iSubItem = 0;
898     item.state = LVIS_FOCUSED;
899     item.stateMask = LVIS_FOCUSED;
900     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
901     expect(1, r);
902 
903     item.iItem = 3;
904     item.mask = LVIF_STATE;
905     item.stateMask = 0xffff;
906     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
907     ok(item.state == 0x1aab, "state %x\n", item.state);
908 
909     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
910     expect(0, r);
911     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
912     expect(0, r);
913 
914     item.iItem = 3;
915     item.mask = LVIF_STATE;
916     item.stateMask = 0xffff;
917     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
918     ok(item.state == 0x2aab, "state %x\n", item.state);
919 
920     r = SendMessage(hwnd, WM_KEYDOWN, VK_SPACE, 0);
921     expect(0, r);
922     r = SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0);
923     expect(0, r);
924 
925     item.iItem = 3;
926     item.mask = LVIF_STATE;
927     item.stateMask = 0xffff;
928     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
929     ok(item.state == 0x1aab, "state %x\n", item.state);
930 
931     DestroyWindow(hwnd);
932 }
933 
934 static void insert_column(HWND hwnd, int idx)
935 {
936     LVCOLUMN column;
937     DWORD rc;
938 
939     memset(&column, 0xcc, sizeof(column));
940     column.mask = LVCF_SUBITEM;
941     column.iSubItem = idx;
942 
943     rc = ListView_InsertColumn(hwnd, idx, &column);
944     expect(idx, rc);
945 }
946 
947 static void insert_item(HWND hwnd, int idx)
948 {
949     static CHAR text[] = "foo";
950 
951     LVITEMA item;
952     DWORD rc;
953 
954     memset(&item, 0xcc, sizeof (item));
955     item.mask = LVIF_TEXT;
956     item.iItem = idx;
957     item.iSubItem = 0;
958     item.pszText = text;
959 
960     rc = ListView_InsertItem(hwnd, &item);
961     expect(idx, rc);
962 }
963 
964 static void test_items(void)
965 {
966     const LPARAM lparamTest = 0x42;
967     HWND hwnd;
968     LVITEMA item;
969     DWORD r;
970     static CHAR text[] = "Text";
971 
972     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
973                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
974     ok(hwnd != NULL, "failed to create listview window\n");
975 
976     /*
977      * Test setting/getting item params
978      */
979 
980     /* Set up two columns */
981     insert_column(hwnd, 0);
982     insert_column(hwnd, 1);
983 
984     /* LVIS_SELECTED with zero stateMask */
985     /* set */
986     memset (&item, 0, sizeof (item));
987     item.mask = LVIF_STATE;
988     item.state = LVIS_SELECTED;
989     item.stateMask = 0;
990     item.iItem = 0;
991     item.iSubItem = 0;
992     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
993     ok(r == 0, "ret %d\n", r);
994     /* get */
995     memset (&item, 0xcc, sizeof (item));
996     item.mask = LVIF_STATE;
997     item.stateMask = LVIS_SELECTED;
998     item.state = 0;
999     item.iItem = 0;
1000     item.iSubItem = 0;
1001     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1002     ok(r != 0, "ret %d\n", r);
1003     ok(item.state & LVIS_SELECTED, "Expected LVIS_SELECTED\n");
1004     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1005 
1006     /* LVIS_SELECTED with zero stateMask */
1007     /* set */
1008     memset (&item, 0, sizeof (item));
1009     item.mask = LVIF_STATE;
1010     item.state = LVIS_FOCUSED;
1011     item.stateMask = 0;
1012     item.iItem = 0;
1013     item.iSubItem = 0;
1014     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1015     ok(r == 0, "ret %d\n", r);
1016     /* get */
1017     memset (&item, 0xcc, sizeof (item));
1018     item.mask = LVIF_STATE;
1019     item.stateMask = LVIS_FOCUSED;
1020     item.state = 0;
1021     item.iItem = 0;
1022     item.iSubItem = 0;
1023     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1024     ok(r != 0, "ret %d\n", r);
1025     ok(item.state & LVIS_FOCUSED, "Expected LVIS_FOCUSED\n");
1026     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1027 
1028     /* LVIS_CUT with LVIS_FOCUSED stateMask */
1029     /* set */
1030     memset (&item, 0, sizeof (item));
1031     item.mask = LVIF_STATE;
1032     item.state = LVIS_CUT;
1033     item.stateMask = LVIS_FOCUSED;
1034     item.iItem = 0;
1035     item.iSubItem = 0;
1036     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1037     ok(r == 0, "ret %d\n", r);
1038     /* get */
1039     memset (&item, 0xcc, sizeof (item));
1040     item.mask = LVIF_STATE;
1041     item.stateMask = LVIS_CUT;
1042     item.state = 0;
1043     item.iItem = 0;
1044     item.iSubItem = 0;
1045     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1046     ok(r != 0, "ret %d\n", r);
1047     ok(item.state & LVIS_CUT, "Expected LVIS_CUT\n");
1048     SendMessage(hwnd, LVM_DELETEITEM, 0, 0);
1049 
1050     /* Insert an item with just a param */
1051     memset (&item, 0xcc, sizeof (item));
1052     item.mask = LVIF_PARAM;
1053     item.iItem = 0;
1054     item.iSubItem = 0;
1055     item.lParam = lparamTest;
1056     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1057     ok(r == 0, "ret %d\n", r);
1058 
1059     /* Test getting of the param */
1060     memset (&item, 0xcc, sizeof (item));
1061     item.mask = LVIF_PARAM;
1062     item.iItem = 0;
1063     item.iSubItem = 0;
1064     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1065     ok(r != 0, "ret %d\n", r);
1066     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1067 
1068     /* Set up a subitem */
1069     memset (&item, 0xcc, sizeof (item));
1070     item.mask = LVIF_TEXT;
1071     item.iItem = 0;
1072     item.iSubItem = 1;
1073     item.pszText = text;
1074     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1075     ok(r != 0, "ret %d\n", r);
1076 
1077     /* Query param from subitem: returns main item param */
1078     memset (&item, 0xcc, sizeof (item));
1079     item.mask = LVIF_PARAM;
1080     item.iItem = 0;
1081     item.iSubItem = 1;
1082     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1083     ok(r != 0, "ret %d\n", r);
1084     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1085 
1086     /* Set up param on first subitem: no effect */
1087     memset (&item, 0xcc, sizeof (item));
1088     item.mask = LVIF_PARAM;
1089     item.iItem = 0;
1090     item.iSubItem = 1;
1091     item.lParam = lparamTest+1;
1092     r = SendMessage(hwnd, LVM_SETITEMA, 0, (LPARAM) &item);
1093     ok(r == 0, "ret %d\n", r);
1094 
1095     /* Query param from subitem again: should still return main item param */
1096     memset (&item, 0xcc, sizeof (item));
1097     item.mask = LVIF_PARAM;
1098     item.iItem = 0;
1099     item.iSubItem = 1;
1100     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1101     ok(r != 0, "ret %d\n", r);
1102     ok(item.lParam == lparamTest, "got lParam %lx, expected %lx\n", item.lParam, lparamTest);
1103 
1104     /**** Some tests of state highlighting ****/
1105     memset (&item, 0xcc, sizeof (item));
1106     item.mask = LVIF_STATE;
1107     item.iItem = 0;
1108     item.iSubItem = 0;
1109     item.state = LVIS_SELECTED;
1110     item.stateMask = LVIS_SELECTED | LVIS_DROPHILITED;
1111     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1112     ok(r != 0, "ret %d\n", r);
1113     item.iSubItem = 1;
1114     item.state = LVIS_DROPHILITED;
1115     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM) &item);
1116     ok(r != 0, "ret %d\n", r);
1117 
1118     memset (&item, 0xcc, sizeof (item));
1119     item.mask = LVIF_STATE;
1120     item.iItem = 0;
1121     item.iSubItem = 0;
1122     item.stateMask = -1;
1123     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1124     ok(r != 0, "ret %d\n", r);
1125     ok(item.state == LVIS_SELECTED, "got state %x, expected %x\n", item.state, LVIS_SELECTED);
1126     item.iSubItem = 1;
1127     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
1128     ok(r != 0, "ret %d\n", r);
1129     todo_wine ok(item.state == LVIS_DROPHILITED, "got state %x, expected %x\n", item.state, LVIS_DROPHILITED);
1130 
1131     /* some notnull but meaningless masks */
1132     memset (&item, 0, sizeof(item));
1133     item.mask = LVIF_NORECOMPUTE;
1134     item.iItem = 0;
1135     item.iSubItem = 0;
1136     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1137     ok(r != 0, "ret %d\n", r);
1138     memset (&item, 0, sizeof(item));
1139     item.mask = LVIF_DI_SETITEM;
1140     item.iItem = 0;
1141     item.iSubItem = 0;
1142     r = SendMessage(hwnd, LVM_GETITEMA, 0, (LPARAM) &item);
1143     ok(r != 0, "ret %d\n", r);
1144 
1145     /* set text to callback value already having it */
1146     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1147     expect(TRUE, r);
1148     memset (&item, 0, sizeof (item));
1149     item.mask  = LVIF_TEXT;
1150     item.pszText = LPSTR_TEXTCALLBACK;
1151     item.iItem = 0;
1152     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM) &item);
1153     ok(r == 0, "ret %d\n", r);
1154     memset (&item, 0, sizeof (item));
1155 
1156     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1157 
1158     item.pszText = LPSTR_TEXTCALLBACK;
1159     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0 , (LPARAM) &item);
1160     expect(TRUE, r);
1161 
1162     ok_sequence(sequences, PARENT_SEQ_INDEX, textcallback_set_again_parent_seq,
1163                 "check callback text comparison rule", FALSE);
1164 
1165     DestroyWindow(hwnd);
1166 }
1167 
1168 static void test_columns(void)
1169 {
1170     HWND hwnd, hwndheader;
1171     LVCOLUMN column;
1172     DWORD rc;
1173     INT order[2];
1174 
1175     hwnd = CreateWindowEx(0, "SysListView32", "foo", LVS_REPORT,
1176                 10, 10, 100, 200, hwndparent, NULL, NULL, NULL);
1177     ok(hwnd != NULL, "failed to create listview window\n");
1178 
1179     /* Add a column with no mask */
1180     memset(&column, 0xcc, sizeof(column));
1181     column.mask = 0;
1182     rc = ListView_InsertColumn(hwnd, 0, &column);
1183     ok(rc==0, "Inserting column with no mask failed with %d\n", rc);
1184 
1185     /* Check its width */
1186     rc = ListView_GetColumnWidth(hwnd, 0);
1187     ok(rc==10 ||
1188        broken(rc==0), /* win9x */
1189        "Inserting column with no mask failed to set width to 10 with %d\n", rc);
1190 
1191     DestroyWindow(hwnd);
1192 
1193     /* LVM_GETCOLUMNORDERARRAY */
1194     hwnd = create_listview_control(0);
1195     hwndheader = subclass_header(hwnd);
1196 
1197     memset(&column, 0, sizeof(column));
1198     column.mask = LVCF_WIDTH;
1199     column.cx = 100;
1200     rc = ListView_InsertColumn(hwnd, 0, &column);
1201     ok(rc == 0, "Inserting column failed with %d\n", rc);
1202 
1203     column.cx = 200;
1204     rc = ListView_InsertColumn(hwnd, 1, &column);
1205     ok(rc == 1, "Inserting column failed with %d\n", rc);
1206 
1207     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1208 
1209     rc = SendMessage(hwnd, LVM_GETCOLUMNORDERARRAY, 2, (LPARAM)&order);
1210     ok(rc != 0, "Expected LVM_GETCOLUMNORDERARRAY to succeed\n");
1211     ok(order[0] == 0, "Expected order 0, got %d\n", order[0]);
1212     ok(order[1] == 1, "Expected order 1, got %d\n", order[1]);
1213 
1214     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_getorderarray_seq, "get order array", FALSE);
1215 
1216     DestroyWindow(hwnd);
1217 }
1218 /* test setting imagelist between WM_NCCREATE and WM_CREATE */
1219 static WNDPROC listviewWndProc;
1220 static HIMAGELIST test_create_imagelist;
1221 
1222 static LRESULT CALLBACK create_test_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1223 {
1224     LRESULT ret;
1225 
1226     if (uMsg == WM_CREATE)
1227     {
1228         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
1229         lpcs->style |= LVS_REPORT;
1230     }
1231     ret = CallWindowProc(listviewWndProc, hwnd, uMsg, wParam, lParam);
1232     if (uMsg == WM_CREATE) SendMessage(hwnd, LVM_SETIMAGELIST, 0, (LPARAM)test_create_imagelist);
1233     return ret;
1234 }
1235 
1236 static void test_create(void)
1237 {
1238     HWND hList;
1239     HWND hHeader;
1240     LONG_PTR ret;
1241     LONG r;
1242     LVCOLUMNA col;
1243     RECT rect;
1244     WNDCLASSEX cls;
1245     cls.cbSize = sizeof(WNDCLASSEX);
1246     ok(GetClassInfoEx(GetModuleHandle(NULL), "SysListView32", &cls), "GetClassInfoEx failed\n");
1247     listviewWndProc = cls.lpfnWndProc;
1248     cls.lpfnWndProc = create_test_wndproc;
1249     cls.lpszClassName = "MyListView32";
1250     ok(RegisterClassEx(&cls), "RegisterClassEx failed\n");
1251 
1252     test_create_imagelist = ImageList_Create(16, 16, 0, 5, 10);
1253     hList = CreateWindow("MyListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1254     ok((HIMAGELIST)SendMessage(hList, LVM_GETIMAGELIST, 0, 0) == test_create_imagelist, "Image list not obtained\n");
1255     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1256 
1257     if (!IsWindow(hHeader))
1258     {
1259         /* version 4.0 */
1260         win_skip("LVM_GETHEADER not implemented. Skipping.\n");
1261         DestroyWindow(hList);
1262         return;
1263     }
1264 
1265     ok(IsWindow(hHeader) && IsWindowVisible(hHeader), "Listview not in report mode\n");
1266     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1267     DestroyWindow(hList);
1268 
1269     /* header isn't created on LVS_ICON and LVS_LIST styles */
1270     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1271                           GetModuleHandle(NULL), 0);
1272     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1273     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1274     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1275     /* insert column */
1276     memset(&col, 0, sizeof(LVCOLUMNA));
1277     col.mask = LVCF_WIDTH;
1278     col.cx = 100;
1279     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1280     ok(r == 0, "Expected 0 column's inserted\n");
1281     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1282     ok(IsWindow(hHeader), "Header should be created\n");
1283     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1284     DestroyWindow(hList);
1285 
1286     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1287                           GetModuleHandle(NULL), 0);
1288     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1289     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1290     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1291     /* insert column */
1292     memset(&col, 0, sizeof(LVCOLUMNA));
1293     col.mask = LVCF_WIDTH;
1294     col.cx = 100;
1295     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1296     ok(r == 0, "Expected 0 column's inserted\n");
1297     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1298     ok(IsWindow(hHeader), "Header should be created\n");
1299     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1300     DestroyWindow(hList);
1301 
1302     /* try to switch LVS_ICON -> LVS_REPORT and back LVS_ICON -> LVS_REPORT */
1303     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE, 0, 0, 100, 100, NULL, NULL,
1304                           GetModuleHandle(NULL), 0);
1305     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLongPtr(hList, GWL_STYLE) | LVS_REPORT);
1306     ok(ret & WS_VISIBLE, "Style wrong, should have WS_VISIBLE\n");
1307     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1308     ok(IsWindow(hHeader), "Header should be created\n");
1309     ret = SetWindowLongPtr(hList, GWL_STYLE, GetWindowLong(hList, GWL_STYLE) & ~LVS_REPORT);
1310     ok((ret & WS_VISIBLE) && (ret & LVS_REPORT), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1311     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1312     ok(IsWindow(hHeader), "Header should be created\n");
1313     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1314     DestroyWindow(hList);
1315 
1316     /* try to switch LVS_LIST -> LVS_REPORT and back LVS_LIST -> LVS_REPORT */
1317     hList = CreateWindow("SysListView32", "Test", WS_VISIBLE|LVS_LIST, 0, 0, 100, 100, NULL, NULL,
1318                           GetModuleHandle(NULL), 0);
1319     ret = SetWindowLongPtr(hList, GWL_STYLE,
1320                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_LIST) | LVS_REPORT);
1321     ok(((ret & WS_VISIBLE) && (ret & LVS_LIST)), "Style wrong, should have WS_VISIBLE|LVS_LIST\n");
1322     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1323     ok(IsWindow(hHeader), "Header should be created\n");
1324     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1325     ret = SetWindowLongPtr(hList, GWL_STYLE,
1326                           (GetWindowLongPtr(hList, GWL_STYLE) & ~LVS_REPORT) | LVS_LIST);
1327     ok(((ret & WS_VISIBLE) && (ret & LVS_REPORT)), "Style wrong, should have WS_VISIBLE|LVS_REPORT\n");
1328     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1329     ok(IsWindow(hHeader), "Header should be created\n");
1330     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1331     DestroyWindow(hList);
1332 
1333     /* LVS_REPORT without WS_VISIBLE */
1334     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1335                           GetModuleHandle(NULL), 0);
1336     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1337     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1338     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1339     /* insert column */
1340     memset(&col, 0, sizeof(LVCOLUMNA));
1341     col.mask = LVCF_WIDTH;
1342     col.cx = 100;
1343     r = SendMessage(hList, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
1344     ok(r == 0, "Expected 0 column's inserted\n");
1345     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1346     ok(IsWindow(hHeader), "Header should be created\n");
1347     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1348     DestroyWindow(hList);
1349 
1350     /* LVS_REPORT without WS_VISIBLE, try to show it */
1351     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1352                           GetModuleHandle(NULL), 0);
1353     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1354     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1355     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1356     ShowWindow(hList, SW_SHOW);
1357     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1358     ok(IsWindow(hHeader), "Header should be created\n");
1359     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1360     DestroyWindow(hList);
1361 
1362     /* LVS_REPORT with LVS_NOCOLUMNHEADER */
1363     hList = CreateWindow("SysListView32", "Test", LVS_REPORT|LVS_NOCOLUMNHEADER|WS_VISIBLE,
1364                           0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), 0);
1365     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1366     ok(IsWindow(hHeader), "Header should be created\n");
1367     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1368     /* HDS_DRAGDROP set by default */
1369     ok(GetWindowLongPtr(hHeader, GWL_STYLE) & HDS_DRAGDROP, "Expected header to have HDS_DRAGDROP\n");
1370     DestroyWindow(hList);
1371 
1372     /* setting LVS_EX_HEADERDRAGDROP creates header */
1373     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1374                           GetModuleHandle(NULL), 0);
1375     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1376     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1377     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1378     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1379     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1380     ok(IsWindow(hHeader) ||
1381        broken(!IsWindow(hHeader)), /* 4.7x common controls */
1382        "Header should be created\n");
1383     ok(hHeader == GetDlgItem(hList, 0), "Expected header as dialog item\n");
1384     DestroyWindow(hList);
1385 
1386     /* not report style accepts LVS_EX_HEADERDRAGDROP too */
1387     hList = create_custom_listview_control(0);
1388     SendMessage(hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_HEADERDRAGDROP);
1389     r = SendMessage(hList, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
1390     ok(r & LVS_EX_HEADERDRAGDROP, "Expected LVS_EX_HEADERDRAGDROP to be set\n");
1391     DestroyWindow(hList);
1392 
1393     /* requesting header info with LVM_GETSUBITEMRECT doesn't create it */
1394     hList = CreateWindow("SysListView32", "Test", LVS_REPORT, 0, 0, 100, 100, NULL, NULL,
1395                           GetModuleHandle(NULL), 0);
1396     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1397     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1398 
1399     rect.left = LVIR_BOUNDS;
1400     rect.top  = 1;
1401     rect.right = rect.bottom = -10;
1402     r = SendMessage(hList, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
1403     ok(r != 0, "Expected not-null LRESULT\n");
1404 
1405     hHeader = (HWND)SendMessage(hList, LVM_GETHEADER, 0, 0);
1406     ok(!IsWindow(hHeader), "Header shouldn't be created\n");
1407     ok(NULL == GetDlgItem(hList, 0), "NULL dialog item expected\n");
1408 
1409     DestroyWindow(hList);
1410 
1411     /* WM_MEASUREITEM should be sent when created with LVS_OWNERDRAWFIXED */
1412     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1413     hList = create_listview_control(LVS_OWNERDRAWFIXED);
1414     ok_sequence(sequences, PARENT_SEQ_INDEX, create_ownerdrawfixed_parent_seq,
1415                 "created with LVS_OWNERDRAWFIXED|LVS_REPORT - parent seq", FALSE);
1416     DestroyWindow(hList);
1417 }
1418 
1419 static void test_redraw(void)
1420 {
1421     HWND hwnd, hwndheader;
1422     HDC hdc;
1423     BOOL res;
1424     DWORD r;
1425 
1426     hwnd = create_listview_control(0);
1427     hwndheader = subclass_header(hwnd);
1428 
1429     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1430 
1431     trace("invalidate & update\n");
1432     InvalidateRect(hwnd, NULL, TRUE);
1433     UpdateWindow(hwnd);
1434     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, redraw_listview_seq, "redraw listview", FALSE);
1435 
1436     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1437 
1438     /* forward WM_ERASEBKGND to parent on CLR_NONE background color */
1439     /* 1. Without backbuffer */
1440     res = ListView_SetBkColor(hwnd, CLR_NONE);
1441     expect(TRUE, res);
1442 
1443     hdc = GetWindowDC(hwndparent);
1444 
1445     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1446     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1447     ok(r != 0, "Expected not zero result\n");
1448     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1449                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1450 
1451     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1452     expect(TRUE, res);
1453 
1454     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1455     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1456     ok(r != 0, "Expected not zero result\n");
1457     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1458                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1459 
1460     /* 2. With backbuffer */
1461     SendMessageA(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER,
1462                                                      LVS_EX_DOUBLEBUFFER);
1463     res = ListView_SetBkColor(hwnd, CLR_NONE);
1464     expect(TRUE, res);
1465 
1466     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1467     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1468     ok(r != 0, "Expected not zero result\n");
1469     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, forward_erasebkgnd_parent_seq,
1470                 "forward WM_ERASEBKGND on CLR_NONE", FALSE);
1471 
1472     res = ListView_SetBkColor(hwnd, CLR_DEFAULT);
1473     expect(TRUE, res);
1474 
1475     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1476     r = SendMessageA(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
1477     todo_wine ok(r != 0, "Expected not zero result\n");
1478     ok_sequence(sequences, PARENT_FULL_SEQ_INDEX, empty_seq,
1479                 "don't forward WM_ERASEBKGND on non-CLR_NONE", FALSE);
1480 
1481     ReleaseDC(hwndparent, hdc);
1482 
1483     DestroyWindow(hwnd);
1484 }
1485 
1486 static LRESULT WINAPI cd_wndproc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
1487 {
1488     COLORREF clr, c0ffee = RGB(0xc0, 0xff, 0xee);
1489 
1490     if(msg == WM_NOTIFY) {
1491         NMHDR *nmhdr = (PVOID)lp;
1492         if(nmhdr->code == NM_CUSTOMDRAW) {
1493             NMLVCUSTOMDRAW *nmlvcd = (PVOID)nmhdr;
1494             trace("NMCUSTOMDRAW (0x%.8x)\n", nmlvcd->nmcd.dwDrawStage);
1495             switch(nmlvcd->nmcd.dwDrawStage) {
1496             case CDDS_PREPAINT:
1497                 SetBkColor(nmlvcd->nmcd.hdc, c0ffee);
1498                 return CDRF_NOTIFYITEMDRAW;
1499             case CDDS_ITEMPREPAINT:
1500                 nmlvcd->clrTextBk = CLR_DEFAULT;
1501                 return CDRF_NOTIFYSUBITEMDRAW;
1502             case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
1503                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1504                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1505                 return CDRF_NOTIFYPOSTPAINT;
1506             case CDDS_ITEMPOSTPAINT | CDDS_SUBITEM:
1507                 clr = GetBkColor(nmlvcd->nmcd.hdc);
1508                 todo_wine ok(clr == c0ffee, "clr=%.8x\n", clr);
1509                 return CDRF_DODEFAULT;
1510             }
1511             return CDRF_DODEFAULT;
1512         }
1513     }
1514 
1515     return DefWindowProcA(hwnd, msg, wp, lp);
1516 }
1517 
1518 static void test_customdraw(void)
1519 {
1520     HWND hwnd;
1521     WNDPROC oldwndproc;
1522 
1523     hwnd = create_listview_control(0);
1524 
1525     insert_column(hwnd, 0);
1526     insert_column(hwnd, 1);
1527     insert_item(hwnd, 0);
1528 
1529     oldwndproc = (WNDPROC)SetWindowLongPtr(hwndparent, GWLP_WNDPROC,
1530                                            (LONG_PTR)cd_wndproc);
1531 
1532     InvalidateRect(hwnd, NULL, TRUE);
1533     UpdateWindow(hwnd);
1534 
1535     SetWindowLongPtr(hwndparent, GWLP_WNDPROC, (LONG_PTR)oldwndproc);
1536 
1537     DestroyWindow(hwnd);
1538 }
1539 
1540 static void test_icon_spacing(void)
1541 {
1542     /* LVM_SETICONSPACING */
1543     /* note: LVM_SETICONSPACING returns the previous icon spacing if successful */
1544 
1545     HWND hwnd;
1546     WORD w, h;
1547     DWORD r;
1548 
1549     hwnd = create_custom_listview_control(LVS_ICON);
1550     ok(hwnd != NULL, "failed to create a listview window\n");
1551 
1552     r = SendMessage(hwnd, WM_NOTIFYFORMAT, (WPARAM)hwndparent, (LPARAM)NF_REQUERY);
1553     expect(NFR_ANSI, r);
1554 
1555     /* reset the icon spacing to defaults */
1556     SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1557 
1558     /* now we can request what the defaults are */
1559     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1, -1));
1560     w = LOWORD(r);
1561     h = HIWORD(r);
1562 
1563     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1564 
1565     trace("test icon spacing\n");
1566 
1567     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(20, 30));
1568     ok(r == MAKELONG(w, h) ||
1569        broken(r == MAKELONG(w, w)), /* win98 */
1570        "Expected %d, got %d\n", MAKELONG(w, h), r);
1571 
1572     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(25, 35));
1573     if (r == 0)
1574     {
1575         /* version 4.0 */
1576         win_skip("LVM_SETICONSPACING unimplemented. Skipping.\n");
1577         DestroyWindow(hwnd);
1578         return;
1579     }
1580     expect(MAKELONG(20,30), r);
1581 
1582     r = SendMessage(hwnd, LVM_SETICONSPACING, 0, MAKELPARAM(-1,-1));
1583     expect(MAKELONG(25,35), r);
1584 
1585     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_icon_spacing_seq, "test icon spacing seq", FALSE);
1586 
1587     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1588     DestroyWindow(hwnd);
1589 }
1590 
1591 static void test_color(void)
1592 {
1593     /* SETBKCOLOR/GETBKCOLOR, SETTEXTCOLOR/GETTEXTCOLOR, SETTEXTBKCOLOR/GETTEXTBKCOLOR */
1594 
1595     HWND hwnd;
1596     DWORD r;
1597     int i;
1598 
1599     COLORREF color;
1600     COLORREF colors[4] = {RGB(0,0,0), RGB(100,50,200), CLR_NONE, RGB(255,255,255)};
1601 
1602     hwnd = create_listview_control(0);
1603     ok(hwnd != NULL, "failed to create a listview window\n");
1604 
1605     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1606 
1607     trace("test color seq\n");
1608     for (i = 0; i < 4; i++)
1609     {
1610         color = colors[i];
1611 
1612         r = SendMessage(hwnd, LVM_SETBKCOLOR, 0, color);
1613         expect(TRUE, r);
1614         r = SendMessage(hwnd, LVM_GETBKCOLOR, 0, color);
1615         expect(color, r);
1616 
1617         r = SendMessage(hwnd, LVM_SETTEXTCOLOR, 0, color);
1618         expect (TRUE, r);
1619         r = SendMessage(hwnd, LVM_GETTEXTCOLOR, 0, color);
1620         expect(color, r);
1621 
1622         r = SendMessage(hwnd, LVM_SETTEXTBKCOLOR, 0, color);
1623         expect(TRUE, r);
1624         r = SendMessage(hwnd, LVM_GETTEXTBKCOLOR, 0, color);
1625         expect(color, r);
1626     }
1627 
1628     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_color_seq, "test color seq", FALSE);
1629 
1630     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1631     DestroyWindow(hwnd);
1632 }
1633 
1634 static void test_item_count(void)
1635 {
1636     /* LVM_INSERTITEM, LVM_DELETEITEM, LVM_DELETEALLITEMS, LVM_GETITEMCOUNT */
1637 
1638     HWND hwnd;
1639     DWORD r;
1640     HDC hdc;
1641     HFONT hOldFont;
1642     TEXTMETRICA tm;
1643     RECT rect;
1644     INT height;
1645 
1646     LVITEM item0;
1647     LVITEM item1;
1648     LVITEM item2;
1649     static CHAR item0text[] = "item0";
1650     static CHAR item1text[] = "item1";
1651     static CHAR item2text[] = "item2";
1652 
1653     hwnd = create_listview_control(0);
1654     ok(hwnd != NULL, "failed to create a listview window\n");
1655 
1656     /* resize in dpiaware manner to fit all 3 items added */
1657     hdc = GetDC(0);
1658     hOldFont = SelectObject(hdc, GetStockObject(SYSTEM_FONT));
1659     GetTextMetricsA(hdc, &tm);
1660     /* 2 extra pixels for bounds and header border */
1661     height = tm.tmHeight + 2;
1662     SelectObject(hdc, hOldFont);
1663     ReleaseDC(0, hdc);
1664 
1665     GetWindowRect(hwnd, &rect);
1666     /* 3 items + 1 header + 1 to be sure */
1667     MoveWindow(hwnd, 0, 0, rect.right - rect.left, 5 * height, FALSE);
1668 
1669     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1670 
1671     trace("test item count\n");
1672 
1673     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1674     expect(0, r);
1675 
1676     /* [item0] */
1677     item0.mask = LVIF_TEXT;
1678     item0.iItem = 0;
1679     item0.iSubItem = 0;
1680     item0.pszText = item0text;
1681     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1682     expect(0, r);
1683 
1684     /* [item0, item1] */
1685     item1.mask = LVIF_TEXT;
1686     item1.iItem = 1;
1687     item1.iSubItem = 0;
1688     item1.pszText = item1text;
1689     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1690     expect(1, r);
1691 
1692     /* [item0, item1, item2] */
1693     item2.mask = LVIF_TEXT;
1694     item2.iItem = 2;
1695     item2.iSubItem = 0;
1696     item2.pszText = item2text;
1697     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1698     expect(2, r);
1699 
1700     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1701     expect(3, r);
1702 
1703     /* [item0, item1] */
1704     r = SendMessage(hwnd, LVM_DELETEITEM, 2, 0);
1705     expect(TRUE, r);
1706 
1707     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1708     expect(2, r);
1709 
1710     /* [] */
1711     r = SendMessage(hwnd, LVM_DELETEALLITEMS, 0, 0);
1712     expect(TRUE, r);
1713 
1714     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1715     expect(0, r);
1716 
1717     /* [item0] */
1718     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1719     expect(0, r);
1720 
1721     /* [item0, item1] */
1722     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1723     expect(1, r);
1724 
1725     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1726     expect(2, r);
1727 
1728     /* [item0, item1, item2] */
1729     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1730     expect(2, r);
1731 
1732     r = SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1733     expect(3, r);
1734 
1735     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_item_count_seq, "test item count seq", FALSE);
1736 
1737     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1738     DestroyWindow(hwnd);
1739 }
1740 
1741 static void test_item_position(void)
1742 {
1743     /* LVM_SETITEMPOSITION/LVM_GETITEMPOSITION */
1744 
1745     HWND hwnd;
1746     DWORD r;
1747     POINT position;
1748 
1749     LVITEM item0;
1750     LVITEM item1;
1751     LVITEM item2;
1752     static CHAR item0text[] = "item0";
1753     static CHAR item1text[] = "item1";
1754     static CHAR item2text[] = "item2";
1755 
1756     hwnd = create_custom_listview_control(LVS_ICON);
1757     ok(hwnd != NULL, "failed to create a listview window\n");
1758 
1759     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1760 
1761     trace("test item position\n");
1762 
1763     /* [item0] */
1764     item0.mask = LVIF_TEXT;
1765     item0.iItem = 0;
1766     item0.iSubItem = 0;
1767     item0.pszText = item0text;
1768     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item0);
1769     expect(0, r);
1770 
1771     /* [item0, item1] */
1772     item1.mask = LVIF_TEXT;
1773     item1.iItem = 1;
1774     item1.iSubItem = 0;
1775     item1.pszText = item1text;
1776     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item1);
1777     expect(1, r);
1778 
1779     /* [item0, item1, item2] */
1780     item2.mask = LVIF_TEXT;
1781     item2.iItem = 2;
1782     item2.iSubItem = 0;
1783     item2.pszText = item2text;
1784     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item2);
1785     expect(2, r);
1786 
1787     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 1, MAKELPARAM(10,5));
1788     expect(TRUE, r);
1789     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 1, (LPARAM) &position);
1790     expect(TRUE, r);
1791     expect2(10, 5, position.x, position.y);
1792 
1793     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 2, MAKELPARAM(0,0));
1794     expect(TRUE, r);
1795     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 2, (LPARAM) &position);
1796     expect(TRUE, r);
1797     expect2(0, 0, position.x, position.y);
1798 
1799     r = SendMessage(hwnd, LVM_SETITEMPOSITION, 0, MAKELPARAM(20,20));
1800     expect(TRUE, r);
1801     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM) &position);
1802     expect(TRUE, r);
1803     expect2(20, 20, position.x, position.y);
1804 
1805     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_itempos_seq, "test item position seq", TRUE);
1806 
1807     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1808     DestroyWindow(hwnd);
1809 }
1810 
1811 static void test_getorigin(void)
1812 {
1813     /* LVM_GETORIGIN */
1814 
1815     HWND hwnd;
1816     DWORD r;
1817     POINT position;
1818 
1819     position.x = position.y = 0;
1820 
1821     hwnd = create_custom_listview_control(LVS_ICON);
1822     ok(hwnd != NULL, "failed to create a listview window\n");
1823     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1824     trace("test get origin results\n");
1825     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1826     expect(TRUE, r);
1827     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1828     DestroyWindow(hwnd);
1829 
1830     hwnd = create_custom_listview_control(LVS_SMALLICON);
1831     ok(hwnd != NULL, "failed to create a listview window\n");
1832     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1833     trace("test get origin results\n");
1834     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1835     expect(TRUE, r);
1836     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1837     DestroyWindow(hwnd);
1838 
1839     hwnd = create_custom_listview_control(LVS_LIST);
1840     ok(hwnd != NULL, "failed to create a listview window\n");
1841     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1842     trace("test get origin results\n");
1843     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1844     expect(FALSE, r);
1845     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1846     DestroyWindow(hwnd);
1847 
1848     hwnd = create_custom_listview_control(LVS_REPORT);
1849     ok(hwnd != NULL, "failed to create a listview window\n");
1850     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1851     trace("test get origin results\n");
1852     r = SendMessage(hwnd, LVM_GETORIGIN, 0, (LPARAM)&position);
1853     expect(FALSE, r);
1854     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1855     DestroyWindow(hwnd);
1856 
1857 }
1858 
1859 static void test_multiselect(void)
1860 {
1861     typedef struct t_select_task
1862     {
1863         const char *descr;
1864         int initPos;
1865         int loopVK;
1866         int count;
1867         int result;
1868     } select_task;
1869 
1870     HWND hwnd;
1871     DWORD r;
1872     int i,j,item_count,selected_count;
1873     static const int items=5;
1874     BYTE kstate[256];
1875     select_task task;
1876     LONG_PTR style;
1877     LVITEMA item;
1878 
1879     static struct t_select_task task_list[] = {
1880         { "using VK_DOWN", 0, VK_DOWN, -1, -1 },
1881         { "using VK_UP", -1, VK_UP, -1, -1 },
1882         { "using VK_END", 0, VK_END, 1, -1 },
1883         { "using VK_HOME", -1, VK_HOME, 1, -1 }
1884     };
1885 
1886 
1887     hwnd = create_listview_control(0);
1888 
1889     for (i=0;i<items;i++) {
1890             insert_item(hwnd, 0);
1891     }
1892 
1893     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1894 
1895     expect(items,item_count);
1896 
1897     for (i=0;i<4;i++) {
1898         task = task_list[i];
1899 
1900         /* deselect all items */
1901         ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1902         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1903 
1904         /* set initial position */
1905         SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, (task.initPos == -1 ? item_count -1 : task.initPos));
1906         ListView_SetItemState(hwnd,(task.initPos == -1 ? item_count -1 : task.initPos),LVIS_SELECTED ,LVIS_SELECTED);
1907 
1908         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1909 
1910         ok(selected_count == 1, "There should be only one selected item at the beginning (is %d)\n",selected_count);
1911 
1912         /* Set SHIFT key pressed */
1913         GetKeyboardState(kstate);
1914         kstate[VK_SHIFT]=0x80;
1915         SetKeyboardState(kstate);
1916 
1917         for (j=1;j<=(task.count == -1 ? item_count : task.count);j++) {
1918             r = SendMessage(hwnd, WM_KEYDOWN, task.loopVK, 0);
1919             expect(0,r);
1920             r = SendMessage(hwnd, WM_KEYUP, task.loopVK, 0);
1921             expect(0,r);
1922         }
1923 
1924         selected_count = (int)SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1925 
1926         ok((task.result == -1 ? item_count : task.result) == selected_count, "Failed multiple selection %s. There should be %d selected items (is %d)\n", task.descr, item_count, selected_count);
1927 
1928         /* Set SHIFT key released */
1929         GetKeyboardState(kstate);
1930         kstate[VK_SHIFT]=0x00;
1931         SetKeyboardState(kstate);
1932     }
1933     DestroyWindow(hwnd);
1934 
1935     /* make multiple selection, then switch to LVS_SINGLESEL */
1936     hwnd = create_listview_control(0);
1937     for (i=0;i<items;i++) {
1938             insert_item(hwnd, 0);
1939     }
1940     item_count = (int)SendMessage(hwnd, LVM_GETITEMCOUNT, 0, 0);
1941     expect(items,item_count);
1942 
1943     /* try with NULL pointer */
1944     r = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)NULL);
1945     expect(FALSE, r);
1946 
1947     /* select all, check notifications */
1948     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1949 
1950     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1951 
1952     item.stateMask = LVIS_SELECTED;
1953     item.state     = LVIS_SELECTED;
1954     r = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
1955     expect(TRUE, r);
1956 
1957     ok_sequence(sequences, PARENT_SEQ_INDEX, select_all_parent_seq,
1958                 "select all notification", FALSE);
1959 
1960     /* deselect all items */
1961     ListView_SetItemState(hwnd, -1, 0, LVIS_SELECTED);
1962     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
1963     for (i=0;i<3;i++) {
1964         ListView_SetItemState(hwnd, i, LVIS_SELECTED, LVIS_SELECTED);
1965     }
1966 
1967     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1968     expect(3, r);
1969     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1970     expect(-1, r);
1971 
1972     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1973     ok(!(style & LVS_SINGLESEL), "LVS_SINGLESEL isn't expected\n");
1974     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SINGLESEL);
1975     /* check that style is accepted */
1976     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
1977     ok(style & LVS_SINGLESEL, "LVS_SINGLESEL expected\n");
1978 
1979     for (i=0;i<3;i++) {
1980         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1981         ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1982     }
1983     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1984     expect(3, r);
1985     SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
1986     expect(3, r);
1987 
1988     /* select one more */
1989     ListView_SetItemState(hwnd, 3, LVIS_SELECTED, LVIS_SELECTED);
1990 
1991     for (i=0;i<3;i++) {
1992         r = ListView_GetItemState(hwnd, i, LVIS_SELECTED);
1993         ok(!(r & LVIS_SELECTED), "Expected item %d to be unselected\n", i);
1994     }
1995     r = ListView_GetItemState(hwnd, 3, LVIS_SELECTED);
1996     ok(r & LVIS_SELECTED, "Expected item %d to be selected\n", i);
1997 
1998     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
1999     expect(1, r);
2000     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2001     expect(-1, r);
2002 
2003     /* try to select all on LVS_SINGLESEL */
2004     memset(&item, 0, sizeof(item));
2005     item.stateMask = LVIS_SELECTED;
2006     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2007     expect(TRUE, r);
2008     SendMessage(hwnd, LVM_SETSELECTIONMARK, 0, -1);
2009 
2010     item.stateMask = LVIS_SELECTED;
2011     item.state     = LVIS_SELECTED;
2012     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2013     expect(FALSE, r);
2014 
2015     r = ListView_GetSelectedCount(hwnd);
2016     expect(0, r);
2017     r = ListView_GetSelectionMark(hwnd);
2018     expect(-1, r);
2019 
2020     /* try to deselect all on LVS_SINGLESEL */
2021     item.stateMask = LVIS_SELECTED;
2022     item.state     = LVIS_SELECTED;
2023     r = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2024     expect(TRUE, r);
2025 
2026     item.stateMask = LVIS_SELECTED;
2027     item.state     = 0;
2028     r = SendMessage(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2029     expect(TRUE, r);
2030     r = ListView_GetSelectedCount(hwnd);
2031     expect(0, r);
2032 
2033     DestroyWindow(hwnd);
2034 }
2035 
2036 static void test_subitem_rect(void)
2037 {
2038     HWND hwnd;
2039     DWORD r;
2040     LVCOLUMN col;
2041     RECT rect;
2042 
2043     /* test LVM_GETSUBITEMRECT for header */
2044     hwnd = create_listview_control(0);
2045     ok(hwnd != NULL, "failed to create a listview window\n");
2046     /* add some columns */
2047     memset(&col, 0, sizeof(LVCOLUMN));
2048     col.mask = LVCF_WIDTH;
2049     col.cx = 100;
2050     r = -1;
2051     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 0, (LPARAM)&col);
2052     expect(0, r);
2053     col.cx = 150;
2054     r = -1;
2055     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 1, (LPARAM)&col);
2056     expect(1, r);
2057     col.cx = 200;
2058     r = -1;
2059     r = SendMessage(hwnd, LVM_INSERTCOLUMN, 2, (LPARAM)&col);
2060     expect(2, r);
2061     /* item = -1 means header, subitem index is 1 based */
2062     rect.left = LVIR_BOUNDS;
2063     rect.top  = 0;
2064     rect.right = rect.bottom = 0;
2065     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2066     expect(0, r);
2067 
2068     rect.left = LVIR_BOUNDS;
2069     rect.top  = 1;
2070     rect.right = rect.bottom = 0;
2071     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2072 
2073     ok(r != 0, "Expected not-null LRESULT\n");
2074     expect(100, rect.left);
2075     expect(250, rect.right);
2076 todo_wine
2077     expect(3, rect.top);
2078 
2079     rect.left = LVIR_BOUNDS;
2080     rect.top  = 2;
2081     rect.right = rect.bottom = 0;
2082     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2083 
2084     ok(r != 0, "Expected not-null LRESULT\n");
2085     expect(250, rect.left);
2086     expect(450, rect.right);
2087 todo_wine
2088     expect(3, rect.top);
2089 
2090     /* item LVS_REPORT padding isn't applied to subitems */
2091     insert_item(hwnd, 0);
2092 
2093     rect.left = LVIR_BOUNDS;
2094     rect.top  = 1;
2095     rect.right = rect.bottom = 0;
2096     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2097     ok(r != 0, "Expected not-null LRESULT\n");
2098     expect(100, rect.left);
2099     expect(250, rect.right);
2100 
2101     rect.left = LVIR_ICON;
2102     rect.top  = 1;
2103     rect.right = rect.bottom = 0;
2104     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2105     ok(r != 0, "Expected not-null LRESULT\n");
2106     /* no icon attached - zero width rectangle, with no left padding */
2107     expect(100, rect.left);
2108     expect(100, rect.right);
2109 
2110     rect.left = LVIR_LABEL;
2111     rect.top  = 1;
2112     rect.right = rect.bottom = 0;
2113     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, 0, (LPARAM)&rect);
2114     ok(r != 0, "Expected not-null LRESULT\n");
2115     /* same as full LVIR_BOUNDS */
2116     expect(100, rect.left);
2117     expect(250, rect.right);
2118 
2119     DestroyWindow(hwnd);
2120 
2121     /* try it for non LVS_REPORT style */
2122     hwnd = CreateWindow("SysListView32", "Test", LVS_ICON, 0, 0, 100, 100, NULL, NULL,
2123                          GetModuleHandle(NULL), 0);
2124     rect.left = LVIR_BOUNDS;
2125     rect.top  = 1;
2126     rect.right = rect.bottom = -10;
2127     r = SendMessage(hwnd, LVM_GETSUBITEMRECT, -1, (LPARAM)&rect);
2128     ok(r == 0, "Expected not-null LRESULT\n");
2129     /* rect is unchanged */
2130     expect(0, rect.left);
2131     expect(-10, rect.right);
2132     expect(1, rect.top);
2133     expect(-10, rect.bottom);
2134     DestroyWindow(hwnd);
2135 }
2136 
2137 /* comparison callback for test_sorting */
2138 static INT WINAPI test_CallBackCompare(LPARAM first, LPARAM second, LPARAM lParam)
2139 {
2140     if (first == second) return 0;
2141     return (first > second ? 1 : -1);
2142 }
2143 
2144 static void test_sorting(void)
2145 {
2146     HWND hwnd;
2147     LVITEMA item = {0};
2148     DWORD r;
2149     LONG_PTR style;
2150     static CHAR names[][5] = {"A", "B", "C", "D", ""};
2151     CHAR buff[10];
2152 
2153     hwnd = create_listview_control(0);
2154     ok(hwnd != NULL, "failed to create a listview window\n");
2155 
2156     /* insert some items */
2157     item.mask = LVIF_PARAM | LVIF_STATE;
2158     item.state = LVIS_SELECTED;
2159     item.iItem = 0;
2160     item.iSubItem = 0;
2161     item.lParam = 3;
2162     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2163     expect(0, r);
2164 
2165     item.mask = LVIF_PARAM;
2166     item.iItem = 1;
2167     item.iSubItem = 0;
2168     item.lParam = 2;
2169     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2170     expect(1, r);
2171 
2172     item.mask = LVIF_STATE | LVIF_PARAM;
2173     item.state = LVIS_SELECTED;
2174     item.iItem = 2;
2175     item.iSubItem = 0;
2176     item.lParam = 4;
2177     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2178     expect(2, r);
2179 
2180     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2181     expect(-1, r);
2182 
2183     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2184     expect(2, r);
2185 
2186     r = SendMessage(hwnd, LVM_SORTITEMS, 0, (LPARAM)test_CallBackCompare);
2187     expect(TRUE, r);
2188 
2189     r = SendMessage(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2190     expect(2, r);
2191     r = SendMessage(hwnd, LVM_GETSELECTIONMARK, 0, 0);
2192     expect(-1, r);
2193     r = SendMessage(hwnd, LVM_GETITEMSTATE, 0, LVIS_SELECTED);
2194     expect(0, r);
2195     r = SendMessage(hwnd, LVM_GETITEMSTATE, 1, LVIS_SELECTED);
2196     expect(LVIS_SELECTED, r);
2197     r = SendMessage(hwnd, LVM_GETITEMSTATE, 2, LVIS_SELECTED);
2198     expect(LVIS_SELECTED, r);
2199 
2200     DestroyWindow(hwnd);
2201 
2202     /* switch to LVS_SORTASCENDING when some items added */
2203     hwnd = create_listview_control(0);
2204     ok(hwnd != NULL, "failed to create a listview window\n");
2205 
2206     item.mask = LVIF_TEXT;
2207     item.iItem = 0;
2208     item.iSubItem = 0;
2209     item.pszText = names[1];
2210     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2211     expect(0, r);
2212 
2213     item.mask = LVIF_TEXT;
2214     item.iItem = 1;
2215     item.iSubItem = 0;
2216     item.pszText = names[2];
2217     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2218     expect(1, r);
2219 
2220     item.mask = LVIF_TEXT;
2221     item.iItem = 2;
2222     item.iSubItem = 0;
2223     item.pszText = names[0];
2224     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2225     expect(2, r);
2226 
2227     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2228     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2229     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2230     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2231 
2232     /* no sorting performed when switched to LVS_SORTASCENDING */
2233     item.mask = LVIF_TEXT;
2234     item.iItem = 0;
2235     item.pszText = buff;
2236     item.cchTextMax = sizeof(buff);
2237     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2238     expect(TRUE, r);
2239     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2240 
2241     item.iItem = 1;
2242     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2243     expect(TRUE, r);
2244     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2245 
2246     item.iItem = 2;
2247     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2248     expect(TRUE, r);
2249     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2250 
2251     /* adding new item doesn't resort list */
2252     item.mask = LVIF_TEXT;
2253     item.iItem = 3;
2254     item.iSubItem = 0;
2255     item.pszText = names[3];
2256     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2257     expect(3, r);
2258 
2259     item.mask = LVIF_TEXT;
2260     item.iItem = 0;
2261     item.pszText = buff;
2262     item.cchTextMax = sizeof(buff);
2263     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2264     expect(TRUE, r);
2265     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2266 
2267     item.iItem = 1;
2268     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2269     expect(TRUE, r);
2270     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2271 
2272     item.iItem = 2;
2273     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2274     expect(TRUE, r);
2275     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2276 
2277     item.iItem = 3;
2278     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2279     expect(TRUE, r);
2280     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2281 
2282     /* corner case - item should be placed at first position */
2283     item.mask = LVIF_TEXT;
2284     item.iItem = 4;
2285     item.iSubItem = 0;
2286     item.pszText = names[4];
2287     r = SendMessage(hwnd, LVM_INSERTITEM, 0, (LPARAM) &item);
2288     expect(0, r);
2289 
2290     item.iItem = 0;
2291     item.pszText = buff;
2292     item.cchTextMax = sizeof(buff);
2293     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2294     expect(TRUE, r);
2295     ok(lstrcmp(buff, names[4]) == 0, "Expected '%s', got '%s'\n", names[4], buff);
2296 
2297     item.iItem = 1;
2298     item.pszText = buff;
2299     item.cchTextMax = sizeof(buff);
2300     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2301     expect(TRUE, r);
2302     ok(lstrcmp(buff, names[1]) == 0, "Expected '%s', got '%s'\n", names[1], buff);
2303 
2304     item.iItem = 2;
2305     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2306     expect(TRUE, r);
2307     ok(lstrcmp(buff, names[2]) == 0, "Expected '%s', got '%s'\n", names[2], buff);
2308 
2309     item.iItem = 3;
2310     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2311     expect(TRUE, r);
2312     ok(lstrcmp(buff, names[0]) == 0, "Expected '%s', got '%s'\n", names[0], buff);
2313 
2314     item.iItem = 4;
2315     r = SendMessage(hwnd, LVM_GETITEM, 0, (LPARAM) &item);
2316     expect(TRUE, r);
2317     ok(lstrcmp(buff, names[3]) == 0, "Expected '%s', got '%s'\n", names[3], buff);
2318 
2319     DestroyWindow(hwnd);
2320 }
2321 
2322 static void test_ownerdata(void)
2323 {
2324     HWND hwnd;
2325     LONG_PTR style, ret;
2326     DWORD res;
2327     LVITEMA item;
2328 
2329     /* it isn't possible to set LVS_OWNERDATA after creation */
2330     if (g_is_below_5)
2331     {
2332         win_skip("set LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2333     }
2334     else
2335     {
2336         hwnd = create_listview_control(0);
2337         ok(hwnd != NULL, "failed to create a listview window\n");
2338         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2339         ok(!(style & LVS_OWNERDATA) && style, "LVS_OWNERDATA isn't expected\n");
2340 
2341         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2342 
2343         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2344         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2345         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2346                 "try to switch to LVS_OWNERDATA seq", FALSE);
2347 
2348         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2349         ok(!(style & LVS_OWNERDATA), "LVS_OWNERDATA isn't expected\n");
2350         DestroyWindow(hwnd);
2351     }
2352 
2353     /* try to set LVS_OWNERDATA after creation just having it */
2354     hwnd = create_listview_control(LVS_OWNERDATA);
2355     ok(hwnd != NULL, "failed to create a listview window\n");
2356     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2357     ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2358 
2359     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2360 
2361     ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_OWNERDATA);
2362     ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2363     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2364                 "try to switch to LVS_OWNERDATA seq", FALSE);
2365     DestroyWindow(hwnd);
2366 
2367     /* try to remove LVS_OWNERDATA after creation just having it */
2368     if (g_is_below_5)
2369     {
2370         win_skip("remove LVS_OWNERDATA after creation leads to crash on < 5.80\n");
2371     }
2372     else
2373     {
2374         hwnd = create_listview_control(LVS_OWNERDATA);
2375         ok(hwnd != NULL, "failed to create a listview window\n");
2376         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2377         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2378 
2379         flush_sequences(sequences, NUM_MSG_SEQUENCES);
2380 
2381         ret = SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_OWNERDATA);
2382         ok(ret == style, "Expected set GWL_STYLE to succeed\n");
2383         ok_sequence(sequences, LISTVIEW_SEQ_INDEX, listview_ownerdata_switchto_seq,
2384                 "try to switch to LVS_OWNERDATA seq", FALSE);
2385         style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2386         ok(style & LVS_OWNERDATA, "LVS_OWNERDATA is expected\n");
2387         DestroyWindow(hwnd);
2388     }
2389 
2390     /* try select an item */
2391     hwnd = create_listview_control(LVS_OWNERDATA);
2392     ok(hwnd != NULL, "failed to create a listview window\n");
2393     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2394     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2395     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2396     expect(0, res);
2397     memset(&item, 0, sizeof(item));
2398     item.stateMask = LVIS_SELECTED;
2399     item.state     = LVIS_SELECTED;
2400     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2401     expect(TRUE, res);
2402     res = SendMessageA(hwnd, LVM_GETSELECTEDCOUNT, 0, 0);
2403     expect(1, res);
2404     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2405     expect(1, res);
2406     DestroyWindow(hwnd);
2407 
2408     /* LVM_SETITEM is unsupported on LVS_OWNERDATA */
2409     hwnd = create_listview_control(LVS_OWNERDATA);
2410     ok(hwnd != NULL, "failed to create a listview window\n");
2411     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2412     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2413     res = SendMessageA(hwnd, LVM_GETITEMCOUNT, 0, 0);
2414     expect(1, res);
2415     memset(&item, 0, sizeof(item));
2416     item.mask = LVIF_STATE;
2417     item.iItem = 0;
2418     item.stateMask = LVIS_SELECTED;
2419     item.state     = LVIS_SELECTED;
2420     res = SendMessageA(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2421     expect(FALSE, res);
2422     DestroyWindow(hwnd);
2423 
2424     /* check notifications after focused/selected changed */
2425     hwnd = create_listview_control(LVS_OWNERDATA);
2426     ok(hwnd != NULL, "failed to create a listview window\n");
2427     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 20, 0);
2428     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2429 
2430     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2431 
2432     memset(&item, 0, sizeof(item));
2433     item.stateMask = LVIS_SELECTED;
2434     item.state     = LVIS_SELECTED;
2435     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2436     expect(TRUE, res);
2437 
2438     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2439                 "ownerdata select notification", TRUE);
2440 
2441     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2442 
2443     memset(&item, 0, sizeof(item));
2444     item.stateMask = LVIS_FOCUSED;
2445     item.state     = LVIS_FOCUSED;
2446     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2447     expect(TRUE, res);
2448 
2449     ok_sequence(sequences, PARENT_SEQ_INDEX, ownderdata_select_focus_parent_seq,
2450                 "ownerdata focus notification", TRUE);
2451 
2452     /* select all, check notifications */
2453     item.stateMask = LVIS_SELECTED;
2454     item.state     = 0;
2455     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2456     expect(TRUE, res);
2457 
2458     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2459 
2460     item.stateMask = LVIS_SELECTED;
2461     item.state     = LVIS_SELECTED;
2462 
2463     g_dump_itemchanged = TRUE;
2464     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2465     expect(TRUE, res);
2466     g_dump_itemchanged = FALSE;
2467 
2468     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2469                 "ownerdata select all notification", TRUE);
2470 
2471     /* select all again, note that all items are selected already */
2472     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2473     item.stateMask = LVIS_SELECTED;
2474     item.state     = LVIS_SELECTED;
2475     g_dump_itemchanged = TRUE;
2476     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2477     expect(TRUE, res);
2478     g_dump_itemchanged = FALSE;
2479     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2480                 "ownerdata select all notification", TRUE);
2481     /* deselect all */
2482     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2483     item.stateMask = LVIS_SELECTED;
2484     item.state     = 0;
2485     g_dump_itemchanged = TRUE;
2486     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2487     expect(TRUE, res);
2488     g_dump_itemchanged = FALSE;
2489     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2490                 "ownerdata deselect all notification", TRUE);
2491 
2492     /* select one, then deselect all */
2493     item.stateMask = LVIS_SELECTED;
2494     item.state     = LVIS_SELECTED;
2495     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2496     expect(TRUE, res);
2497     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2498     item.stateMask = LVIS_SELECTED;
2499     item.state     = 0;
2500     g_dump_itemchanged = TRUE;
2501     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2502     expect(TRUE, res);
2503     g_dump_itemchanged = FALSE;
2504     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_deselect_all_parent_seq,
2505                 "ownerdata select all notification", TRUE);
2506 
2507     /* remove focused, try to focus all */
2508     item.stateMask = LVIS_FOCUSED;
2509     item.state     = LVIS_FOCUSED;
2510     res = SendMessageA(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2511     expect(TRUE, res);
2512     item.stateMask = LVIS_FOCUSED;
2513     item.state     = 0;
2514     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2515     expect(TRUE, res);
2516     item.stateMask = LVIS_FOCUSED;
2517     res = SendMessageA(hwnd, LVM_GETITEMSTATE, 0, LVIS_FOCUSED);
2518     expect(0, res);
2519     /* setting all to focused returns failure value */
2520     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2521     item.stateMask = LVIS_FOCUSED;
2522     item.state     = LVIS_FOCUSED;
2523     g_dump_itemchanged = TRUE;
2524     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2525     expect(FALSE, res);
2526     g_dump_itemchanged = FALSE;
2527     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2528                 "ownerdata focus all notification", FALSE);
2529     /* focus single item, remove all */
2530     item.stateMask = LVIS_FOCUSED;
2531     item.state     = LVIS_FOCUSED;
2532     res = SendMessage(hwnd, LVM_SETITEMSTATE, 0, (LPARAM)&item);
2533     expect(TRUE, res);
2534     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2535     item.stateMask = LVIS_FOCUSED;
2536     item.state     = 0;
2537     g_dump_itemchanged = TRUE;
2538     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2539     expect(TRUE, res);
2540     g_dump_itemchanged = FALSE;
2541     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_defocus_all_parent_seq,
2542                 "ownerdata remove focus all notification", TRUE);
2543     /* set all cut */
2544     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2545     item.stateMask = LVIS_CUT;
2546     item.state     = LVIS_CUT;
2547     g_dump_itemchanged = TRUE;
2548     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2549     expect(TRUE, res);
2550     g_dump_itemchanged = FALSE;
2551     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2552                 "ownerdata cut all notification", TRUE);
2553     /* all marked cut, try again */
2554     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2555     item.stateMask = LVIS_CUT;
2556     item.state     = LVIS_CUT;
2557     g_dump_itemchanged = TRUE;
2558     res = SendMessageA(hwnd, LVM_SETITEMSTATE, -1, (LPARAM)&item);
2559     expect(TRUE, res);
2560     g_dump_itemchanged = FALSE;
2561     ok_sequence(sequences, PARENT_SEQ_INDEX, ownerdata_setstate_all_parent_seq,
2562                 "ownerdata cut all notification #2", TRUE);
2563 
2564     DestroyWindow(hwnd);
2565 
2566     /* check notifications on LVM_GETITEM */
2567     /* zero callback mask */
2568     hwnd = create_listview_control(LVS_OWNERDATA);
2569     ok(hwnd != NULL, "failed to create a listview window\n");
2570     res = SendMessageA(hwnd, LVM_SETITEMCOUNT, 1, 0);
2571     ok(res != 0, "Expected LVM_SETITEMCOUNT to succeed\n");
2572 
2573     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2574 
2575     memset(&item, 0, sizeof(item));
2576     item.stateMask = LVIS_SELECTED;
2577     item.mask      = LVIF_STATE;
2578     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2579     expect(TRUE, res);
2580 
2581     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2582                 "ownerdata getitem selected state 1", FALSE);
2583 
2584     /* non zero callback mask but not we asking for */
2585     res = SendMessageA(hwnd, LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK, 0);
2586     expect(TRUE, res);
2587 
2588     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2589 
2590     memset(&item, 0, sizeof(item));
2591     item.stateMask = LVIS_SELECTED;
2592     item.mask      = LVIF_STATE;
2593     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2594     expect(TRUE, res);
2595 
2596     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2597                 "ownerdata getitem selected state 2", FALSE);
2598 
2599     /* LVIS_OVERLAYMASK callback mask, asking for index */
2600     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2601 
2602     memset(&item, 0, sizeof(item));
2603     item.stateMask = LVIS_OVERLAYMASK;
2604     item.mask      = LVIF_STATE;
2605     res = SendMessageA(hwnd, LVM_GETITEMA, 0, (LPARAM)&item);
2606     expect(TRUE, res);
2607 
2608     ok_sequence(sequences, PARENT_SEQ_INDEX, single_getdispinfo_parent_seq,
2609                 "ownerdata getitem selected state 2", FALSE);
2610 
2611     DestroyWindow(hwnd);
2612 
2613     /* LVS_SORTASCENDING/LVS_SORTDESCENDING aren't compatible with LVS_OWNERDATA */
2614     hwnd = create_listview_control(LVS_OWNERDATA | LVS_SORTASCENDING);
2615     ok(hwnd != NULL, "failed to create a listview window\n");
2616     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2617     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2618     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2619     SetWindowLongPtrA(hwnd, GWL_STYLE, style & ~LVS_SORTASCENDING);
2620     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2621     ok(!(style & LVS_SORTASCENDING), "Expected LVS_SORTASCENDING not set\n");
2622     DestroyWindow(hwnd);
2623     /* apparently it's allowed to switch these style on after creation */
2624     hwnd = create_listview_control(LVS_OWNERDATA);
2625     ok(hwnd != NULL, "failed to create a listview window\n");
2626     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2627     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2628     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTASCENDING);
2629     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2630     ok(style & LVS_SORTASCENDING, "Expected LVS_SORTASCENDING to be set\n");
2631     DestroyWindow(hwnd);
2632 
2633     hwnd = create_listview_control(LVS_OWNERDATA);
2634     ok(hwnd != NULL, "failed to create a listview window\n");
2635     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2636     ok(style & LVS_OWNERDATA, "Expected LVS_OWNERDATA\n");
2637     SetWindowLongPtrA(hwnd, GWL_STYLE, style | LVS_SORTDESCENDING);
2638     style = GetWindowLongPtrA(hwnd, GWL_STYLE);
2639     ok(style & LVS_SORTDESCENDING, "Expected LVS_SORTDESCENDING to be set\n");
2640     DestroyWindow(hwnd);
2641 }
2642 
2643 static void test_norecompute(void)
2644 {
2645     static CHAR testA[] = "test";
2646     CHAR buff[10];
2647     LVITEMA item;
2648     HWND hwnd;
2649     DWORD res;
2650 
2651     /* self containing control */
2652     hwnd = create_listview_control(0);
2653     ok(hwnd != NULL, "failed to create a listview window\n");
2654     memset(&item, 0, sizeof(item));
2655     item.mask = LVIF_TEXT | LVIF_STATE;
2656     item.iItem = 0;
2657     item.stateMask = LVIS_SELECTED;
2658     item.state     = LVIS_SELECTED;
2659     item.pszText   = testA;
2660     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2661     expect(0, res);
2662     /* retrieve with LVIF_NORECOMPUTE */
2663     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2664     item.iItem = 0;
2665     item.pszText    = buff;
2666     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2667     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2668     expect(TRUE, res);
2669     ok(lstrcmp(buff, testA) == 0, "Expected (%s), got (%s)\n", testA, buff);
2670 
2671     item.mask = LVIF_TEXT;
2672     item.iItem = 1;
2673     item.pszText = LPSTR_TEXTCALLBACK;
2674     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2675     expect(1, res);
2676 
2677     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2678     item.iItem = 1;
2679     item.pszText    = buff;
2680     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2681 
2682     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2683     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2684     expect(TRUE, res);
2685     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2686        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2687     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq", FALSE);
2688 
2689     DestroyWindow(hwnd);
2690 
2691     /* LVS_OWNERDATA */
2692     hwnd = create_listview_control(LVS_OWNERDATA);
2693     ok(hwnd != NULL, "failed to create a listview window\n");
2694 
2695     item.mask = LVIF_STATE;
2696     item.stateMask = LVIS_SELECTED;
2697     item.state     = LVIS_SELECTED;
2698     item.iItem = 0;
2699     res = SendMessageA(hwnd, LVM_INSERTITEM, 0, (LPARAM)&item);
2700     expect(0, res);
2701 
2702     item.mask  = LVIF_TEXT | LVIF_NORECOMPUTE;
2703     item.iItem = 0;
2704     item.pszText    = buff;
2705     item.cchTextMax = sizeof(buff)/sizeof(CHAR);
2706     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2707     res = SendMessageA(hwnd, LVM_GETITEM, 0, (LPARAM)&item);
2708     expect(TRUE, res);
2709     ok(item.pszText == LPSTR_TEXTCALLBACK, "Expected (%p), got (%p)\n",
2710        LPSTR_TEXTCALLBACK, (VOID*)item.pszText);
2711     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq, "retrieve with LVIF_NORECOMPUTE seq 2", FALSE);
2712 
2713     DestroyWindow(hwnd);
2714 }
2715 
2716 static void test_nosortheader(void)
2717 {
2718     HWND hwnd, header;
2719     LONG_PTR style;
2720 
2721     hwnd = create_listview_control(0);
2722     ok(hwnd != NULL, "failed to create a listview window\n");
2723 
2724     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2725     ok(IsWindow(header), "header expected\n");
2726 
2727     style = GetWindowLongPtr(header, GWL_STYLE);
2728     ok(style & HDS_BUTTONS, "expected header to have HDS_BUTTONS\n");
2729 
2730     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2731     SetWindowLongPtr(hwnd, GWL_STYLE, style | LVS_NOSORTHEADER);
2732     /* HDS_BUTTONS retained */
2733     style = GetWindowLongPtr(header, GWL_STYLE);
2734     ok(style & HDS_BUTTONS, "expected header to retain HDS_BUTTONS\n");
2735 
2736     DestroyWindow(hwnd);
2737 
2738     /* create with LVS_NOSORTHEADER */
2739     hwnd = create_listview_control(LVS_NOSORTHEADER);
2740     ok(hwnd != NULL, "failed to create a listview window\n");
2741 
2742     header = (HWND)SendMessageA(hwnd, LVM_GETHEADER, 0, 0);
2743     ok(IsWindow(header), "header expected\n");
2744 
2745     style = GetWindowLongPtr(header, GWL_STYLE);
2746     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2747 
2748     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2749     SetWindowLongPtr(hwnd, GWL_STYLE, style & ~LVS_NOSORTHEADER);
2750     /* not changed here */
2751     style = GetWindowLongPtr(header, GWL_STYLE);
2752     ok(!(style & HDS_BUTTONS), "expected header to have no HDS_BUTTONS\n");
2753 
2754     DestroyWindow(hwnd);
2755 }
2756 
2757 static void test_setredraw(void)
2758 {
2759     HWND hwnd;
2760     DWORD_PTR style;
2761     DWORD ret;
2762     HDC hdc;
2763     RECT rect;
2764 
2765     hwnd = create_listview_control(LVS_OWNERDATA);
2766     ok(hwnd != NULL, "failed to create a listview window\n");
2767 
2768     /* Passing WM_SETREDRAW to DefWinProc removes WS_VISIBLE.
2769        ListView seems to handle it internally without DefWinProc */
2770 
2771     /* default value first */
2772     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2773     expect(0, ret);
2774     /* disable */
2775     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2776     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2777     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2778     expect(0, ret);
2779     style = GetWindowLongPtr(hwnd, GWL_STYLE);
2780     ok(style & WS_VISIBLE, "Expected WS_VISIBLE to be set\n");
2781     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2782     expect(0, ret);
2783 
2784     /* check update rect after redrawing */
2785     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2786     expect(0, ret);
2787     InvalidateRect(hwnd, NULL, FALSE);
2788     RedrawWindow(hwnd, NULL, NULL, RDW_UPDATENOW);
2789     rect.right = rect.bottom = 1;
2790     GetUpdateRect(hwnd, &rect, FALSE);
2791     expect(0, rect.right);
2792     expect(0, rect.bottom);
2793 
2794     /* WM_ERASEBKGND */
2795     hdc = GetWindowDC(hwndparent);
2796     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2797     expect(TRUE, ret);
2798     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2799     expect(0, ret);
2800     ret = SendMessage(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
2801     expect(TRUE, ret);
2802     ret = SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
2803     expect(0, ret);
2804     ReleaseDC(hwndparent, hdc);
2805 
2806     /* check notification messages to show that repainting is disabled */
2807     ret = SendMessage(hwnd, LVM_SETITEMCOUNT, 1, 0);
2808     expect(TRUE, ret);
2809     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2810     expect(0, ret);
2811     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2812 
2813     InvalidateRect(hwnd, NULL, TRUE);
2814     UpdateWindow(hwnd);
2815     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2816                 "redraw after WM_SETREDRAW (FALSE)", FALSE);
2817 
2818     ret = SendMessage(hwnd, LVM_SETBKCOLOR, 0, CLR_NONE);
2819     expect(TRUE, ret);
2820     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2821     InvalidateRect(hwnd, NULL, TRUE);
2822     UpdateWindow(hwnd);
2823     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_seq,
2824                 "redraw after WM_SETREDRAW (FALSE) with CLR_NONE bkgnd", FALSE);
2825 
2826     /* message isn't forwarded to header */
2827     subclass_header(hwnd);
2828     flush_sequences(sequences, NUM_MSG_SEQUENCES);
2829     ret = SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);
2830     expect(0, ret);
2831     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, setredraw_seq,
2832                 "WM_SETREDRAW: not forwarded to header", FALSE);
2833 
2834     DestroyWindow(hwnd);
2835 }
2836 
2837 static void test_hittest(void)
2838 {
2839     HWND hwnd;
2840     DWORD r;
2841     RECT bounds;
2842     LVITEMA item;
2843     static CHAR text[] = "1234567890ABCDEFGHIJKLMNOPQRST";
2844     POINT pos;
2845     INT x, y;
2846     HIMAGELIST himl, himl2;
2847     HBITMAP hbmp;
2848 
2849     hwnd = create_listview_control(0);
2850     ok(hwnd != NULL, "failed to create a listview window\n");
2851 
2852     /* LVS_REPORT with a single subitem (2 columns) */
2853     insert_column(hwnd, 0);
2854     insert_column(hwnd, 1);
2855     insert_item(hwnd, 0);
2856 
2857     item.iSubItem = 0;
2858     /* the only purpose of that line is to be as long as a half item rect */
2859     item.pszText  = text;
2860     r = SendMessage(hwnd, LVM_SETITEMTEXT, 0, (LPARAM)&item);
2861     expect(TRUE, r);
2862 
2863     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
2864     expect(TRUE, r);
2865     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(100, 0));
2866     expect(TRUE, r);
2867 
2868     memset(&bounds, 0, sizeof(bounds));
2869     bounds.left = LVIR_BOUNDS;
2870     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&bounds);
2871     ok(bounds.bottom - bounds.top > 0, "Expected non zero item height\n");
2872     ok(bounds.right - bounds.left > 0, "Expected non zero item width\n");
2873     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pos);
2874     expect(TRUE, r);
2875 
2876     /* LVS_EX_FULLROWSELECT not set, no icons attached */
2877     x = pos.x + 50; /* column half width */
2878     y = pos.y + (bounds.bottom - bounds.top) / 2;
2879     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMLABEL, 0, FALSE, FALSE, __LINE__);
2880     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2881     x = pos.x + 150; /* outside column */
2882     y = pos.y + (bounds.bottom - bounds.top) / 2;
2883     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2884     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2885     y = (bounds.bottom - bounds.top) / 2;
2886     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2887     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2888     /* outside possible client rectangle (to right) */
2889     x = pos.x + 500;
2890     y = pos.y + (bounds.bottom - bounds.top) / 2;
2891     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2892     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2893     y = (bounds.bottom - bounds.top) / 2;
2894     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2895     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2896     /* subitem returned with -1 item too */
2897     x = pos.x + 150;
2898     y = -10;
2899     test_lvm_subitemhittest(hwnd, x, y, -1, 1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2900     /* parent client area is 100x100 by default */
2901     MoveWindow(hwnd, 0, 0, 300, 100, FALSE);
2902     x = pos.x + 150; /* outside column */
2903     y = pos.y + (bounds.bottom - bounds.top) / 2;
2904     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, FALSE, __LINE__);
2905     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2906     y = (bounds.bottom - bounds.top) / 2;
2907     test_lvm_hittest(hwnd, x, y, -1, LVHT_NOWHERE, 0, FALSE, TRUE, __LINE__);
2908     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2909     /* the same with LVS_EX_FULLROWSELECT */
2910     SendMessage(hwnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
2911     x = pos.x + 150; /* outside column */
2912     y = pos.y + (bounds.bottom - bounds.top) / 2;
2913     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEM, LVHT_ONITEMLABEL, FALSE, FALSE, __LINE__);
2914     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2915     y = (bounds.bottom - bounds.top) / 2;
2916     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2917     MoveWindow(hwnd, 0, 0, 100, 100, FALSE);
2918     x = pos.x + 150; /* outside column */
2919     y = pos.y + (bounds.bottom - bounds.top) / 2;
2920     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2921     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2922     y = (bounds.bottom - bounds.top) / 2;
2923     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2924     test_lvm_subitemhittest(hwnd, x, y, 0, 1, LVHT_ONITEMLABEL, FALSE, FALSE, FALSE, __LINE__);
2925     /* outside possible client rectangle (to right) */
2926     x = pos.x + 500;
2927     y = pos.y + (bounds.bottom - bounds.top) / 2;
2928     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, FALSE, __LINE__);
2929     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2930     y = (bounds.bottom - bounds.top) / 2;
2931     test_lvm_hittest(hwnd, x, y, -1, LVHT_TORIGHT, 0, FALSE, TRUE, __LINE__);
2932     test_lvm_subitemhittest(hwnd, x, y, -1, -1, LVHT_NOWHERE, FALSE, FALSE, FALSE, __LINE__);
2933     /* try with icons, state icons index is 1 based so at least 2 bitmaps needed */
2934     himl = ImageList_Create(16, 16, 0, 4, 4);
2935     ok(himl != NULL, "failed to create imagelist\n");
2936     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2937     ok(hbmp != NULL, "failed to create bitmap\n");
2938     r = ImageList_Add(himl, hbmp, 0);
2939     ok(r == 0, "should be zero\n");
2940     hbmp = CreateBitmap(16, 16, 1, 1, NULL);
2941     ok(hbmp != NULL, "failed to create bitmap\n");
2942     r = ImageList_Add(himl, hbmp, 0);
2943     ok(r == 1, "should be one\n");
2944 
2945     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)himl);
2946     ok(r == 0, "should return zero\n");
2947 
2948     item.mask = LVIF_IMAGE;
2949     item.iImage = 0;
2950     item.iItem = 0;
2951     item.iSubItem = 0;
2952     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2953     expect(TRUE, r);
2954     /* on state icon */
2955     x = pos.x + 8;
2956     y = pos.y + (bounds.bottom - bounds.top) / 2;
2957     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2958     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2959     y = (bounds.bottom - bounds.top) / 2;
2960     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2961 
2962     /* state icons indices are 1 based, check with valid index */
2963     item.mask = LVIF_STATE;
2964     item.state = INDEXTOSTATEIMAGEMASK(1);
2965     item.stateMask = LVIS_STATEIMAGEMASK;
2966     item.iItem = 0;
2967     item.iSubItem = 0;
2968     r = SendMessage(hwnd, LVM_SETITEM, 0, (LPARAM)&item);
2969     expect(TRUE, r);
2970     /* on state icon */
2971     x = pos.x + 8;
2972     y = pos.y + (bounds.bottom - bounds.top) / 2;
2973     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMSTATEICON, 0, FALSE, FALSE, __LINE__);
2974     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2975     y = (bounds.bottom - bounds.top) / 2;
2976     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMSTATEICON, FALSE, FALSE, FALSE, __LINE__);
2977 
2978     himl2 = (HIMAGELIST)SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_STATE, (LPARAM)NULL);
2979     ok(himl2 == himl, "should return handle\n");
2980 
2981     r = SendMessage(hwnd, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)himl);
2982     ok(r == 0, "should return zero\n");
2983     /* on item icon */
2984     x = pos.x + 8;
2985     y = pos.y + (bounds.bottom - bounds.top) / 2;
2986     test_lvm_hittest(hwnd, x, y, 0, LVHT_ONITEMICON, 0, FALSE, FALSE, __LINE__);
2987     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2988     y = (bounds.bottom - bounds.top) / 2;
2989     test_lvm_subitemhittest(hwnd, x, y, 0, 0, LVHT_ONITEMICON, FALSE, FALSE, FALSE, __LINE__);
2990 
2991     DestroyWindow(hwnd);
2992 }
2993 
2994 static void test_getviewrect(void)
2995 {
2996     HWND hwnd;
2997     DWORD r;
2998     RECT rect;
2999     LVITEMA item;
3000 
3001     hwnd = create_listview_control(0);
3002     ok(hwnd != NULL, "failed to create a listview window\n");
3003 
3004     /* empty */
3005     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3006     expect(TRUE, r);
3007 
3008     insert_column(hwnd, 0);
3009     insert_column(hwnd, 1);
3010 
3011     memset(&item, 0, sizeof(item));
3012     item.iItem = 0;
3013     item.iSubItem = 0;
3014     SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3015 
3016     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(100, 0));
3017     expect(TRUE, r);
3018     r = SendMessage(hwnd, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(120, 0));
3019     expect(TRUE, r);
3020 
3021     rect.left = rect.right = rect.top = rect.bottom = -1;
3022     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3023     expect(TRUE, r);
3024     /* left is set to (2e31-1) - XP SP2 */
3025     expect(0, rect.right);
3026     expect(0, rect.top);
3027     expect(0, rect.bottom);
3028 
3029     /* switch to LVS_ICON */
3030     SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~LVS_REPORT);
3031 
3032     rect.left = rect.right = rect.top = rect.bottom = -1;
3033     r = SendMessage(hwnd, LVM_GETVIEWRECT, 0, (LPARAM)&rect);
3034     expect(TRUE, r);
3035     expect(0, rect.left);
3036     expect(0, rect.top);
3037     /* precise value differs for 2k, XP and Vista */
3038     ok(rect.bottom > 0, "Expected positive bottom value, got %d\n", rect.bottom);
3039     ok(rect.right  > 0, "Expected positive right value, got %d\n", rect.right);
3040 
3041     DestroyWindow(hwnd);
3042 }
3043 
3044 static void test_getitemposition(void)
3045 {
3046     HWND hwnd, header;
3047     DWORD r;
3048     POINT pt;
3049     RECT rect;
3050 
3051     hwnd = create_listview_control(0);
3052     ok(hwnd != NULL, "failed to create a listview window\n");
3053     header = subclass_header(hwnd);
3054 
3055     /* LVS_REPORT, single item, no columns added */
3056     insert_item(hwnd, 0);
3057 
3058     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3059 
3060     pt.x = pt.y = -1;
3061     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3062     expect(TRUE, r);
3063     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq1, "get item position 1", FALSE);
3064 
3065     /* LVS_REPORT, single item, single column */
3066     insert_column(hwnd, 0);
3067 
3068     flush_sequences(sequences, NUM_MSG_SEQUENCES);
3069 
3070     pt.x = pt.y = -1;
3071     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3072     expect(TRUE, r);
3073     ok_sequence(sequences, LISTVIEW_SEQ_INDEX, getitemposition_seq2, "get item position 2", TRUE);
3074 
3075     memset(&rect, 0, sizeof(rect));
3076     SendMessage(header, HDM_GETITEMRECT, 0, (LPARAM)&rect);
3077     /* some padding? */
3078     expect(2, pt.x);
3079     /* offset by header height */
3080     expect(rect.bottom - rect.top, pt.y);
3081 
3082     DestroyWindow(hwnd);
3083 }
3084 
3085 static void test_columnscreation(void)
3086 {
3087     HWND hwnd, header;
3088     DWORD r;
3089 
3090     hwnd = create_listview_control(0);
3091     ok(hwnd != NULL, "failed to create a listview window\n");
3092 
3093     insert_item(hwnd, 0);
3094 
3095     /* headers columns aren't created automatically */
3096     header = (HWND)SendMessage(hwnd, LVM_GETHEADER, 0, 0);
3097     ok(IsWindow(header), "Expected header handle\n");
3098     r = SendMessage(header, HDM_GETITEMCOUNT, 0, 0);
3099     expect(0, r);
3100 
3101     DestroyWindow(hwnd);
3102 }
3103 
3104 static void test_getitemrect(void)
3105 {
3106     HWND hwnd;
3107     HIMAGELIST himl;
3108     HBITMAP hbm;
3109     RECT rect;
3110     DWORD r;
3111     LVITEMA item;
3112     LVCOLUMNA col;
3113     INT order[2];
3114     POINT pt;
3115 
3116     hwnd = create_listview_control(0);
3117     ok(hwnd != NULL, "failed to create a listview window\n");
3118 
3119     /* empty item */
3120     memset(&item, 0, sizeof(item));
3121     item.iItem = 0;
3122     item.iSubItem = 0;
3123     r = SendMessage(hwnd, LVM_INSERTITEMA, 0, (LPARAM)&item);
3124     expect(0, r);
3125 
3126     rect.left = LVIR_BOUNDS;
3127     rect.right = rect.top = rect.bottom = -1;
3128     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3129     expect(TRUE, r);
3130 
3131     /* zero width rectangle with no padding */
3132     expect(0, rect.left);
3133     expect(0, rect.right);
3134 
3135     insert_column(hwnd, 0);
3136     insert_column(hwnd, 1);
3137 
3138     col.mask = LVCF_WIDTH;
3139     col.cx   = 50;
3140     r = SendMessage(hwnd, LVM_SETCOLUMN, 0, (LPARAM)&col);
3141     expect(TRUE, r);
3142 
3143     col.mask = LVCF_WIDTH;
3144     col.cx   = 100;
3145     r = SendMessage(hwnd, LVM_SETCOLUMN, 1, (LPARAM)&col);
3146     expect(TRUE, r);
3147 
3148     rect.left = LVIR_BOUNDS;
3149     rect.right = rect.top = rect.bottom = -1;
3150     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3151     expect(TRUE, r);
3152 
3153     /* still no left padding */
3154     expect(0, rect.left);
3155     expect(150, rect.right);
3156 
3157     rect.left = LVIR_SELECTBOUNDS;
3158     rect.right = rect.top = rect.bottom = -1;
3159     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3160     expect(TRUE, r);
3161     /* padding */
3162     expect(2, rect.left);
3163 
3164     rect.left = LVIR_LABEL;
3165     rect.right = rect.top = rect.bottom = -1;
3166     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3167     expect(TRUE, r);
3168     /* padding, column width */
3169     expect(2, rect.left);
3170     expect(50, rect.right);
3171 
3172     /* no icons attached */
3173     rect.left = LVIR_ICON;
3174     rect.right = rect.top = rect.bottom = -1;
3175     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3176     expect(TRUE, r);
3177     /* padding */
3178     expect(2, rect.left);
3179     expect(2, rect.right);
3180 
3181     /* change order */
3182     order[0] = 1; order[1] = 0;
3183     r = SendMessage(hwnd, LVM_SETCOLUMNORDERARRAY, 2, (LPARAM)&order);
3184     expect(TRUE, r);
3185     pt.x = -1;
3186     r = SendMessage(hwnd, LVM_GETITEMPOSITION, 0, (LPARAM)&pt);
3187     expect(TRUE, r);
3188     /* 1 indexed column width + padding */
3189     expect(102, pt.x);
3190     /* rect is at zero too */
3191     rect.left = LVIR_BOUNDS;
3192     rect.right = rect.top = rect.bottom = -1;
3193     r = SendMessage(hwnd, LVM_GETITEMRECT, 0, (LPARAM)&rect);
3194     expect(TRUE, r);