| /* | 
 |  * Graphics driver management functions | 
 |  * | 
 |  * Copyright 1996 Alexandre Julliard | 
 |  */ | 
 |  | 
 | #include <string.h> | 
 | #include "gdi.h" | 
 | #include "heap.h" | 
 | #include "debugtools.h" | 
 |  | 
 | DEFAULT_DEBUG_CHANNEL(driver) | 
 |  | 
 | typedef struct tagGRAPHICS_DRIVER | 
 | { | 
 |     struct tagGRAPHICS_DRIVER *next; | 
 |     LPSTR                      name; | 
 |     const DC_FUNCTIONS        *funcs; | 
 | } GRAPHICS_DRIVER; | 
 |  | 
 | static GRAPHICS_DRIVER *firstDriver = NULL; | 
 | static GRAPHICS_DRIVER *genericDriver = NULL; | 
 |  | 
 | /********************************************************************** | 
 |  *	     DRIVER_RegisterDriver | 
 |  */ | 
 | BOOL DRIVER_RegisterDriver( LPCSTR name, const DC_FUNCTIONS *funcs ) | 
 | { | 
 |     GRAPHICS_DRIVER *driver = HeapAlloc( GetProcessHeap(), 0, sizeof(*driver) ); | 
 |     if (!driver) return FALSE; | 
 |     driver->funcs = funcs; | 
 |     if (name) | 
 |     { | 
 |         driver->name  = HEAP_strdupA( GetProcessHeap(), 0, name ); | 
 |         driver->next  = firstDriver; | 
 |         firstDriver = driver; | 
 |         return TRUE; | 
 |     } | 
 |     /* No name -> it's the generic driver */ | 
 |     if (genericDriver) | 
 |     { | 
 |         WARN(" already a generic driver\n" ); | 
 |         HeapFree( GetProcessHeap(), 0, driver ); | 
 |         return FALSE; | 
 |     } | 
 |     driver->name = NULL; | 
 |     genericDriver = driver; | 
 |     return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************** | 
 |  *	     DRIVER_FindDriver | 
 |  */ | 
 | const DC_FUNCTIONS *DRIVER_FindDriver( LPCSTR name ) | 
 | { | 
 |     GRAPHICS_DRIVER *driver = firstDriver; | 
 |  | 
 |     TRACE(": %s\n", name); | 
 |     while (driver && name) | 
 |     { | 
 |         if (!strcasecmp( driver->name, name )) return driver->funcs; | 
 |         driver = driver->next; | 
 |     } | 
 |     return genericDriver ? genericDriver->funcs : NULL; | 
 | } | 
 |  | 
 |  | 
 | /********************************************************************** | 
 |  *	     DRIVER_UnregisterDriver | 
 |  */ | 
 | BOOL DRIVER_UnregisterDriver( LPCSTR name ) | 
 | { | 
 |     if (name) | 
 |     { | 
 |         GRAPHICS_DRIVER **ppDriver = &firstDriver; | 
 |         while (*ppDriver) | 
 |         { | 
 |             if (!strcasecmp( (*ppDriver)->name, name )) | 
 |             { | 
 |                 GRAPHICS_DRIVER *driver = *ppDriver; | 
 |                 (*ppDriver) = driver->next; | 
 |                 HeapFree( GetProcessHeap(), 0, driver->name ); | 
 |                 HeapFree( GetProcessHeap(), 0, driver ); | 
 |                 return TRUE; | 
 |             } | 
 |             ppDriver = &(*ppDriver)->next; | 
 |         } | 
 |         return FALSE; | 
 |     } | 
 |     else | 
 |     { | 
 |         if (!genericDriver) return FALSE; | 
 |         HeapFree( GetProcessHeap(), 0, genericDriver ); | 
 |         genericDriver = NULL; | 
 |         return TRUE; | 
 |     } | 
 | } | 
 |  | 
 | /***************************************************************************** | 
 |  *      DRIVER_GetDriverName | 
 |  * | 
 |  */ | 
 | BOOL DRIVER_GetDriverName( LPCSTR device, LPSTR driver, DWORD size ) | 
 | { | 
 |     char *p; | 
 |     size = GetProfileStringA("devices", device, "", driver, size); | 
 |     if(!size) { | 
 |         WARN("Unable to find '%s' in [devices] section of win.ini\n", device); | 
 | 	return FALSE; | 
 |     } | 
 |     p = strchr(driver, ','); | 
 |     if(!p) { | 
 |         WARN("'%s' entry in [devices] section of win.ini is malformed.\n", | 
 | 	     device); | 
 | 	return FALSE; | 
 |     } | 
 |     *p = '\0'; | 
 |     TRACE("Found '%s' for '%s'\n", driver, device); | 
 |     return TRUE; | 
 | } | 
 |      | 
 | /***************************************************************************** | 
 |  *      GDI_CallDevInstall16   [GDI32.100] | 
 |  * | 
 |  * This should thunk to 16-bit and simply call the proc with the given args. | 
 |  */ | 
 | INT WINAPI GDI_CallDevInstall16( FARPROC16 lpfnDevInstallProc, HWND hWnd,  | 
 |                                  LPSTR lpModelName, LPSTR OldPort, LPSTR NewPort ) | 
 | { | 
 |     FIXME("(%p, %04x, %s, %s, %s)\n",  | 
 | 	  lpfnDevInstallProc, hWnd, lpModelName, OldPort, NewPort ); | 
 |     return -1; | 
 | } | 
 |  | 
 | /***************************************************************************** | 
 |  *      GDI_CallExtDeviceModePropSheet16   [GDI32.101] | 
 |  * | 
 |  * This should load the correct driver for lpszDevice and calls this driver's | 
 |  * ExtDeviceModePropSheet proc.  | 
 |  * | 
 |  * Note: The driver calls a callback routine for each property sheet page; these  | 
 |  * pages are supposed to be filled into the structure pointed to by lpPropSheet. | 
 |  * The layout of this structure is: | 
 |  *  | 
 |  * struct | 
 |  * { | 
 |  *   DWORD  nPages; | 
 |  *   DWORD  unknown; | 
 |  *   HPROPSHEETPAGE  pages[10]; | 
 |  * }; | 
 |  */ | 
 | INT WINAPI GDI_CallExtDeviceModePropSheet16( HWND hWnd, LPCSTR lpszDevice,  | 
 |                                              LPCSTR lpszPort, LPVOID lpPropSheet ) | 
 | { | 
 |     FIXME("(%04x, %s, %s, %p)\n",  | 
 |       hWnd, lpszDevice, lpszPort, lpPropSheet ); | 
 |     return -1; | 
 | } | 
 |  | 
 | /***************************************************************************** | 
 |  *      GDI_CallExtDeviceMode16   [GDI32.102] | 
 |  * | 
 |  * This should load the correct driver for lpszDevice and calls this driver's | 
 |  * ExtDeviceMode proc. | 
 |  */ | 
 | INT WINAPI GDI_CallExtDeviceMode16( HWND hwnd,  | 
 |                                     LPDEVMODEA lpdmOutput, LPSTR lpszDevice,  | 
 |                                     LPSTR lpszPort, LPDEVMODEA lpdmInput,  | 
 |                                     LPSTR lpszProfile, DWORD fwMode ) | 
 | { | 
 |     char buf[300]; | 
 |     const DC_FUNCTIONS *funcs; | 
 |  | 
 |     TRACE("(%04x, %p, %s, %s, %p, %s, %ld)\n",  | 
 | 	  hwnd, lpdmOutput, lpszDevice, lpszPort,  | 
 | 	  lpdmInput, lpszProfile, fwMode ); | 
 |  | 
 |     if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1; | 
 |     funcs = DRIVER_FindDriver( buf ); | 
 |     if(!funcs || !funcs->pExtDeviceMode) return -1; | 
 |     return funcs->pExtDeviceMode(buf, hwnd, lpdmOutput, lpszDevice, lpszPort, | 
 | 				 lpdmInput, lpszProfile, fwMode); | 
 | } | 
 |  | 
 | /**************************************************************************** | 
 |  *      GDI_CallAdvancedSetupDialog16     [GDI32.103] | 
 |  * | 
 |  * This should load the correct driver for lpszDevice and calls this driver's | 
 |  * AdvancedSetupDialog proc. | 
 |  */ | 
 | INT WINAPI GDI_CallAdvancedSetupDialog16( HWND hwnd, LPSTR lpszDevice, | 
 |                                           LPDEVMODEA devin, LPDEVMODEA devout ) | 
 | { | 
 |     TRACE("(%04x, %s, %p, %p)\n",  | 
 | 	  hwnd, lpszDevice, devin, devout ); | 
 |     return -1; | 
 | } | 
 |  | 
 | /***************************************************************************** | 
 |  *      GDI_CallDeviceCapabilities16      [GDI32.104] | 
 |  * | 
 |  * This should load the correct driver for lpszDevice and calls this driver's | 
 |  * DeviceCapabilities proc. | 
 |  */ | 
 | DWORD WINAPI GDI_CallDeviceCapabilities16( LPCSTR lpszDevice, LPCSTR lpszPort, | 
 |                                            WORD fwCapability, LPSTR lpszOutput, | 
 |                                            LPDEVMODEA lpdm ) | 
 | { | 
 |     char buf[300]; | 
 |     const DC_FUNCTIONS *funcs; | 
 |  | 
 |     TRACE("(%s, %s, %d, %p, %p)\n",  | 
 | 	  lpszDevice, lpszPort, fwCapability, lpszOutput, lpdm ); | 
 |  | 
 |  | 
 |     if(!DRIVER_GetDriverName( lpszDevice, buf, sizeof(buf) )) return -1; | 
 |     funcs = DRIVER_FindDriver( buf ); | 
 |     if(!funcs || !funcs->pDeviceCapabilities) return -1; | 
 |     return funcs->pDeviceCapabilities( buf, lpszDevice, lpszPort, | 
 | 				       fwCapability, lpszOutput, lpdm); | 
 |  | 
 | } | 
 |  | 
 |  |