Fixed a file descriptor leak in the PE loader.
[wine] / graphics / driver.c
1 /*
2  * Graphics driver management functions
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include <string.h>
8 #include "gdi.h"
9 #include "heap.h"
10 #include "debugtools.h"
11
12 DEFAULT_DEBUG_CHANNEL(driver)
13
14 typedef struct tagGRAPHICS_DRIVER
15 {
16     struct tagGRAPHICS_DRIVER *next;
17     LPSTR                      name;
18     const DC_FUNCTIONS        *funcs;
19 } GRAPHICS_DRIVER;
20
21 static GRAPHICS_DRIVER *firstDriver = NULL;
22 static GRAPHICS_DRIVER *genericDriver = NULL;
23
24 /**********************************************************************
25  *           DRIVER_RegisterDriver
26  */
27 BOOL DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs )
28 {
29     GRAPHICS_DRIVER *driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver) );
30     if (!driver) return FALSE;
31     driver->funcs = funcs;
32     if (name)
33     {
34         driver->name  = HEAP_strdupA( GetProcessHeap(), 0, name );
35         driver->next  = firstDriver;
36         firstDriver = driver;
37         return TRUE;
38     }
39     /* No name -> it's the generic driver */
40     if (genericDriver)
41     {
42         WARN(" already a generic driver\n" );
43         HeapFree( GetProcessHeap(), 0, driver );
44         return FALSE;
45     }
46     driver->name = NULL;
47     genericDriver = driver;
48     return TRUE;
49 }
50
51
52 /**********************************************************************
53  *           DRIVER_FindDriver
54  */
55 const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name )
56 {
57     GRAPHICS_DRIVER *driver = firstDriver;
58
59     TRACE(": %s\n", name);
60     while (driver && name)
61     {
62         if (!strcasecmp( driver->name, name )) return driver->funcs;
63         driver = driver->next;
64     }
65     return genericDriver ? genericDriver->funcs : NULL;
66 }
67
68
69 /**********************************************************************
70  *           DRIVER_UnregisterDriver
71  */
72 BOOL DRIVER_UnregisterDriver( LPCSTR name )
73 {
74     if (name)
75     {
76         GRAPHICS_DRIVER **ppDriver = &firstDriver;
77         while (*ppDriver)
78         {
79             if (!strcasecmp( (*ppDriver)->name, name ))
80             {
81                 GRAPHICS_DRIVER *driver = *ppDriver;
82                 (*ppDriver) = driver->next;
83                 HeapFree( GetProcessHeap(), 0, driver->name );
84                 HeapFree( GetProcessHeap(), 0, driver );
85                 return TRUE;
86             }
87             ppDriver = &(*ppDriver)->next;
88         }
89         return FALSE;
90     }
91     else
92     {
93         if (!genericDriver) return FALSE;
94         HeapFree( GetProcessHeap(), 0, genericDriver );
95         genericDriver = NULL;
96         return TRUE;
97     }
98 }
99
100 /*****************************************************************************
101  *      DRIVER_GetDriverName
102  *
103  */
104 BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size )
105 {
106     char *p;
107     size = GetProfileStringA("devices", device, "", driver, size);
108     if(!size) {
109         WARN("Unable to find '%s' in [devices] section of win.ini\n", device);
110         return FALSE;
111     }
112     p = strchr(driver, ',');
113     if(!p) {
114         WARN("'%s' entry in [devices] section of win.ini is malformed.\n",
115              device);
116         return FALSE;
117     }
118     *p = '\0';
119     TRACE("Found '%s' for '%s'\n", driver, device);
120     return TRUE;
121 }
122     
123 /*****************************************************************************
124  *      GDI_CallDevInstall16   [GDI32.100]
125  *
126  * This should thunk to 16-bit and simply call the proc with the given args.
127  */
128 INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd, 
129                                  LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort )
130 {
131     FIXME("(%p, %04x, %s, %s, %s)\n", 
132           lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort );
133     return -1;
134 }
135
136 /*****************************************************************************
137  *      GDI_CallExtDeviceModePropSheet16   [GDI32.101]
138  *
139  * This should load the correct driver for lpszDevice and calls this driver's
140  * ExtDeviceModePropSheet proc. 
141  *
142  * Note: The driver calls a callback routine for each property sheet page; these 
143  * pages are supposed to be filled into the structure pointed to by lpPropSheet.
144  * The layout of this structure is:
145  * 
146  * struct
147  * {
148  *   DWORD  nPages;
149  *   DWORD  unknown;
150  *   HPROPSHEETPAGE  pages[10];
151  * };
152  */
153 INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice, 
154                                              LPCSTR lpszPort, LPVOID lpPropSheet )
155 {
156     FIXME("(%04x, %s, %s, %p)\n", 
157       hWnd, lpszDevice, lpszPort, lpPropSheet );
158     return -1;
159 }
160
161 /*****************************************************************************
162  *      GDI_CallExtDeviceMode16   [GDI32.102]
163  *
164  * This should load the correct driver for lpszDevice and calls this driver's
165  * ExtDeviceMode proc.
166  */
167 INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd, 
168                                     LPDEVMODEA lpdmOutput, LPSTR lpszDevice, 
169                                     LPSTR lpszPort, LPDEVMODEA lpdmInput, 
170                                     LPSTR lpszProfile, DWORD fwMode )
171 {
172     char buf[300];
173     const DC_FUNCTIONS *funcs;
174
175     TRACE("(%04x, %p, %s, %s, %p, %s, %ld)\n", 
176           hwnd, lpdmOutput, lpszDevice, lpszPort, 
177           lpdmInput, lpszProfile, fwMode );
178
179     if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
180     funcs = DRIVER_FindDriver( buf );
181     if(!funcs || !funcs->pExtDeviceMode) return -1;
182     return funcs->pExtDeviceMode(buf, hwnd, lpdmOutput, lpszDevice, lpszPort,
183                                  lpdmInput, lpszProfile, fwMode);
184 }
185
186 /****************************************************************************
187  *      GDI_CallAdvancedSetupDialog16     [GDI32.103]
188  *
189  * This should load the correct driver for lpszDevice and calls this driver's
190  * AdvancedSetupDialog proc.
191  */
192 INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice,
193                                           LPDEVMODEA devin, LPDEVMODEA devout )
194 {
195     TRACE("(%04x, %s, %p, %p)\n", 
196           hwnd, lpszDevice, devin, devout );
197     return -1;
198 }
199
200 /*****************************************************************************
201  *      GDI_CallDeviceCapabilities16      [GDI32.104]
202  *
203  * This should load the correct driver for lpszDevice and calls this driver's
204  * DeviceCapabilities proc.
205  */
206 DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort,
207                                            WORD fwCapability, LPSTR lpszOutput,
208                                            LPDEVMODEA lpdm )
209 {
210     char buf[300];
211     const DC_FUNCTIONS *funcs;
212
213     TRACE("(%s, %s, %d, %p, %p)\n", 
214           lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm );
215
216
217     if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1;
218     funcs = DRIVER_FindDriver( buf );
219     if(!funcs || !funcs->pDeviceCapabilities) return -1;
220     return funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort,
221                                        fwCapability, lpszOutput, lpdm);
222
223 }
224
225