Make paper size and bin type handling more like Windows drivers.
[wine] / dlls / wineps / init.c
1 /*
2  *      PostScript driver initialization functions
3  *
4  *      Copyright 1998 Huw D M Davies
5  *
6  */
7 #include <string.h>
8
9 #include "gdi.h"
10 #include "psdrv.h"
11 #include "debugtools.h"
12 #include "heap.h"
13 #include "winreg.h"
14 #include "winspool.h"
15 #include "winerror.h"
16 #include "options.h"
17
18 DEFAULT_DEBUG_CHANNEL(psdrv);
19
20 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
21                                LPCSTR output, const DEVMODEA* initData );
22 static BOOL PSDRV_DeleteDC( DC *dc );
23
24 static const DC_FUNCTIONS PSDRV_Funcs =
25 {
26     NULL,                            /* pAbortDoc */
27     NULL,                            /* pAbortPath */
28     NULL,                            /* pAngleArc */
29     PSDRV_Arc,                       /* pArc */
30     NULL,                            /* pArcTo */
31     NULL,                            /* pBeginPath */
32     NULL,                            /* pBitBlt */
33     NULL,                            /* pBitmapBits */
34     NULL,                            /* pChoosePixelFormat */
35     PSDRV_Chord,                     /* pChord */
36     NULL,                            /* pCloseFigure */
37     NULL,                            /* pCreateBitmap */
38     PSDRV_CreateDC,                  /* pCreateDC */
39     NULL,                            /* pCreateDIBSection */
40     NULL,                            /* pCreateDIBSection16 */
41     PSDRV_DeleteDC,                  /* pDeleteDC */
42     NULL,                            /* pDeleteObject */
43     NULL,                            /* pDescribePixelFormat */
44     PSDRV_DeviceCapabilities,        /* pDeviceCapabilities */
45     PSDRV_Ellipse,                   /* pEllipse */
46     PSDRV_EndDoc,                    /* pEndDoc */
47     PSDRV_EndPage,                   /* pEndPage */
48     NULL,                            /* pEndPath */
49     PSDRV_EnumDeviceFonts,           /* pEnumDeviceFonts */
50     PSDRV_Escape,                    /* pEscape */
51     NULL,                            /* pExcludeClipRect */
52     PSDRV_ExtDeviceMode,             /* pExtDeviceMode */
53     NULL,                            /* pExtFloodFill */
54     PSDRV_ExtTextOut,                /* pExtTextOut */
55     NULL,                            /* pFillPath */
56     NULL,                            /* pFillRgn */
57     NULL,                            /* pFlattenPath */
58     NULL,                            /* pFrameRgn */
59     PSDRV_GetCharWidth,              /* pGetCharWidth */
60     NULL,                            /* pGetDCOrgEx */
61     NULL,                            /* pGetDeviceGammaRamp */
62     NULL,                            /* pGetPixel */
63     NULL,                            /* pGetPixelFormat */
64     PSDRV_GetTextExtentPoint,        /* pGetTextExtentPoint */
65     PSDRV_GetTextMetrics,            /* pGetTextMetrics */
66     NULL,                            /* pIntersectClipRect */
67     NULL,                            /* pInvertRgn */
68     PSDRV_LineTo,                    /* pLineTo */
69     NULL,                            /* pMoveTo */
70     NULL,                            /* pOffsetClipRgn */
71     NULL,                            /* pOffsetViewportOrg (optional) */
72     NULL,                            /* pOffsetWindowOrg (optional) */
73     NULL,                            /* pPaintRgn */
74     PSDRV_PatBlt,                    /* pPatBlt */
75     PSDRV_Pie,                       /* pPie */
76     NULL,                            /* pPolyBezier */
77     NULL,                            /* pPolyBezierTo */
78     NULL,                            /* pPolyDraw */
79     PSDRV_PolyPolygon,               /* pPolyPolygon */
80     PSDRV_PolyPolyline,              /* pPolyPolyline */
81     PSDRV_Polygon,                   /* pPolygon */
82     PSDRV_Polyline,                  /* pPolyline */
83     NULL,                            /* pPolylineTo */
84     NULL,                            /* pRealizePalette */
85     PSDRV_Rectangle,                 /* pRectangle */
86     NULL,                            /* pRestoreDC */
87     PSDRV_RoundRect,                 /* pRoundRect */
88     NULL,                            /* pSaveDC */
89     NULL,                            /* pScaleViewportExt (optional) */
90     NULL,                            /* pScaleWindowExt (optional) */
91     NULL,                            /* pSelectClipPath */
92     NULL,                            /* pSelectClipRgn */
93     PSDRV_SelectObject,              /* pSelectObject */
94     NULL,                            /* pSelectPalette */
95     PSDRV_SetBkColor,                /* pSetBkColor */
96     NULL,                            /* pSetBkMode */
97     PSDRV_SetDeviceClipping,         /* pSetDeviceClipping */
98     NULL,                            /* pSetDeviceGammaRamp */
99     NULL,                            /* pSetDIBitsToDevice */
100     NULL,                            /* pSetMapMode (optional) */
101     NULL,                            /* pSetMapperFlags */
102     PSDRV_SetPixel,                  /* pSetPixel */
103     NULL,                            /* pSetPixelFormat */
104     NULL,                            /* pSetPolyFillMode */
105     NULL,                            /* pSetROP2 */
106     NULL,                            /* pSetRelAbs */
107     NULL,                            /* pSetStretchBltMode */
108     NULL,                            /* pSetTextAlign */
109     NULL,                            /* pSetTextCharacterExtra */
110     PSDRV_SetTextColor,              /* pSetTextColor */
111     NULL,                            /* pSetTextJustification */
112     NULL,                            /* pSetViewportExt (optional) */
113     NULL,                            /* pSetViewportOrg (optional) */
114     NULL,                            /* pSetWindowExt (optional) */
115     NULL,                            /* pSetWindowOrg (optional) */
116     PSDRV_StartDoc,                  /* pStartDoc */
117     PSDRV_StartPage,                 /* pStartPage */
118     NULL,                            /* pStretchBlt */
119     PSDRV_StretchDIBits,             /* pStretchDIBits */
120     NULL,                            /* pStrokeAndFillPath */
121     NULL,                            /* pStrokePath */
122     NULL,                            /* pSwapBuffers */
123     NULL                             /* pWidenPath */
124 };
125
126
127 /* Default entries for devcaps */
128
129 static DeviceCaps PSDRV_DevCaps = {
130 /* version */           0, 
131 /* technology */        DT_RASPRINTER,
132 /* horzSize */          210,
133 /* vertSize */          297,
134 /* horzRes */           4961,
135 /* vertRes */           7016, 
136 /* bitsPixel */         1,
137 /* planes */            1,
138 /* numBrushes */        -1,
139 /* numPens */           10,
140 /* numMarkers */        0,
141 /* numFonts */          39,
142 /* numColors */         2,
143 /* pdeviceSize */       0,      
144 /* curveCaps */         CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES |
145                         CC_WIDE | CC_STYLED | CC_WIDESTYLED | CC_INTERIORS |
146                         CC_ROUNDRECT,
147 /* lineCaps */          LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
148                         LC_STYLED | LC_WIDESTYLED | LC_INTERIORS,
149 /* polygoalnCaps */     PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON |
150                         PC_SCANLINE | PC_WIDE | PC_STYLED | PC_WIDESTYLED |
151                         PC_INTERIORS,
152 /* textCaps */          TC_CR_ANY, /* psdrv 0x59f7 */
153 /* clipCaps */          CP_RECTANGLE,
154 /* rasterCaps */        RC_BITBLT | RC_BITMAP64 | RC_GDI20_OUTPUT |
155                         RC_DIBTODEV | RC_STRETCHBLT |
156                         RC_STRETCHDIB, /* psdrv 0x6e99 */
157 /* aspectX */           600,
158 /* aspectY */           600,
159 /* aspectXY */          848,
160 /* pad1 */              { 0 },
161 /* logPixelsX */        600,
162 /* logPixelsY */        600, 
163 /* pad2 */              { 0 },
164 /* palette size */      0,
165 /* ..etc */             0, 0 };
166
167 static PSDRV_DEVMODEA DefaultDevmode = 
168 {
169   { /* dmPublic */
170 /* dmDeviceName */      "Wine PostScript Driver",
171 /* dmSpecVersion */     0x30a,
172 /* dmDriverVersion */   0x001,
173 /* dmSize */            sizeof(DEVMODEA),
174 /* dmDriverExtra */     0,
175 /* dmFields */          DM_ORIENTATION | DM_PAPERSIZE | DM_SCALE | 
176                         DM_COPIES | DM_DEFAULTSOURCE | DM_COLOR | 
177                         DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION,
178    { /* u1 */
179      { /* s1 */
180 /* dmOrientation */     DMORIENT_PORTRAIT,
181 /* dmPaperSize */       DMPAPER_A4,
182 /* dmPaperLength */     2969,
183 /* dmPaperWidth */      2101
184      }
185    },
186 /* dmScale */           100, /* ?? */
187 /* dmCopies */          1,
188 /* dmDefaultSource */   DMBIN_AUTO,
189 /* dmPrintQuality */    0,
190 /* dmColor */           DMCOLOR_MONOCHROME,
191 /* dmDuplex */          0,
192 /* dmYResolution */     0,
193 /* dmTTOption */        DMTT_SUBDEV,
194 /* dmCollate */         0,
195 /* dmFormName */        "",
196 /* dmUnusedPadding */   0,
197 /* dmBitsPerPel */      0,
198 /* dmPelsWidth */       0,
199 /* dmPelsHeight */      0,
200 /* dmDisplayFlags */    0,
201 /* dmDisplayFrequency */ 0,
202 /* dmICMMethod */       0,
203 /* dmICMIntent */       0,
204 /* dmMediaType */       0,
205 /* dmDitherType */      0,
206 /* dmReserved1 */       0,
207 /* dmReserved2 */       0,
208 /* dmPanningWidth */    0,
209 /* dmPanningHeight */   0
210   },
211   { /* dmDocPrivate */
212     /* dummy */ 0
213   },
214   { /* dmDrvPrivate */
215     /* ppdfilename */         "default.ppd", 
216     /* numInstalledOptions */ 0 
217   }
218 };
219
220 HANDLE PSDRV_Heap = 0;
221
222 static HANDLE PSDRV_DefaultFont = 0;
223 static LOGFONTA DefaultLogFont = {
224     100, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0,
225     DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, ""
226 };
227
228 /*********************************************************************
229  *           PSDRV_Init
230  *
231  * Initializes font metrics and registers driver. Called from GDI_Init()
232  *
233  */
234 BOOL WINAPI PSDRV_Init( HINSTANCE hinst, DWORD reason, LPVOID reserved )
235 {
236     TRACE("(0x%4x, 0x%08lx, %p)\n", hinst, reason, reserved);
237    
238     switch(reason) {
239         case DLL_PROCESS_ATTACH:
240                 /* FIXME: return FALSE if we fail any of these steps */
241                 PSDRV_Heap = HeapCreate(0, 0x10000, 0);
242                 PSDRV_GetFontMetrics();
243                 PSDRV_DefaultFont = CreateFontIndirectA(&DefaultLogFont);
244                 /* Register driver as "WINEPS", "WINEPS.DLL" and "WINEPS.DRV"
245                    to allow an easy configuring for users */
246                 DRIVER_RegisterDriver( "WINEPS", &PSDRV_Funcs );
247                 DRIVER_RegisterDriver( "WINEPS.DLL", &PSDRV_Funcs );
248                 DRIVER_RegisterDriver( "WINEPS.DRV", &PSDRV_Funcs );
249                 break;
250         case DLL_PROCESS_DETACH:
251                 DeleteObject( PSDRV_DefaultFont );
252                 HeapDestroy( PSDRV_Heap );
253                 DRIVER_UnregisterDriver( "WINEPS" );
254                 DRIVER_UnregisterDriver( "WINEPS.DLL" );
255                 DRIVER_UnregisterDriver( "WINEPS.DRV" );
256                 break;
257     }
258  
259     return TRUE;
260 }
261
262
263 /**********************************************************************
264  *           PSDRV_CreateDC
265  */
266 static BOOL PSDRV_CreateDC( DC *dc, LPCSTR driver, LPCSTR device,
267                                LPCSTR output, const DEVMODEA* initData )
268 {
269     PSDRV_PDEVICE *physDev;
270     PRINTERINFO *pi;
271     DeviceCaps *devCaps;
272     PAGESIZE *page;
273     INT width = 0, height = 0;
274
275     /* If no device name was specified, retrieve the device name
276      * from the DEVMODE structure from the DC's physDev.
277      * (See CreateCompatibleDC) */
278     if ( !device && dc->physDev )
279     {
280         physDev = (PSDRV_PDEVICE *)dc->physDev;
281         device = physDev->Devmode->dmPublic.dmDeviceName;
282     }
283     pi = PSDRV_FindPrinterInfo(device);
284         
285     TRACE("(%s %s %s %p)\n", driver, device, output, initData);
286
287     if(!pi) return FALSE;
288
289     if(!pi->Fonts) {
290         MESSAGE("To use WINEPS you need to install some AFM files.\n");
291         return FALSE;
292     }
293
294     physDev = (PSDRV_PDEVICE *)HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY,
295                                                      sizeof(*physDev) );
296     if (!physDev) return FALSE;
297     dc->physDev = physDev;
298
299     physDev->pi = pi;
300
301     physDev->Devmode = (PSDRV_DEVMODEA *)HeapAlloc( PSDRV_Heap, 0,
302                                                      sizeof(PSDRV_DEVMODEA) );
303     if(!physDev->Devmode) {
304         HeapFree( PSDRV_Heap, 0, physDev );
305         return FALSE;
306     }
307     
308     memcpy( physDev->Devmode, pi->Devmode, sizeof(PSDRV_DEVMODEA) );
309
310     if(initData) {
311         PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)initData, pi);
312     }
313
314     
315     devCaps = HeapAlloc( PSDRV_Heap, 0, sizeof(PSDRV_DevCaps) );
316     memcpy(devCaps, &PSDRV_DevCaps, sizeof(PSDRV_DevCaps));
317
318     /* Are aspect[XY] and logPixels[XY] correct? */
319     /* Need to handle different res in x and y => fix ppd */
320     devCaps->aspectX = devCaps->logPixelsX = 
321                                 physDev->pi->ppd->DefaultResolution;
322     devCaps->aspectY = devCaps->logPixelsY = 
323                                 physDev->pi->ppd->DefaultResolution;
324     devCaps->aspectXY = (int)hypot( (double)devCaps->aspectX, 
325                                     (double)devCaps->aspectY );
326
327
328     for(page = pi->ppd->PageSizes; page; page = page->next) {
329         if(page->WinPage == physDev->Devmode->dmPublic.u1.s1.dmPaperSize)
330             break;
331     }
332     if(!page) {
333         FIXME("Can't find page\n");
334         physDev->PageSize.left = 0;
335         physDev->PageSize.right = 0;
336         physDev->PageSize.bottom = 0;
337         physDev->PageSize.top = 0;
338     } else if(page->ImageableArea) { /* PageSize is in device units */
339         physDev->PageSize.left = page->ImageableArea->llx *
340           devCaps->logPixelsX / 72;
341        physDev->PageSize.right = page->ImageableArea->urx *
342           devCaps->logPixelsX / 72;
343        physDev->PageSize.bottom = page->ImageableArea->lly *
344           devCaps->logPixelsY / 72;
345        physDev->PageSize.top = page->ImageableArea->ury *
346           devCaps->logPixelsY / 72;
347     } else {
348         physDev->PageSize.left = physDev->PageSize.bottom = 0;
349         physDev->PageSize.right = page->PaperDimension->x *
350           devCaps->logPixelsX / 72;
351         physDev->PageSize.top = page->PaperDimension->y *
352           devCaps->logPixelsY / 72;
353     }
354     TRACE("PageSize = (%d,%d - %d,%d)\n", physDev->PageSize.left, physDev->PageSize.bottom, physDev->PageSize.right, physDev->PageSize.top);
355
356     /* these are in mm */
357     width = (physDev->PageSize.right - physDev->PageSize.left) * 25.4 /
358       devCaps->logPixelsX;
359     height = (physDev->PageSize.top - physDev->PageSize.bottom) * 25.4 /
360       devCaps->logPixelsY;
361
362     if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
363         devCaps->horzSize = width;
364         devCaps->vertSize = height;
365     } else {
366         devCaps->horzSize = height;
367         devCaps->vertSize = width;
368     }
369
370     devCaps->horzRes = devCaps->logPixelsX * devCaps->horzSize / 25.4;
371     devCaps->vertRes = devCaps->logPixelsY * devCaps->vertSize / 25.4;
372
373     TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
374           "horzRes = %d, vertRes = %d\n",
375           devCaps->horzSize, devCaps->vertSize,
376           devCaps->horzRes, devCaps->vertRes);
377
378     if(physDev->pi->ppd->ColorDevice) {
379         devCaps->bitsPixel = 8;
380         devCaps->numColors = 256;
381         /* FIXME are these values OK? */
382     }
383
384     /* etc */
385
386     dc->devCaps = devCaps;
387
388     dc->hVisRgn = CreateRectRgn(0, 0, dc->devCaps->horzRes,
389                             dc->devCaps->vertRes);
390     
391     dc->hFont = PSDRV_DefaultFont;
392     physDev->job.output = output ?
393       HEAP_strdupA( PSDRV_Heap, 0, output ) :
394       HEAP_strdupA( PSDRV_Heap, 0, "LPT1:" );  /* HACK */
395     physDev->job.hJob = 0;
396     return TRUE;
397 }
398
399
400 /**********************************************************************
401  *           PSDRV_DeleteDC
402  */
403 static BOOL PSDRV_DeleteDC( DC *dc )
404 {
405     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
406     
407     TRACE("\n");
408
409     HeapFree( PSDRV_Heap, 0, physDev->Devmode );
410     HeapFree( PSDRV_Heap, 0, physDev->job.output );
411     HeapFree( PSDRV_Heap, 0, (void *)dc->devCaps );
412     HeapFree( PSDRV_Heap, 0, physDev );
413     dc->physDev = NULL;
414
415     return TRUE;
416 }
417
418
419 /**********************************************************************
420  *              PSDRV_FindPrinterInfo
421  */
422 PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) 
423 {
424     static PRINTERINFO *PSDRV_PrinterList;
425     DWORD type = REG_BINARY, needed, res, dwPaperSize;
426     PRINTERINFO *pi = PSDRV_PrinterList, **last = &PSDRV_PrinterList;
427     FONTNAME *font;
428     AFM *afm;
429     HANDLE hPrinter;
430
431     TRACE("'%s'\n", name);
432     
433     for( ; pi; last = &pi->next, pi = pi->next) {
434         if(!strcmp(pi->FriendlyName, name))
435             return pi;
436     }
437
438     pi = *last = HeapAlloc( PSDRV_Heap, 0, sizeof(*pi) );
439     pi->FriendlyName = HEAP_strdupA( PSDRV_Heap, 0, name );
440     res = DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
441                             NULL, 0, &needed );
442
443     if(res == ERROR_INVALID_PRINTER_NAME || needed != sizeof(DefaultDevmode)) {
444         pi->Devmode = HeapAlloc( PSDRV_Heap, 0, sizeof(DefaultDevmode) );
445         memcpy(pi->Devmode, &DefaultDevmode, sizeof(DefaultDevmode) );
446         DrvSetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE,
447                  REG_BINARY, (LPBYTE)&DefaultDevmode, sizeof(DefaultDevmode) );
448
449         /* need to do something here AddPrinter?? */
450     } else {
451         pi->Devmode = HeapAlloc( PSDRV_Heap, 0, needed );
452         DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
453                           (LPBYTE)pi->Devmode, needed, &needed);
454     }
455
456     if (OpenPrinterA (pi->FriendlyName, &hPrinter, NULL) == 0)
457     {
458         ERR ("OpenPrinterA failed with code %li\n", GetLastError ());
459         if (HeapFree (PSDRV_Heap, 0, pi->FriendlyName) == 0)
460             WARN ("HeapFree failed with code %li\n", GetLastError ());
461         if (HeapFree (PSDRV_Heap, 0, pi->Devmode) == 0)
462             WARN ("HeapFree failed with code %li\n", GetLastError ());
463         if (HeapFree (PSDRV_Heap, 0, pi) == 0)
464             WARN ("HeapFree failed with code %li\n", GetLastError ());
465         *last = NULL;
466         return NULL;
467     }
468
469     res = GetPrinterDataA (hPrinter, "PPD File", NULL,
470             pi->Devmode->dmDrvPrivate.ppdFileName, 256, &needed);
471     if (res != ERROR_SUCCESS)
472     {
473         ERR ("Error %li getting PPD file name for printer '%s'\n", res, name);
474         if (ClosePrinter (hPrinter) == 0)
475             WARN ("ClosePrinter failed with code %li\n", GetLastError ());
476         if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
477             WARN ("HeapFree failed with code %li\n", GetLastError ());
478         if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
479             WARN ("HeapFree failed with code %li\n", GetLastError ());
480         if (HeapFree(PSDRV_Heap, 0, pi) == 0)
481             WARN ("HeapFree failed with code %li\n", GetLastError ());
482         *last = NULL;
483         return NULL;
484     }
485
486     res = GetPrinterDataA (hPrinter, "Paper Size", NULL, (LPBYTE) &dwPaperSize,
487             sizeof (DWORD), &needed);
488     if (res == ERROR_SUCCESS)
489         pi->Devmode->dmPublic.u1.s1.dmPaperSize = (SHORT) dwPaperSize;
490     else if (res == ERROR_FILE_NOT_FOUND)
491         TRACE ("No 'Paper Size' for printer '%s'\n", name);
492     else
493     {
494         ERR ("GetPrinterDataA returned %li\n", res);
495         if (ClosePrinter (hPrinter) == 0)
496             WARN ("ClosePrinter failed with code %li\n", GetLastError ());
497         if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
498             WARN ("HeapFree failed with code %li\n", GetLastError ());
499         if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
500             WARN ("HeapFree failed with code %li\n", GetLastError ());
501         if (HeapFree(PSDRV_Heap, 0, pi) == 0)
502             WARN ("HeapFree failed with code %li\n", GetLastError ());
503         *last = NULL;
504         return NULL;
505     }
506
507     res = EnumPrinterDataExA (hPrinter, "PrinterDriverData\\FontSubTable", NULL,
508             0, &needed, &pi->FontSubTableSize);
509     if (res == ERROR_SUCCESS)
510         TRACE ("No 'FontSubTable' for printer '%s'\n", name);
511     else if (res == ERROR_MORE_DATA)
512     {
513         pi->FontSubTable = HeapAlloc (PSDRV_Heap, 0, needed);
514         if (pi->FontSubTable == NULL)
515         {
516             ERR ("Failed to allocate %li bytes from heap\n", needed);
517             if (ClosePrinter (hPrinter) == 0)
518                 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
519             if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
520                 WARN ("HeapFree failed with code %li\n", GetLastError ());
521             if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
522                 WARN ("HeapFree failed with code %li\n", GetLastError ());
523             if (HeapFree(PSDRV_Heap, 0, pi) == 0)
524                 WARN ("HeapFree failed with code %li\n", GetLastError ());
525             *last = NULL;
526             return NULL;
527         }
528
529         res = EnumPrinterDataExA (hPrinter, "PrinterDriverData\\FontSubTable",
530                 (LPBYTE) pi->FontSubTable, needed, &needed,
531                 &pi->FontSubTableSize);
532         if (res != ERROR_SUCCESS)
533         {
534             ERR ("EnumPrinterDataExA returned %li\n", res);
535             if (ClosePrinter (hPrinter) == 0)
536                 WARN ("ClosePrinter failed with code %li\n", GetLastError ());
537             if (HeapFree (PSDRV_Heap, 0, pi->FontSubTable) == 0)
538                 WARN ("HeapFree failed with code %li\n", GetLastError ());
539             if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
540                 WARN ("HeapFree failed with code %li\n", GetLastError ());
541             if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
542                 WARN ("HeapFree failed with code %li\n", GetLastError ());
543             if (HeapFree(PSDRV_Heap, 0, pi) == 0)
544                 WARN ("HeapFree failed with code %li\n", GetLastError ());
545             *last = NULL;
546             return NULL;
547         }
548     }
549     else        /* error in 1st call to EnumPrinterDataExA */
550     {
551         ERR ("EnumPrinterDataExA returned %li\n", res);
552         if (ClosePrinter (hPrinter) == 0)
553             WARN ("ClosePrinter failed with code %li\n", GetLastError ());
554         if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
555             WARN ("HeapFree failed with code %li\n", GetLastError ());
556         if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
557             WARN ("HeapFree failed with code %li\n", GetLastError ());
558         if (HeapFree(PSDRV_Heap, 0, pi) == 0)
559             WARN ("HeapFree failed with code %li\n", GetLastError ());
560         *last = NULL;
561         return NULL;
562     }
563
564     if (ClosePrinter (hPrinter) == 0)
565     {
566         ERR ("ClosePrinter failed with code %li\n", GetLastError ());
567         if (ClosePrinter (hPrinter) == 0)
568             WARN ("ClosePrinter failed with code %li\n", GetLastError ());
569         if (HeapFree (PSDRV_Heap, 0, pi->FontSubTable) == 0)
570             WARN ("HeapFree failed with code %li\n", GetLastError ());
571         if (HeapFree(PSDRV_Heap, 0, pi->FriendlyName) == 0)
572             WARN ("HeapFree failed with code %li\n", GetLastError ());
573         if (HeapFree(PSDRV_Heap, 0, pi->Devmode) == 0)
574             WARN ("HeapFree failed with code %li\n", GetLastError ());
575         if (HeapFree(PSDRV_Heap, 0, pi) == 0)
576             WARN ("HeapFree failed with code %li\n", GetLastError ());
577         *last = NULL;
578         return NULL;
579     }
580
581     pi->ppd = PSDRV_ParsePPD(pi->Devmode->dmDrvPrivate.ppdFileName);
582     if(!pi->ppd) {
583         HeapFree(PSDRV_Heap, 0, pi->FontSubTable);
584         HeapFree(PSDRV_Heap, 0, pi->FriendlyName);
585         HeapFree(PSDRV_Heap, 0, pi->Devmode);
586         HeapFree(PSDRV_Heap, 0, pi);
587         *last = NULL;
588         MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
589             pi->Devmode->dmDrvPrivate.ppdFileName);
590         return NULL;
591     }
592
593     pi->next = NULL;
594     pi->Fonts = NULL;
595
596     for(font = pi->ppd->InstalledFonts; font; font = font->next) {
597         afm = PSDRV_FindAFMinList(PSDRV_AFMFontList, font->Name);
598         if(!afm) {
599             TRACE(
600          "Couldn't find AFM file for installed printer font '%s' - ignoring\n",
601          font->Name);
602         } else {
603             PSDRV_AddAFMtoList(&pi->Fonts, afm);
604         }
605     }
606
607     return pi;
608 }