Release 1.5.29.
[wine] / dlls / gdi32 / driver.c
1 /*
2  * Graphics driver management functions
3  *
4  * Copyright 1994 Bob Amstadt
5  * Copyright 1996, 2001 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "ddrawgdi.h"
33 #include "wine/winbase16.h"
34
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/list.h"
38 #include "wine/debug.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(driver);
41
42 struct graphics_driver
43 {
44     struct list                entry;
45     HMODULE                    module;  /* module handle */
46     const struct gdi_dc_funcs *funcs;
47 };
48
49 static struct list drivers = LIST_INIT( drivers );
50 static struct graphics_driver *display_driver;
51 static DWORD display_driver_load_error;
52
53 const struct gdi_dc_funcs *font_driver = NULL;
54
55 static CRITICAL_SECTION driver_section;
56 static CRITICAL_SECTION_DEBUG critsect_debug =
57 {
58     0, 0, &driver_section,
59     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
60       0, 0, { (DWORD_PTR)(__FILE__ ": driver_section") }
61 };
62 static CRITICAL_SECTION driver_section = { &critsect_debug, -1, 0, 0, 0, 0 };
63
64 #ifdef __APPLE__
65 static const char default_driver[] = "mac,x11";
66 #else
67 static const char default_driver[] = "x11";
68 #endif
69
70 /**********************************************************************
71  *           create_driver
72  *
73  * Allocate and fill the driver structure for a given module.
74  */
75 static struct graphics_driver *create_driver( HMODULE module )
76 {
77     static const struct gdi_dc_funcs empty_funcs;
78     const struct gdi_dc_funcs *funcs = NULL;
79     struct graphics_driver *driver;
80
81     if (!(driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver)))) return NULL;
82     driver->module = module;
83
84     if (module)
85     {
86         const struct gdi_dc_funcs * (CDECL *wine_get_gdi_driver)( unsigned int version );
87
88         if ((wine_get_gdi_driver = (void *)GetProcAddress( module, "wine_get_gdi_driver" )))
89             funcs = wine_get_gdi_driver( WINE_GDI_DRIVER_VERSION );
90     }
91     if (!funcs) funcs = &empty_funcs;
92     driver->funcs = funcs;
93     return driver;
94 }
95
96
97 /**********************************************************************
98  *           get_display_driver
99  *
100  * Special case for loading the display driver: get the name from the config file
101  */
102 static const struct gdi_dc_funcs *get_display_driver( HMODULE *module_ret )
103 {
104     struct graphics_driver *driver;
105     char buffer[MAX_PATH], libname[32], *name, *next;
106     HMODULE module = 0;
107     HKEY hkey;
108
109     if (display_driver) goto done;
110
111     strcpy( buffer, default_driver );
112     /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
113     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
114     {
115         DWORD type, count = sizeof(buffer);
116         RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
117         RegCloseKey( hkey );
118     }
119
120     name = buffer;
121     while (name)
122     {
123         next = strchr( name, ',' );
124         if (next) *next++ = 0;
125
126         snprintf( libname, sizeof(libname), "wine%s.drv", name );
127         if ((module = LoadLibraryA( libname )) != 0) break;
128         name = next;
129     }
130
131     if (!module) display_driver_load_error = GetLastError();
132
133     if (!(driver = create_driver( module )))
134     {
135         MESSAGE( "Could not create graphics driver '%s'\n", buffer );
136         FreeLibrary( module );
137         ExitProcess(1);
138     }
139     if (InterlockedCompareExchangePointer( (void **)&display_driver, driver, NULL ))
140     {
141         /* somebody beat us to it */
142         FreeLibrary( driver->module );
143         HeapFree( GetProcessHeap(), 0, driver );
144     }
145 done:
146     *module_ret = display_driver->module;
147     return display_driver->funcs;
148 }
149
150
151 /**********************************************************************
152  *           DRIVER_load_driver
153  */
154 const struct gdi_dc_funcs *DRIVER_load_driver( LPCWSTR name, HMODULE *module_ret )
155 {
156     HMODULE module;
157     struct graphics_driver *driver, *new_driver;
158     static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
159     static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
160
161     /* display driver is a special case */
162     if (!strcmpiW( name, displayW ) || !strcmpiW( name, display1W ))
163         return get_display_driver( module_ret );
164
165     if ((module = GetModuleHandleW( name )))
166     {
167         if (display_driver && display_driver->module == module)
168         {
169             *module_ret = module;
170             return display_driver->funcs;
171         }
172         EnterCriticalSection( &driver_section );
173         LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry )
174         {
175             if (driver->module == module) goto done;
176         }
177         LeaveCriticalSection( &driver_section );
178     }
179
180     if (!(module = LoadLibraryW( name ))) return NULL;
181
182     if (!(new_driver = create_driver( module )))
183     {
184         FreeLibrary( module );
185         return NULL;
186     }
187
188     /* check if someone else added it in the meantime */
189     EnterCriticalSection( &driver_section );
190     LIST_FOR_EACH_ENTRY( driver, &drivers, struct graphics_driver, entry )
191     {
192         if (driver->module != module) continue;
193         FreeLibrary( module );
194         HeapFree( GetProcessHeap(), 0, new_driver );
195         goto done;
196     }
197     driver = new_driver;
198     list_add_head( &drivers, &driver->entry );
199     TRACE( "loaded driver %p for %s\n", driver, debugstr_w(name) );
200 done:
201     *module_ret = driver->module;
202     LeaveCriticalSection( &driver_section );
203     return driver->funcs;
204 }
205
206
207 /***********************************************************************
208  *           __wine_get_driver_module    (GDI32.@)
209  */
210 HMODULE CDECL __wine_get_driver_module( HDC hdc )
211 {
212     DC *dc;
213     HMODULE ret = 0;
214
215     if ((dc = get_dc_ptr( hdc )))
216     {
217         ret = dc->module;
218         release_dc_ptr( dc );
219         if (!ret) SetLastError( display_driver_load_error );
220     }
221     else SetLastError( ERROR_INVALID_HANDLE );
222     return ret;
223 }
224
225
226 static INT nulldrv_AbortDoc( PHYSDEV dev )
227 {
228     return 0;
229 }
230
231 static BOOL nulldrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
232                          INT xstart, INT ystart, INT xend, INT yend )
233 {
234     return TRUE;
235 }
236
237 static BOOL nulldrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
238                            INT xstart, INT ystart, INT xend, INT yend )
239 {
240     return TRUE;
241 }
242
243 static BOOL nulldrv_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev )
244 {
245     if (!display_driver || !display_driver->funcs->pCreateCompatibleDC) return TRUE;
246     return display_driver->funcs->pCreateCompatibleDC( NULL, pdev );
247 }
248
249 static BOOL nulldrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
250                               LPCWSTR output, const DEVMODEW *devmode )
251 {
252     assert(0);  /* should never be called */
253     return FALSE;
254 }
255
256 static BOOL nulldrv_DeleteDC( PHYSDEV dev )
257 {
258     assert(0);  /* should never be called */
259     return TRUE;
260 }
261
262 static BOOL nulldrv_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
263 {
264     return TRUE;
265 }
266
267 static DWORD nulldrv_DeviceCapabilities( LPSTR buffer, LPCSTR device, LPCSTR port,
268                                          WORD cap, LPSTR output, DEVMODEA *devmode )
269 {
270     return -1;
271 }
272
273 static BOOL nulldrv_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
274 {
275     return TRUE;
276 }
277
278 static INT nulldrv_EndDoc( PHYSDEV dev )
279 {
280     return 0;
281 }
282
283 static INT nulldrv_EndPage( PHYSDEV dev )
284 {
285     return 0;
286 }
287
288 static BOOL nulldrv_EnumFonts( PHYSDEV dev, LOGFONTW *logfont, FONTENUMPROCW proc, LPARAM lParam )
289 {
290     return TRUE;
291 }
292
293 static INT nulldrv_EnumICMProfiles( PHYSDEV dev, ICMENUMPROCW func, LPARAM lparam )
294 {
295     return -1;
296 }
297
298 static INT nulldrv_ExtDeviceMode( LPSTR buffer, HWND hwnd, DEVMODEA *output, LPSTR device,
299                                   LPSTR port, DEVMODEA *input, LPSTR profile, DWORD mode )
300 {
301     return -1;
302 }
303
304 static INT nulldrv_ExtEscape( PHYSDEV dev, INT escape, INT in_size, const void *in_data,
305                                     INT out_size, void *out_data )
306 {
307     return 0;
308 }
309
310 static BOOL nulldrv_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT type )
311 {
312     return TRUE;
313 }
314
315 static BOOL nulldrv_FontIsLinked( PHYSDEV dev )
316 {
317     return FALSE;
318 }
319
320 static BOOL nulldrv_GdiComment( PHYSDEV dev, UINT size, const BYTE *data )
321 {
322     return FALSE;
323 }
324
325 static BOOL nulldrv_GdiRealizationInfo( PHYSDEV dev, void *info )
326 {
327     return FALSE;
328 }
329
330 static UINT nulldrv_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
331 {
332     return DCB_RESET;
333 }
334
335 static BOOL nulldrv_GetCharABCWidths( PHYSDEV dev, UINT first, UINT last, LPABC abc )
336 {
337     return FALSE;
338 }
339
340 static BOOL nulldrv_GetCharABCWidthsI( PHYSDEV dev, UINT first, UINT count, WORD *indices, LPABC abc )
341 {
342     return FALSE;
343 }
344
345 static BOOL nulldrv_GetCharWidth( PHYSDEV dev, UINT first, UINT last, INT *buffer )
346 {
347     return FALSE;
348 }
349
350 static INT nulldrv_GetDeviceCaps( PHYSDEV dev, INT cap )
351 {
352     switch (cap)  /* return meaningful values for some entries */
353     {
354     case HORZRES:     return 640;
355     case VERTRES:     return 480;
356     case BITSPIXEL:   return 1;
357     case PLANES:      return 1;
358     case NUMCOLORS:   return 2;
359     case ASPECTX:     return 36;
360     case ASPECTY:     return 36;
361     case ASPECTXY:    return 51;
362     case LOGPIXELSX:  return 72;
363     case LOGPIXELSY:  return 72;
364     case SIZEPALETTE: return 2;
365     case TEXTCAPS:    return (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
366                               TC_CR_ANY | TC_SF_X_YINDEP | TC_SA_DOUBLE | TC_SA_INTEGER |
367                               TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE | TC_VA_ABLE);
368     default:          return 0;
369     }
370 }
371
372 static BOOL nulldrv_GetDeviceGammaRamp( PHYSDEV dev, void *ramp )
373 {
374     SetLastError( ERROR_INVALID_PARAMETER );
375     return FALSE;
376 }
377
378 static DWORD nulldrv_GetFontData( PHYSDEV dev, DWORD table, DWORD offset, LPVOID buffer, DWORD length )
379 {
380     return FALSE;
381 }
382
383 static DWORD nulldrv_GetFontUnicodeRanges( PHYSDEV dev, LPGLYPHSET glyphs )
384 {
385     return 0;
386 }
387
388 static DWORD nulldrv_GetGlyphIndices( PHYSDEV dev, LPCWSTR str, INT count, LPWORD indices, DWORD flags )
389 {
390     return GDI_ERROR;
391 }
392
393 static DWORD nulldrv_GetGlyphOutline( PHYSDEV dev, UINT ch, UINT format, LPGLYPHMETRICS metrics,
394                                       DWORD size, LPVOID buffer, const MAT2 *mat )
395 {
396     return GDI_ERROR;
397 }
398
399 static BOOL nulldrv_GetICMProfile( PHYSDEV dev, LPDWORD size, LPWSTR filename )
400 {
401     return FALSE;
402 }
403
404 static DWORD nulldrv_GetImage( PHYSDEV dev, BITMAPINFO *info, struct gdi_image_bits *bits,
405                                struct bitblt_coords *src )
406 {
407     return ERROR_NOT_SUPPORTED;
408 }
409
410 static DWORD nulldrv_GetKerningPairs( PHYSDEV dev, DWORD count, LPKERNINGPAIR pairs )
411 {
412     return 0;
413 }
414
415 static UINT nulldrv_GetOutlineTextMetrics( PHYSDEV dev, UINT size, LPOUTLINETEXTMETRICW otm )
416 {
417     return 0;
418 }
419
420 static UINT nulldrv_GetSystemPaletteEntries( PHYSDEV dev, UINT start, UINT count, PALETTEENTRY *entries )
421 {
422     return 0;
423 }
424
425 static UINT nulldrv_GetTextCharsetInfo( PHYSDEV dev, LPFONTSIGNATURE fs, DWORD flags )
426 {
427     return DEFAULT_CHARSET;
428 }
429
430 static BOOL nulldrv_GetTextExtentExPoint( PHYSDEV dev, LPCWSTR str, INT count, INT *dx )
431 {
432     return FALSE;
433 }
434
435 static BOOL nulldrv_GetTextExtentExPointI( PHYSDEV dev, const WORD *indices, INT count, INT *dx )
436 {
437     return FALSE;
438 }
439
440 static INT nulldrv_GetTextFace( PHYSDEV dev, INT size, LPWSTR name )
441 {
442     INT ret = 0;
443     LOGFONTW font;
444     HFONT hfont = GetCurrentObject( dev->hdc, OBJ_FONT );
445
446     if (GetObjectW( hfont, sizeof(font), &font ))
447     {
448         ret = strlenW( font.lfFaceName ) + 1;
449         if (name)
450         {
451             lstrcpynW( name, font.lfFaceName, size );
452             ret = min( size, ret );
453         }
454     }
455     return ret;
456 }
457
458 static BOOL nulldrv_GetTextMetrics( PHYSDEV dev, TEXTMETRICW *metrics )
459 {
460     return FALSE;
461 }
462
463 static BOOL nulldrv_LineTo( PHYSDEV dev, INT x, INT y )
464 {
465     return TRUE;
466 }
467
468 static BOOL nulldrv_MoveTo( PHYSDEV dev, INT x, INT y )
469 {
470     return TRUE;
471 }
472
473 static BOOL nulldrv_PaintRgn( PHYSDEV dev, HRGN rgn )
474 {
475     return TRUE;
476 }
477
478 static BOOL nulldrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
479 {
480     return TRUE;
481 }
482
483 static BOOL nulldrv_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
484                          INT xstart, INT ystart, INT xend, INT yend )
485 {
486     return TRUE;
487 }
488
489 static BOOL nulldrv_PolyPolygon( PHYSDEV dev, const POINT *points, const INT *counts, UINT polygons )
490 {
491     return TRUE;
492 }
493
494 static BOOL nulldrv_PolyPolyline( PHYSDEV dev, const POINT *points, const DWORD *counts, DWORD lines )
495 {
496     return TRUE;
497 }
498
499 static BOOL nulldrv_Polygon( PHYSDEV dev, const POINT *points, INT count )
500 {
501     INT counts[1] = { count };
502
503     return PolyPolygon( dev->hdc, points, counts, 1 );
504 }
505
506 static BOOL nulldrv_Polyline( PHYSDEV dev, const POINT *points, INT count )
507 {
508     DWORD counts[1] = { count };
509
510     if (count < 0) return FALSE;
511     return PolyPolyline( dev->hdc, points, counts, 1 );
512 }
513
514 static DWORD nulldrv_PutImage( PHYSDEV dev, HRGN clip, BITMAPINFO *info,
515                                const struct gdi_image_bits *bits, struct bitblt_coords *src,
516                                struct bitblt_coords *dst, DWORD rop )
517 {
518     return ERROR_SUCCESS;
519 }
520
521 static UINT nulldrv_RealizeDefaultPalette( PHYSDEV dev )
522 {
523     return 0;
524 }
525
526 static UINT nulldrv_RealizePalette( PHYSDEV dev, HPALETTE palette, BOOL primary )
527 {
528     return 0;
529 }
530
531 static BOOL nulldrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
532 {
533     return TRUE;
534 }
535
536 static HDC nulldrv_ResetDC( PHYSDEV dev, const DEVMODEW *devmode )
537 {
538     return 0;
539 }
540
541 static BOOL nulldrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
542                                INT ell_width, INT ell_height )
543 {
544     return TRUE;
545 }
546
547 static HBITMAP nulldrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap )
548 {
549     return bitmap;
550 }
551
552 static HBRUSH nulldrv_SelectBrush( PHYSDEV dev, HBRUSH brush, const struct brush_pattern *pattern )
553 {
554     return brush;
555 }
556
557 static HPALETTE nulldrv_SelectPalette( PHYSDEV dev, HPALETTE palette, BOOL bkgnd )
558 {
559     return palette;
560 }
561
562 static HPEN nulldrv_SelectPen( PHYSDEV dev, HPEN pen, const struct brush_pattern *pattern )
563 {
564     return pen;
565 }
566
567 static INT nulldrv_SetArcDirection( PHYSDEV dev, INT dir )
568 {
569     return dir;
570 }
571
572 static COLORREF nulldrv_SetBkColor( PHYSDEV dev, COLORREF color )
573 {
574     return color;
575 }
576
577 static INT nulldrv_SetBkMode( PHYSDEV dev, INT mode )
578 {
579     return mode;
580 }
581
582 static UINT nulldrv_SetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags )
583 {
584     return DCB_RESET;
585 }
586
587 static COLORREF nulldrv_SetDCBrushColor( PHYSDEV dev, COLORREF color )
588 {
589     return color;
590 }
591
592 static COLORREF nulldrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
593 {
594     return color;
595 }
596
597 static void nulldrv_SetDeviceClipping( PHYSDEV dev, HRGN rgn )
598 {
599 }
600
601 static DWORD nulldrv_SetLayout( PHYSDEV dev, DWORD layout )
602 {
603     return layout;
604 }
605
606 static BOOL nulldrv_SetDeviceGammaRamp( PHYSDEV dev, void *ramp )
607 {
608     SetLastError( ERROR_INVALID_PARAMETER );
609     return FALSE;
610 }
611
612 static DWORD nulldrv_SetMapperFlags( PHYSDEV dev, DWORD flags )
613 {
614     return flags;
615 }
616
617 static COLORREF nulldrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
618 {
619     return color;
620 }
621
622 static INT nulldrv_SetPolyFillMode( PHYSDEV dev, INT mode )
623 {
624     return mode;
625 }
626
627 static INT nulldrv_SetROP2( PHYSDEV dev, INT rop )
628 {
629     return rop;
630 }
631
632 static INT nulldrv_SetRelAbs( PHYSDEV dev, INT mode )
633 {
634     return mode;
635 }
636
637 static INT nulldrv_SetStretchBltMode( PHYSDEV dev, INT mode )
638 {
639     return mode;
640 }
641
642 static UINT nulldrv_SetTextAlign( PHYSDEV dev, UINT align )
643 {
644     return align;
645 }
646
647 static INT nulldrv_SetTextCharacterExtra( PHYSDEV dev, INT extra )
648 {
649     return extra;
650 }
651
652 static COLORREF nulldrv_SetTextColor( PHYSDEV dev, COLORREF color )
653 {
654     return color;
655 }
656
657 static BOOL nulldrv_SetTextJustification( PHYSDEV dev, INT extra, INT breaks )
658 {
659     return TRUE;
660 }
661
662 static INT nulldrv_StartDoc( PHYSDEV dev, const DOCINFOW *info )
663 {
664     return 0;
665 }
666
667 static INT nulldrv_StartPage( PHYSDEV dev )
668 {
669     return 1;
670 }
671
672 static BOOL nulldrv_UnrealizePalette( HPALETTE palette )
673 {
674     return FALSE;
675 }
676
677 static struct opengl_funcs *nulldrv_wine_get_wgl_driver( PHYSDEV dev, UINT version )
678 {
679     return (void *)-1;
680 }
681
682 const struct gdi_dc_funcs null_driver =
683 {
684     nulldrv_AbortDoc,                   /* pAbortDoc */
685     nulldrv_AbortPath,                  /* pAbortPath */
686     nulldrv_AlphaBlend,                 /* pAlphaBlend */
687     nulldrv_AngleArc,                   /* pAngleArc */
688     nulldrv_Arc,                        /* pArc */
689     nulldrv_ArcTo,                      /* pArcTo */
690     nulldrv_BeginPath,                  /* pBeginPath */
691     nulldrv_BlendImage,                 /* pBlendImage */
692     nulldrv_Chord,                      /* pChord */
693     nulldrv_CloseFigure,                /* pCloseFigure */
694     nulldrv_CreateCompatibleDC,         /* pCreateCompatibleDC */
695     nulldrv_CreateDC,                   /* pCreateDC */
696     nulldrv_DeleteDC,                   /* pDeleteDC */
697     nulldrv_DeleteObject,               /* pDeleteObject */
698     nulldrv_DeviceCapabilities,         /* pDeviceCapabilities */
699     nulldrv_Ellipse,                    /* pEllipse */
700     nulldrv_EndDoc,                     /* pEndDoc */
701     nulldrv_EndPage,                    /* pEndPage */
702     nulldrv_EndPath,                    /* pEndPath */
703     nulldrv_EnumFonts,                  /* pEnumFonts */
704     nulldrv_EnumICMProfiles,            /* pEnumICMProfiles */
705     nulldrv_ExcludeClipRect,            /* pExcludeClipRect */
706     nulldrv_ExtDeviceMode,              /* pExtDeviceMode */
707     nulldrv_ExtEscape,                  /* pExtEscape */
708     nulldrv_ExtFloodFill,               /* pExtFloodFill */
709     nulldrv_ExtSelectClipRgn,           /* pExtSelectClipRgn */
710     nulldrv_ExtTextOut,                 /* pExtTextOut */
711     nulldrv_FillPath,                   /* pFillPath */
712     nulldrv_FillRgn,                    /* pFillRgn */
713     nulldrv_FlattenPath,                /* pFlattenPath */
714     nulldrv_FontIsLinked,               /* pFontIsLinked */
715     nulldrv_FrameRgn,                   /* pFrameRgn */
716     nulldrv_GdiComment,                 /* pGdiComment */
717     nulldrv_GdiRealizationInfo,         /* pGdiRealizationInfo */
718     nulldrv_GetBoundsRect,              /* pGetBoundsRect */
719     nulldrv_GetCharABCWidths,           /* pGetCharABCWidths */
720     nulldrv_GetCharABCWidthsI,          /* pGetCharABCWidthsI */
721     nulldrv_GetCharWidth,               /* pGetCharWidth */
722     nulldrv_GetDeviceCaps,              /* pGetDeviceCaps */
723     nulldrv_GetDeviceGammaRamp,         /* pGetDeviceGammaRamp */
724     nulldrv_GetFontData,                /* pGetFontData */
725     nulldrv_GetFontUnicodeRanges,       /* pGetFontUnicodeRanges */
726     nulldrv_GetGlyphIndices,            /* pGetGlyphIndices */
727     nulldrv_GetGlyphOutline,            /* pGetGlyphOutline */
728     nulldrv_GetICMProfile,              /* pGetICMProfile */
729     nulldrv_GetImage,                   /* pGetImage */
730     nulldrv_GetKerningPairs,            /* pGetKerningPairs */
731     nulldrv_GetNearestColor,            /* pGetNearestColor */
732     nulldrv_GetOutlineTextMetrics,      /* pGetOutlineTextMetrics */
733     nulldrv_GetPixel,                   /* pGetPixel */
734     nulldrv_GetSystemPaletteEntries,    /* pGetSystemPaletteEntries */
735     nulldrv_GetTextCharsetInfo,         /* pGetTextCharsetInfo */
736     nulldrv_GetTextExtentExPoint,       /* pGetTextExtentExPoint */
737     nulldrv_GetTextExtentExPointI,      /* pGetTextExtentExPointI */
738     nulldrv_GetTextFace,                /* pGetTextFace */
739     nulldrv_GetTextMetrics,             /* pGetTextMetrics */
740     nulldrv_GradientFill,               /* pGradientFill */
741     nulldrv_IntersectClipRect,          /* pIntersectClipRect */
742     nulldrv_InvertRgn,                  /* pInvertRgn */
743     nulldrv_LineTo,                     /* pLineTo */
744     nulldrv_ModifyWorldTransform,       /* pModifyWorldTransform */
745     nulldrv_MoveTo,                     /* pMoveTo */
746     nulldrv_OffsetClipRgn,              /* pOffsetClipRgn */
747     nulldrv_OffsetViewportOrgEx,        /* pOffsetViewportOrg */
748     nulldrv_OffsetWindowOrgEx,          /* pOffsetWindowOrg */
749     nulldrv_PaintRgn,                   /* pPaintRgn */
750     nulldrv_PatBlt,                     /* pPatBlt */
751     nulldrv_Pie,                        /* pPie */
752     nulldrv_PolyBezier,                 /* pPolyBezier */
753     nulldrv_PolyBezierTo,               /* pPolyBezierTo */
754     nulldrv_PolyDraw,                   /* pPolyDraw */
755     nulldrv_PolyPolygon,                /* pPolyPolygon */
756     nulldrv_PolyPolyline,               /* pPolyPolyline */
757     nulldrv_Polygon,                    /* pPolygon */
758     nulldrv_Polyline,                   /* pPolyline */
759     nulldrv_PolylineTo,                 /* pPolylineTo */
760     nulldrv_PutImage,                   /* pPutImage */
761     nulldrv_RealizeDefaultPalette,      /* pRealizeDefaultPalette */
762     nulldrv_RealizePalette,             /* pRealizePalette */
763     nulldrv_Rectangle,                  /* pRectangle */
764     nulldrv_ResetDC,                    /* pResetDC */
765     nulldrv_RestoreDC,                  /* pRestoreDC */
766     nulldrv_RoundRect,                  /* pRoundRect */
767     nulldrv_SaveDC,                     /* pSaveDC */
768     nulldrv_ScaleViewportExtEx,         /* pScaleViewportExt */
769     nulldrv_ScaleWindowExtEx,           /* pScaleWindowExt */
770     nulldrv_SelectBitmap,               /* pSelectBitmap */
771     nulldrv_SelectBrush,                /* pSelectBrush */
772     nulldrv_SelectClipPath,             /* pSelectClipPath */
773     nulldrv_SelectFont,                 /* pSelectFont */
774     nulldrv_SelectPalette,              /* pSelectPalette */
775     nulldrv_SelectPen,                  /* pSelectPen */
776     nulldrv_SetArcDirection,            /* pSetArcDirection */
777     nulldrv_SetBkColor,                 /* pSetBkColor */
778     nulldrv_SetBkMode,                  /* pSetBkMode */
779     nulldrv_SetBoundsRect,              /* pSetBoundsRect */
780     nulldrv_SetDCBrushColor,            /* pSetDCBrushColor */
781     nulldrv_SetDCPenColor,              /* pSetDCPenColor */
782     nulldrv_SetDIBitsToDevice,          /* pSetDIBitsToDevice */
783     nulldrv_SetDeviceClipping,          /* pSetDeviceClipping */
784     nulldrv_SetDeviceGammaRamp,         /* pSetDeviceGammaRamp */
785     nulldrv_SetLayout,                  /* pSetLayout */
786     nulldrv_SetMapMode,                 /* pSetMapMode */
787     nulldrv_SetMapperFlags,             /* pSetMapperFlags */
788     nulldrv_SetPixel,                   /* pSetPixel */
789     nulldrv_SetPolyFillMode,            /* pSetPolyFillMode */
790     nulldrv_SetROP2,                    /* pSetROP2 */
791     nulldrv_SetRelAbs,                  /* pSetRelAbs */
792     nulldrv_SetStretchBltMode,          /* pSetStretchBltMode */
793     nulldrv_SetTextAlign,               /* pSetTextAlign */
794     nulldrv_SetTextCharacterExtra,      /* pSetTextCharacterExtra */
795     nulldrv_SetTextColor,               /* pSetTextColor */
796     nulldrv_SetTextJustification,       /* pSetTextJustification */
797     nulldrv_SetViewportExtEx,           /* pSetViewportExt */
798     nulldrv_SetViewportOrgEx,           /* pSetViewportOrg */
799     nulldrv_SetWindowExtEx,             /* pSetWindowExt */
800     nulldrv_SetWindowOrgEx,             /* pSetWindowOrg */
801     nulldrv_SetWorldTransform,          /* pSetWorldTransform */
802     nulldrv_StartDoc,                   /* pStartDoc */
803     nulldrv_StartPage,                  /* pStartPage */
804     nulldrv_StretchBlt,                 /* pStretchBlt */
805     nulldrv_StretchDIBits,              /* pStretchDIBits */
806     nulldrv_StrokeAndFillPath,          /* pStrokeAndFillPath */
807     nulldrv_StrokePath,                 /* pStrokePath */
808     nulldrv_UnrealizePalette,           /* pUnrealizePalette */
809     nulldrv_WidenPath,                  /* pWidenPath */
810     nulldrv_wine_get_wgl_driver,        /* wine_get_wgl_driver */
811
812     GDI_PRIORITY_NULL_DRV               /* priority */
813 };
814
815
816 /*****************************************************************************
817  *      DRIVER_GetDriverName
818  *
819  */
820 BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size )
821 {
822     static const WCHAR displayW[] = { 'd','i','s','p','l','a','y',0 };
823     static const WCHAR devicesW[] = { 'd','e','v','i','c','e','s',0 };
824     static const WCHAR display1W[] = {'\\','\\','.','\\','D','I','S','P','L','A','Y','1',0};
825     static const WCHAR empty_strW[] = { 0 };
826     WCHAR *p;
827
828     /* display is a special case */
829     if (!strcmpiW( device, displayW ) ||
830         !strcmpiW( device, display1W ))
831     {
832         lstrcpynW( driver, displayW, size );
833         return TRUE;
834     }
835
836     size = GetProfileStringW(devicesW, device, empty_strW, driver, size);
837     if(!size) {
838         WARN("Unable to find %s in [devices] section of win.ini\n", debugstr_w(device));
839         return FALSE;
840     }
841     p = strchrW(driver, ',');
842     if(!p)
843     {
844         WARN("%s entry in [devices] section of win.ini is malformed.\n", debugstr_w(device));
845         return FALSE;
846     }
847     *p = 0;
848     TRACE("Found %s for %s\n", debugstr_w(driver), debugstr_w(device));
849     return TRUE;
850 }
851
852
853 /***********************************************************************
854  *           GdiConvertToDevmodeW    (GDI32.@)
855  */
856 DEVMODEW * WINAPI GdiConvertToDevmodeW(const DEVMODEA *dmA)
857 {
858     DEVMODEW *dmW;
859     WORD dmW_size, dmA_size;
860
861     dmA_size = dmA->dmSize;
862
863     /* this is the minimal dmSize that XP accepts */
864     if (dmA_size < FIELD_OFFSET(DEVMODEA, dmFields))
865         return NULL;
866
867     if (dmA_size > sizeof(DEVMODEA))
868         dmA_size = sizeof(DEVMODEA);
869
870     dmW_size = dmA_size + CCHDEVICENAME;
871     if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
872         dmW_size += CCHFORMNAME;
873
874     dmW = HeapAlloc(GetProcessHeap(), 0, dmW_size + dmA->dmDriverExtra);
875     if (!dmW) return NULL;
876
877     MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmDeviceName, -1,
878                                    dmW->dmDeviceName, CCHDEVICENAME);
879     /* copy slightly more, to avoid long computations */
880     memcpy(&dmW->dmSpecVersion, &dmA->dmSpecVersion, dmA_size - CCHDEVICENAME);
881
882     if (dmA_size >= FIELD_OFFSET(DEVMODEA, dmFormName) + CCHFORMNAME)
883     {
884         if (dmA->dmFields & DM_FORMNAME)
885             MultiByteToWideChar(CP_ACP, 0, (const char*) dmA->dmFormName, -1,
886                                        dmW->dmFormName, CCHFORMNAME);
887         else
888             dmW->dmFormName[0] = 0;
889
890         if (dmA_size > FIELD_OFFSET(DEVMODEA, dmLogPixels))
891             memcpy(&dmW->dmLogPixels, &dmA->dmLogPixels, dmA_size - FIELD_OFFSET(DEVMODEA, dmLogPixels));
892     }
893
894     if (dmA->dmDriverExtra)
895         memcpy((char *)dmW + dmW_size, (const char *)dmA + dmA_size, dmA->dmDriverExtra);
896
897     dmW->dmSize = dmW_size;
898
899     return dmW;
900 }
901
902
903 /*****************************************************************************
904  *      @ [GDI32.100]
905  *
906  * This should thunk to 16-bit and simply call the proc with the given args.
907  */
908 INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd,
909                                  LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort )
910 {
911     FIXME("(%p, %p, %s, %s, %s)\n", lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
912     return -1;
913 }
914
915 /*****************************************************************************
916  *      @ [GDI32.101]
917  *
918  * This should load the correct driver for lpszDevice and calls this driver's
919  * ExtDeviceModePropSheet proc.
920  *
921  * Note: The driver calls a callback routine for each property sheet page; these
922  * pages are supposed to be filled into the structure pointed to by lpPropSheet.
923  * The layout of this structure is:
924  *
925  * struct
926  * {
927  *   DWORD  nPages;
928  *   DWORD  unknown;
929  *   HPROPSHEETPAGE  pages[10];
930  * };
931  */
932 INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice,
933                                              LPCSTR lpszPort, LPVOID lpPropSheet )
934 {
935     FIXME("(%p, %s, %s, %p)\n", hWnd, lpszDevice, lpszPort, lpPropSheet );
936     return -1;
937 }
938
939 /*****************************************************************************
940  *      @ [GDI32.102]
941  *
942  * This should load the correct driver for lpszDevice and call this driver's
943  * ExtDeviceMode proc.
944  *
945  * FIXME: convert ExtDeviceMode to unicode in the driver interface
946  */
947 INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd,
948                                     LPDEVMODEA lpdmOutput, LPSTR lpszDevice,
949                                     LPSTR lpszPort, LPDEVMODEA lpdmInput,
950                                     LPSTR lpszProfile, DWORD fwMode )
951 {
952     WCHAR deviceW[300];
953     WCHAR bufW[300];
954     char buf[300];
955     HDC hdc;
956     DC *dc;
957     INT ret = -1;
958
959     TRACE("(%p, %p, %s, %s, %p, %s, %d)\n",
960           hwnd, lpdmOutput, lpszDevice, lpszPort, lpdmInput, lpszProfile, fwMode );
961
962     if (!lpszDevice) return -1;
963     if (!MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, deviceW, 300)) return -1;
964
965     if(!DRIVER_GetDriverName( deviceW, bufW, 300 )) return -1;
966
967     if (!WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, 300, NULL, NULL)) return -1;
968
969     if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
970
971     if ((dc = get_dc_ptr( hdc )))
972     {
973         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pExtDeviceMode );
974         ret = physdev->funcs->pExtDeviceMode( buf, hwnd, lpdmOutput, lpszDevice, lpszPort,
975                                               lpdmInput, lpszProfile, fwMode );
976         release_dc_ptr( dc );
977     }
978     DeleteDC( hdc );
979     return ret;
980 }
981
982 /****************************************************************************
983  *      @ [GDI32.103]
984  *
985  * This should load the correct driver for lpszDevice and calls this driver's
986  * AdvancedSetupDialog proc.
987  */
988 INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
989                                           LPDEVMODEA devin, LPDEVMODEA devout )
990 {
991     TRACE("(%p, %s, %p, %p)\n", hwnd, lpszDevice, devin, devout );
992     return -1;
993 }
994
995 /*****************************************************************************
996  *      @ [GDI32.104]
997  *
998  * This should load the correct driver for lpszDevice and calls this driver's
999  * DeviceCapabilities proc.
1000  *
1001  * FIXME: convert DeviceCapabilities to unicode in the driver interface
1002  */
1003 DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort,
1004                                            WORD fwCapability, LPSTR lpszOutput,
1005                                            LPDEVMODEA lpdm )
1006 {
1007     WCHAR deviceW[300];
1008     WCHAR bufW[300];
1009     char buf[300];
1010     HDC hdc;
1011     DC *dc;
1012     INT ret = -1;
1013
1014     TRACE("(%s, %s, %d, %p, %p)\n", lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );
1015
1016     if (!lpszDevice) return -1;
1017     if (!MultiByteToWideChar(CP_ACP, 0, lpszDevice, -1, deviceW, 300)) return -1;
1018
1019     if(!DRIVER_GetDriverName( deviceW, bufW, 300 )) return -1;
1020
1021     if (!WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, 300, NULL, NULL)) return -1;
1022
1023     if (!(hdc = CreateICA( buf, lpszDevice, lpszPort, NULL ))) return -1;
1024
1025     if ((dc = get_dc_ptr( hdc )))
1026     {
1027         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pDeviceCapabilities );
1028         ret = physdev->funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort,
1029                                                    fwCapability, lpszOutput, lpdm );
1030         release_dc_ptr( dc );
1031     }
1032     DeleteDC( hdc );
1033     return ret;
1034 }
1035
1036
1037 /************************************************************************
1038  *             Escape  [GDI32.@]
1039  */
1040 INT WINAPI Escape( HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data )
1041 {
1042     INT ret;
1043     POINT *pt;
1044
1045     switch (escape)
1046     {
1047     case ABORTDOC:
1048         return AbortDoc( hdc );
1049
1050     case ENDDOC:
1051         return EndDoc( hdc );
1052
1053     case GETPHYSPAGESIZE:
1054         pt = out_data;
1055         pt->x = GetDeviceCaps( hdc, PHYSICALWIDTH );
1056         pt->y = GetDeviceCaps( hdc, PHYSICALHEIGHT );
1057         return 1;
1058
1059     case GETPRINTINGOFFSET:
1060         pt = out_data;
1061         pt->x = GetDeviceCaps( hdc, PHYSICALOFFSETX );
1062         pt->y = GetDeviceCaps( hdc, PHYSICALOFFSETY );
1063         return 1;
1064
1065     case GETSCALINGFACTOR:
1066         pt = out_data;
1067         pt->x = GetDeviceCaps( hdc, SCALINGFACTORX );
1068         pt->y = GetDeviceCaps( hdc, SCALINGFACTORY );
1069         return 1;
1070
1071     case NEWFRAME:
1072         return EndPage( hdc );
1073
1074     case SETABORTPROC:
1075         return SetAbortProc( hdc, (ABORTPROC)in_data );
1076
1077     case STARTDOC:
1078         {
1079             DOCINFOA doc;
1080             char *name = NULL;
1081
1082             /* in_data may not be 0 terminated so we must copy it */
1083             if (in_data)
1084             {
1085                 name = HeapAlloc( GetProcessHeap(), 0, in_count+1 );
1086                 memcpy( name, in_data, in_count );
1087                 name[in_count] = 0;
1088             }
1089             /* out_data is actually a pointer to the DocInfo structure and used as
1090              * a second input parameter */
1091             if (out_data) doc = *(DOCINFOA *)out_data;
1092             else
1093             {
1094                 doc.cbSize = sizeof(doc);
1095                 doc.lpszOutput = NULL;
1096                 doc.lpszDatatype = NULL;
1097                 doc.fwType = 0;
1098             }
1099             doc.lpszDocName = name;
1100             ret = StartDocA( hdc, &doc );
1101             HeapFree( GetProcessHeap(), 0, name );
1102             if (ret > 0) ret = StartPage( hdc );
1103             return ret;
1104         }
1105
1106     case QUERYESCSUPPORT:
1107         {
1108             DWORD code;
1109
1110             if (in_count < sizeof(SHORT)) return 0;
1111             code = (in_count < sizeof(DWORD)) ? *(const USHORT *)in_data : *(const DWORD *)in_data;
1112             switch (code)
1113             {
1114             case ABORTDOC:
1115             case ENDDOC:
1116             case GETPHYSPAGESIZE:
1117             case GETPRINTINGOFFSET:
1118             case GETSCALINGFACTOR:
1119             case NEWFRAME:
1120             case QUERYESCSUPPORT:
1121             case SETABORTPROC:
1122             case STARTDOC:
1123                 return TRUE;
1124             }
1125             break;
1126         }
1127     }
1128
1129     /* if not handled internally, pass it to the driver */
1130     return ExtEscape( hdc, escape, in_count, in_data, 0, out_data );
1131 }
1132
1133
1134 /******************************************************************************
1135  *              ExtEscape       [GDI32.@]
1136  *
1137  * Access capabilities of a particular device that are not available through GDI.
1138  *
1139  * PARAMS
1140  *    hdc         [I] Handle to device context
1141  *    nEscape     [I] Escape function
1142  *    cbInput     [I] Number of bytes in input structure
1143  *    lpszInData  [I] Pointer to input structure
1144  *    cbOutput    [I] Number of bytes in output structure
1145  *    lpszOutData [O] Pointer to output structure
1146  *
1147  * RETURNS
1148  *    Success: >0
1149  *    Not implemented: 0
1150  *    Failure: <0
1151  */
1152 INT WINAPI ExtEscape( HDC hdc, INT nEscape, INT cbInput, LPCSTR lpszInData,
1153                       INT cbOutput, LPSTR lpszOutData )
1154 {
1155     PHYSDEV physdev;
1156     INT ret;
1157     DC * dc = get_dc_ptr( hdc );
1158
1159     if (!dc) return 0;
1160     update_dc( dc );
1161     physdev = GET_DC_PHYSDEV( dc, pExtEscape );
1162     ret = physdev->funcs->pExtEscape( physdev, nEscape, cbInput, lpszInData, cbOutput, lpszOutData );
1163     release_dc_ptr( dc );
1164     return ret;
1165 }
1166
1167
1168 /*******************************************************************
1169  *      DrawEscape [GDI32.@]
1170  *
1171  *
1172  */
1173 INT WINAPI DrawEscape(HDC hdc, INT nEscape, INT cbInput, LPCSTR lpszInData)
1174 {
1175     FIXME("DrawEscape, stub\n");
1176     return 0;
1177 }
1178
1179 /*******************************************************************
1180  *      NamedEscape [GDI32.@]
1181  */
1182 INT WINAPI NamedEscape( HDC hdc, LPCWSTR pDriver, INT nEscape, INT cbInput, LPCSTR lpszInData,
1183                         INT cbOutput, LPSTR lpszOutData )
1184 {
1185     FIXME("(%p, %s, %d, %d, %p, %d, %p)\n",
1186           hdc, wine_dbgstr_w(pDriver), nEscape, cbInput, lpszInData, cbOutput,
1187           lpszOutData);
1188     return 0;
1189 }
1190
1191 /*******************************************************************
1192  *      DdQueryDisplaySettingsUniqueness [GDI32.@]
1193  *      GdiEntry13                       [GDI32.@]
1194  */
1195 ULONG WINAPI DdQueryDisplaySettingsUniqueness(VOID)
1196 {
1197     static int warn_once;
1198
1199     if (!warn_once++)
1200         FIXME("stub\n");
1201     return 0;
1202 }