tests: Assorted spelling fixes.
[wine] / dlls / user32 / tests / dce.c
1 /*
2  * Unit tests for DCE support
3  *
4  * Copyright 2005 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30
31 #include "wine/test.h"
32
33 #ifndef DCX_USESTYLE
34 #define DCX_USESTYLE         0x00010000
35 #endif
36
37 static HWND hwnd_cache, hwnd_owndc, hwnd_classdc, hwnd_classdc2;
38
39 /* test behavior of DC attributes with various GetDC/ReleaseDC combinations */
40 static void test_dc_attributes(void)
41 {
42     HDC hdc, old_hdc;
43     HDC hdcs[20];
44     INT i, rop, def_rop, found_dc;
45
46     /* test cache DC */
47
48     hdc = GetDC( hwnd_cache );
49     def_rop = GetROP2( hdc );
50
51     SetROP2( hdc, R2_WHITE );
52     rop = GetROP2( hdc );
53     ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
54
55     ReleaseDC( hwnd_cache, hdc );
56     hdc = GetDC( hwnd_cache );
57     rop = GetROP2( hdc );
58     ok( rop == def_rop, "wrong ROP2 %d after release\n", rop );
59     SetROP2( hdc, R2_WHITE );
60     ReleaseDC( hwnd_cache, hdc );
61     old_hdc = hdc;
62
63     found_dc = 0;
64     for (i = 0; i < 20; i++)
65     {
66         hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
67         if (!hdc) break;
68         rop = GetROP2( hdc );
69         ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
70         if (hdc == old_hdc)
71         {
72             found_dc = 1;
73             SetROP2( hdc, R2_WHITE );
74         }
75     }
76     if (!found_dc)
77     {
78         trace( "hdc %p not found in cache using %p\n", old_hdc, hdcs[0] );
79         old_hdc = hdcs[0];
80         SetROP2( old_hdc, R2_WHITE );
81     }
82     while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
83
84     for (i = 0; i < 20; i++)
85     {
86         hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
87         if (!hdc) break;
88         rop = GetROP2( hdc );
89         if (hdc == old_hdc)
90             ok( rop == R2_WHITE || broken( rop == def_rop),  /* win9x doesn't support DCX_NORESETATTRS */
91                 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
92         else
93             ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
94     }
95     while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
96
97     for (i = 0; i < 20; i++)
98     {
99         hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE );
100         if (!hdc) break;
101         rop = GetROP2( hdc );
102         if (hdc == old_hdc)
103         {
104             ok( rop == R2_WHITE || broken( rop == def_rop),
105                 "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
106             SetROP2( old_hdc, def_rop );
107         }
108         else
109             ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc );
110     }
111     while (i >= 0) ReleaseDC( hwnd_cache, hdcs[--i] );
112
113     /* test own DC */
114
115     hdc = GetDC( hwnd_owndc );
116     SetROP2( hdc, R2_WHITE );
117     rop = GetROP2( hdc );
118     ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
119
120     old_hdc = hdc;
121     ReleaseDC( hwnd_owndc, hdc );
122     hdc = GetDC( hwnd_owndc );
123     ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
124     rop = GetROP2( hdc );
125     ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
126     ReleaseDC( hwnd_owndc, hdc );
127     rop = GetROP2( hdc );
128     ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
129
130     /* test class DC */
131
132     hdc = GetDC( hwnd_classdc );
133     SetROP2( hdc, R2_WHITE );
134     rop = GetROP2( hdc );
135     ok( rop == R2_WHITE, "wrong ROP2 %d\n", rop );
136
137     old_hdc = hdc;
138     ReleaseDC( hwnd_classdc, hdc );
139     hdc = GetDC( hwnd_classdc );
140     ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
141     rop = GetROP2( hdc );
142     ok( rop == R2_WHITE, "wrong ROP2 %d after release\n", rop );
143     ReleaseDC( hwnd_classdc, hdc );
144     rop = GetROP2( hdc );
145     ok( rop == R2_WHITE, "wrong ROP2 %d after second release\n", rop );
146
147     /* test class DC with 2 windows */
148
149     old_hdc = GetDC( hwnd_classdc );
150     SetROP2( old_hdc, R2_BLACK );
151     hdc = GetDC( hwnd_classdc2 );
152     ok( old_hdc == hdc, "didn't get same DC %p/%p\n", old_hdc, hdc );
153     rop = GetROP2( hdc );
154     ok( rop == R2_BLACK, "wrong ROP2 %d for other window\n", rop );
155     ReleaseDC( hwnd_classdc, old_hdc );
156     ReleaseDC( hwnd_classdc, hdc );
157     rop = GetROP2( hdc );
158     ok( rop == R2_BLACK, "wrong ROP2 %d after release\n", rop );
159 }
160
161
162 /* test behavior with various invalid parameters */
163 static void test_parameters(void)
164 {
165     HDC hdc;
166
167     hdc = GetDC( hwnd_cache );
168     ok( ReleaseDC( hwnd_owndc, hdc ), "ReleaseDC with wrong window should succeed\n" );
169
170     hdc = GetDC( hwnd_cache );
171     ok( !ReleaseDC( hwnd_cache, 0 ), "ReleaseDC with wrong HDC should fail\n" );
172     ok( ReleaseDC( hwnd_cache, hdc ), "correct ReleaseDC should succeed\n" );
173     ok( !ReleaseDC( hwnd_cache, hdc ), "second ReleaseDC should fail\n" );
174
175     hdc = GetDC( hwnd_owndc );
176     ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
177     hdc = GetDC( hwnd_owndc );
178     ok( ReleaseDC( hwnd_owndc, hdc ), "correct ReleaseDC should succeed\n" );
179     ok( ReleaseDC( hwnd_owndc, hdc ), "second ReleaseDC should succeed\n" );
180
181     hdc = GetDC( hwnd_classdc );
182     ok( ReleaseDC( hwnd_cache, hdc ), "ReleaseDC with wrong window should succeed\n" );
183     hdc = GetDC( hwnd_classdc );
184     ok( ReleaseDC( hwnd_classdc, hdc ), "correct ReleaseDC should succeed\n" );
185     ok( ReleaseDC( hwnd_classdc, hdc ), "second ReleaseDC should succeed\n" );
186 }
187
188
189 static void test_dc_visrgn(void)
190 {
191     HDC old_hdc, hdc;
192     HRGN hrgn, hrgn2;
193     RECT rect;
194
195     /* cache DC */
196
197     SetRect( &rect, 10, 10, 20, 20 );
198     MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
199     hrgn = CreateRectRgnIndirect( &rect );
200     hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
201     SetRectEmpty( &rect );
202     GetClipBox( hdc, &rect );
203     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
204         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
205     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
206     ReleaseDC( hwnd_cache, hdc );
207     ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
208
209     /* cache DC with NORESETATTRS */
210
211     SetRect( &rect, 10, 10, 20, 20 );
212     MapWindowPoints( hwnd_cache, 0, (POINT *)&rect, 2 );
213     hrgn = CreateRectRgnIndirect( &rect );
214     hdc = GetDCEx( hwnd_cache, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE | DCX_NORESETATTRS );
215     SetRectEmpty( &rect );
216     GetClipBox( hdc, &rect );
217     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
218         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
219     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
220     ReleaseDC( hwnd_cache, hdc );
221     ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
222     hdc = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS );
223     SetRectEmpty( &rect );
224     GetClipBox( hdc, &rect );
225     ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
226         "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
227     ReleaseDC( hwnd_cache, hdc );
228
229     /* window DC */
230
231     SetRect( &rect, 10, 10, 20, 20 );
232     MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
233     hrgn = CreateRectRgnIndirect( &rect );
234     hdc = GetDCEx( hwnd_owndc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
235     SetRectEmpty( &rect );
236     GetClipBox( hdc, &rect );
237     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
238         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
239     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
240     ReleaseDC( hwnd_owndc, hdc );
241     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
242     SetRectEmpty( &rect );
243     GetClipBox( hdc, &rect );
244     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
245         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
246     hdc = GetDCEx( hwnd_owndc, 0, DCX_USESTYLE );
247     SetRectEmpty( &rect );
248     GetClipBox( hdc, &rect );
249     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
250         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
251     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
252     ReleaseDC( hwnd_owndc, hdc );
253     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
254
255     SetRect( &rect, 20, 20, 30, 30 );
256     MapWindowPoints( hwnd_owndc, 0, (POINT *)&rect, 2 );
257     hrgn2 = CreateRectRgnIndirect( &rect );
258     hdc = GetDCEx( hwnd_owndc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
259     ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
260     SetRectEmpty( &rect );
261     GetClipBox( hdc, &rect );
262     ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
263         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
264     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
265     ReleaseDC( hwnd_owndc, hdc );
266     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
267     hdc = GetDCEx( hwnd_owndc, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
268     ok( GetRgnBox( hrgn2, &rect ) == ERROR, "region must no longer be valid\n" );
269     SetRectEmpty( &rect );
270     GetClipBox( hdc, &rect );
271     ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
272         "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
273     ReleaseDC( hwnd_owndc, hdc );
274
275     /* class DC */
276
277     SetRect( &rect, 10, 10, 20, 20 );
278     MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
279     hrgn = CreateRectRgnIndirect( &rect );
280     hdc = GetDCEx( hwnd_classdc, hrgn, DCX_INTERSECTRGN | DCX_USESTYLE );
281     SetRectEmpty( &rect );
282     GetClipBox( hdc, &rect );
283     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
284         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
285     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
286     ReleaseDC( hwnd_classdc, hdc );
287     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
288     SetRectEmpty( &rect );
289     GetClipBox( hdc, &rect );
290     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
291         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
292
293     hdc = GetDCEx( hwnd_classdc, 0, DCX_USESTYLE );
294     SetRectEmpty( &rect );
295     GetClipBox( hdc, &rect );
296     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
297         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
298     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
299     ReleaseDC( hwnd_classdc, hdc );
300     ok( GetRgnBox( hrgn, &rect ) != ERROR, "region must still be valid\n" );
301
302     SetRect( &rect, 20, 20, 30, 30 );
303     MapWindowPoints( hwnd_classdc, 0, (POINT *)&rect, 2 );
304     hrgn2 = CreateRectRgnIndirect( &rect );
305     hdc = GetDCEx( hwnd_classdc, hrgn2, DCX_INTERSECTRGN | DCX_USESTYLE );
306     ok( GetRgnBox( hrgn, &rect ) == ERROR, "region must no longer be valid\n" );
307     SetRectEmpty( &rect );
308     GetClipBox( hdc, &rect );
309     ok( rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30,
310         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
311     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
312
313     old_hdc = hdc;
314     hdc = GetDCEx( hwnd_classdc2, 0, DCX_USESTYLE );
315     ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
316     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
317     SetRectEmpty( &rect );
318     GetClipBox( hdc, &rect );
319     ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
320         "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
321     ReleaseDC( hwnd_classdc2, hdc );
322     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
323     hdc = GetDCEx( hwnd_classdc2, 0, DCX_EXCLUDERGN | DCX_USESTYLE );
324     ok( GetRgnBox( hrgn2, &rect ) != ERROR, "region2 must still be valid\n" );
325     ok( !(rect.left >= 20 && rect.top >= 20 && rect.right <= 30 && rect.bottom <= 30),
326         "clip box must have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
327     ReleaseDC( hwnd_classdc2, hdc );
328 }
329
330
331 /* test various BeginPaint/EndPaint behaviors */
332 static void test_begin_paint(void)
333 {
334     HDC old_hdc, hdc;
335     RECT rect;
336     PAINTSTRUCT ps;
337
338     /* cache DC */
339
340     /* clear update region */
341     RedrawWindow( hwnd_cache, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
342     SetRect( &rect, 10, 10, 20, 20 );
343     RedrawWindow( hwnd_cache, &rect, 0, RDW_INVALIDATE );
344     hdc = BeginPaint( hwnd_cache, &ps );
345     SetRectEmpty( &rect );
346     GetClipBox( hdc, &rect );
347     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
348         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
349     EndPaint( hwnd_cache, &ps );
350
351     /* window DC */
352
353     RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
354     SetRect( &rect, 10, 10, 20, 20 );
355     RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE );
356     hdc = BeginPaint( hwnd_owndc, &ps );
357     SetRectEmpty( &rect );
358     GetClipBox( hdc, &rect );
359     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
360         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
361     ReleaseDC( hwnd_owndc, hdc );
362     SetRectEmpty( &rect );
363     GetClipBox( hdc, &rect );
364     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
365         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
366     ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
367     SetRectEmpty( &rect );
368     GetClipBox( hdc, &rect );
369     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
370         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
371     EndPaint( hwnd_owndc, &ps );
372     SetRectEmpty( &rect );
373     GetClipBox( hdc, &rect );
374     ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
375         "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
376     RedrawWindow( hwnd_owndc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
377     SetRect( &rect, 10, 10, 20, 20 );
378     RedrawWindow( hwnd_owndc, &rect, 0, RDW_INVALIDATE|RDW_ERASE );
379     ok( GetDC( hwnd_owndc ) == hdc, "got different hdc\n" );
380     SetRectEmpty( &rect );
381     GetClipBox( hdc, &rect );
382     ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
383         "clip box should be the whole window %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
384     RedrawWindow( hwnd_owndc, NULL, 0, RDW_ERASENOW );
385     SetRectEmpty( &rect );
386     GetClipBox( hdc, &rect );
387     ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
388         "clip box should still be the whole window %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
389
390     /* class DC */
391
392     RedrawWindow( hwnd_classdc, NULL, 0, RDW_VALIDATE|RDW_NOFRAME|RDW_NOERASE );
393     SetRect( &rect, 10, 10, 20, 20 );
394     RedrawWindow( hwnd_classdc, &rect, 0, RDW_INVALIDATE );
395     hdc = BeginPaint( hwnd_classdc, &ps );
396     SetRectEmpty( &rect );
397     GetClipBox( hdc, &rect );
398     ok( rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20,
399         "invalid clip box %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
400
401     old_hdc = hdc;
402     hdc = GetDC( hwnd_classdc2 );
403     ok( old_hdc == hdc, "did not get the same hdc %p/%p\n", old_hdc, hdc );
404     SetRectEmpty( &rect );
405     GetClipBox( hdc, &rect );
406     ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20),
407         "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
408 }
409
410 static void test_invisible_create(void)
411 {
412     HWND hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED,
413                                     0, 200, 100, 100,
414                                     0, 0, GetModuleHandleA(0), NULL );
415     HDC dc1, dc2;
416
417     dc1 = GetDC(hwnd_owndc);
418     dc2 = GetDC(hwnd_owndc);
419
420     ok(dc1 == dc2, "expected owndc dcs to match\n");
421
422     ReleaseDC(hwnd_owndc, dc2);
423     ReleaseDC(hwnd_owndc, dc1);
424     DestroyWindow(hwnd_owndc);
425 }
426
427 static void test_dc_layout(void)
428 {
429     DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
430     DWORD (WINAPI *pGetLayout)(HDC hdc);
431     HWND hwnd_cache_rtl, hwnd_owndc_rtl, hwnd_classdc_rtl, hwnd_classdc2_rtl;
432     HDC hdc;
433     DWORD layout;
434     HMODULE mod = GetModuleHandleA("gdi32.dll");
435
436     pGetLayout = (void *)GetProcAddress( mod, "GetLayout" );
437     pSetLayout = (void *)GetProcAddress( mod, "SetLayout" );
438     if (!pGetLayout || !pSetLayout)
439     {
440         win_skip( "Don't have SetLayout\n" );
441         return;
442     }
443
444     hdc = GetDC( hwnd_cache );
445     pSetLayout( hdc, LAYOUT_RTL );
446     layout = pGetLayout( hdc );
447     ReleaseDC( hwnd_cache, hdc );
448     if (!layout)
449     {
450         win_skip( "SetLayout not supported\n" );
451         return;
452     }
453
454     hwnd_cache_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
455                                      0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
456     hwnd_owndc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
457                                      0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
458     hwnd_classdc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
459                                        200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
460     hwnd_classdc2_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
461                                         200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL );
462     hdc = GetDC( hwnd_cache_rtl );
463     layout = pGetLayout( hdc );
464
465     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
466     pSetLayout( hdc, 0 );
467     ReleaseDC( hwnd_cache_rtl, hdc );
468     hdc = GetDC( hwnd_owndc_rtl );
469     layout = pGetLayout( hdc );
470     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
471     ReleaseDC( hwnd_cache_rtl, hdc );
472
473     hdc = GetDC( hwnd_cache );
474     layout = pGetLayout( hdc );
475     ok( layout == 0, "wrong layout %x\n", layout );
476     ReleaseDC( hwnd_cache, hdc );
477
478     hdc = GetDC( hwnd_owndc_rtl );
479     layout = pGetLayout( hdc );
480     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
481     pSetLayout( hdc, 0 );
482     ReleaseDC( hwnd_owndc_rtl, hdc );
483     hdc = GetDC( hwnd_owndc_rtl );
484     layout = pGetLayout( hdc );
485     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
486     ReleaseDC( hwnd_owndc_rtl, hdc );
487
488     hdc = GetDC( hwnd_classdc_rtl );
489     layout = pGetLayout( hdc );
490     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
491     pSetLayout( hdc, 0 );
492     ReleaseDC( hwnd_classdc_rtl, hdc );
493     hdc = GetDC( hwnd_classdc2_rtl );
494     layout = pGetLayout( hdc );
495     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
496     ReleaseDC( hwnd_classdc2_rtl, hdc );
497     hdc = GetDC( hwnd_classdc );
498     layout = pGetLayout( hdc );
499     ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout );
500     ReleaseDC( hwnd_classdc_rtl, hdc );
501
502     DestroyWindow(hwnd_classdc2_rtl);
503     DestroyWindow(hwnd_classdc_rtl);
504     DestroyWindow(hwnd_owndc_rtl);
505     DestroyWindow(hwnd_cache_rtl);
506 }
507
508 static void test_destroyed_window(void)
509 {
510     HDC dc;
511
512     dc = GetDCEx(hwnd_cache, 0, DCX_USESTYLE);
513     ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
514
515     dc = GetDCEx(hwnd_owndc, 0, DCX_USESTYLE);
516     ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
517
518     dc = GetDCEx(hwnd_classdc, 0, DCX_USESTYLE);
519     ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
520
521     dc = GetDCEx(hwnd_classdc2, 0, DCX_USESTYLE);
522     ok(!dc, "Got a non-NULL DC (%p) for a destroyed window.\n", dc);
523 }
524
525 START_TEST(dce)
526 {
527     WNDCLASSA cls;
528
529     cls.style = CS_DBLCLKS;
530     cls.lpfnWndProc = DefWindowProcA;
531     cls.cbClsExtra = 0;
532     cls.cbWndExtra = 0;
533     cls.hInstance = GetModuleHandleA(0);
534     cls.hIcon = 0;
535     cls.hCursor = LoadCursorA(0, IDC_ARROW);
536     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
537     cls.lpszMenuName = NULL;
538     cls.lpszClassName = "cache_class";
539     RegisterClassA(&cls);
540     cls.style = CS_DBLCLKS | CS_OWNDC;
541     cls.lpszClassName = "owndc_class";
542     RegisterClassA(&cls);
543     cls.style = CS_DBLCLKS | CS_CLASSDC;
544     cls.lpszClassName = "classdc_class";
545     RegisterClassA(&cls);
546
547     hwnd_cache = CreateWindowA("cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
548                                0, 0, 100, 100,
549                                0, 0, GetModuleHandleA(0), NULL );
550     hwnd_owndc = CreateWindowA("owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
551                                0, 200, 100, 100,
552                                0, 0, GetModuleHandleA(0), NULL );
553     hwnd_classdc = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
554                                  200, 0, 100, 100,
555                                  0, 0, GetModuleHandleA(0), NULL );
556     hwnd_classdc2 = CreateWindowA("classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE,
557                                   200, 200, 100, 100,
558                                   0, 0, GetModuleHandleA(0), NULL );
559     test_dc_attributes();
560     test_parameters();
561     test_dc_visrgn();
562     test_begin_paint();
563     test_invisible_create();
564     test_dc_layout();
565
566     DestroyWindow(hwnd_classdc2);
567     DestroyWindow(hwnd_classdc);
568     DestroyWindow(hwnd_owndc);
569     DestroyWindow(hwnd_cache);
570
571     test_destroyed_window();
572 }