Skip to content
Snippets Groups Projects
Commit 91857a6c authored by Ian Pilcher's avatar Ian Pilcher Committed by Alexandre Julliard
Browse files

Misc. error checking in PostScript driver.

parent ce7f12c4
No related branches found
No related tags found
No related merge requests found
......@@ -10,7 +10,9 @@
#include <stdio.h>
#include <sys/stat.h>
#include <dirent.h>
#include "winnt.h" /* HEAP_ZERO_MEMORY */
#include <limits.h> /* INT_MIN */
#include <float.h> /* FLT_MAX */
#include "winnt.h" /* HEAP_ZERO_MEMORY */
#include "psdrv.h"
#include "options.h"
#include "debugtools.h"
......@@ -22,6 +24,58 @@ DEFAULT_DEBUG_CHANNEL(psdrv);
/* ptr to fonts for which we have afm files */
FONTFAMILY *PSDRV_AFMFontList = NULL;
/*******************************************************************************
* CheckMetrics
*
* Check an AFMMETRICS structure to make sure all elements have been properly
* filled in.
*
*/
static const AFMMETRICS badMetrics =
{
INT_MIN, /* C */
FLT_MAX, /* WX */
NULL, /* N */
{ FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX }, /* B */
NULL /* L */
};
inline static BOOL CheckMetrics(const AFMMETRICS *metrics)
{
if ( metrics->C == badMetrics.C ||
metrics->WX == badMetrics.WX ||
metrics->N == badMetrics.N ||
metrics->B.llx == badMetrics.B.llx ||
metrics->B.lly == badMetrics.B.lly ||
metrics->B.urx == badMetrics.B.urx ||
metrics->B.ury == badMetrics.B.ury )
return FALSE;
return TRUE;
}
/*******************************************************************************
* FreeAFM
*
* Free an AFM structure and any subsidiary objects that have been allocated
*
*/
static void FreeAFM(AFM *afm)
{
if (afm->FontName != NULL)
HeapFree(PSDRV_Heap, 0, afm->FontName);
if (afm->FullName != NULL)
HeapFree(PSDRV_Heap, 0, afm->FullName);
if (afm->FamilyName != NULL)
HeapFree(PSDRV_Heap, 0, afm->FamilyName);
if (afm->EncodingScheme != NULL)
HeapFree(PSDRV_Heap, 0, afm->EncodingScheme);
if (afm->Metrics != NULL)
HeapFree(PSDRV_Heap, 0, afm->Metrics);
HeapFree(PSDRV_Heap, 0, afm);
}
/***********************************************************
*
......@@ -32,21 +86,28 @@ FONTFAMILY *PSDRV_AFMFontList = NULL;
* Actually only collects the widths of numbered chars and puts then in
* afm->CharWidths.
*/
static void PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
static BOOL PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
{
unsigned char line[256], valbuf[256];
unsigned char *cp, *item, *value, *curpos, *endpos;
int i;
AFMMETRICS *metric;
afm->Metrics = metric = HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY,
afm->Metrics = metric = HeapAlloc( PSDRV_Heap, 0,
afm->NumofMetrics * sizeof(AFMMETRICS) );
if (metric == NULL)
return FALSE;
for(i = 0; i < afm->NumofMetrics; i++, metric++) {
*metric = badMetrics;
do {
if(!fgets(line, sizeof(line), fp)) {
ERR("Unexpected EOF\n");
return;
HeapFree(PSDRV_Heap, 0, afm->Metrics);
afm->Metrics = NULL;
return FALSE;
}
cp = line + strlen(line);
do {
......@@ -61,11 +122,21 @@ static void PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
while(isspace(*item))
item++;
value = strpbrk(item, " \t");
if (!value) { ERR("No whitespace found.\n");return;}
if (!value) {
ERR("No whitespace found.\n");
HeapFree(PSDRV_Heap, 0, afm->Metrics);
afm->Metrics = NULL;
return FALSE;
}
while(isspace(*value))
value++;
cp = endpos = strchr(value, ';');
if (!cp) { ERR("missing ;, failed. [%s]\n", line); return; }
if (!cp) {
ERR("missing ;, failed. [%s]\n", line);
HeapFree(PSDRV_Heap, 0, afm->Metrics);
afm->Metrics = NULL;
return FALSE;
}
while(isspace(*--cp))
;
memcpy(valbuf, value, cp - value + 1);
......@@ -104,13 +175,20 @@ static void PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
curpos = endpos + 1;
}
if (CheckMetrics(metric) == FALSE) {
ERR("Error parsing character metrics\n");
HeapFree(PSDRV_Heap, 0, afm->Metrics);
afm->Metrics = NULL;
return FALSE;
}
TRACE("Metrics for '%s' WX = %f B = %f,%f - %f,%f\n",
metric->N->sz, metric->WX, metric->B.llx, metric->B.lly,
metric->B.urx, metric->B.ury);
}
return;
return TRUE;
}
/***********************************************************
......@@ -123,6 +201,7 @@ static void PSDRV_AFMGetCharMetrics(AFM *afm, FILE *fp)
*
* This is not complete (we don't handle kerning yet) and not efficient
*/
static AFM *PSDRV_AFMParse(char const *file)
{
FILE *fp;
......@@ -178,16 +257,31 @@ static AFM *PSDRV_AFMParse(char const *file)
if(!strncmp("FontName", buf, 8)) {
afm->FontName = HEAP_strdupA(PSDRV_Heap, 0, value);
if (afm->FontName == NULL) {
fclose(fp);
FreeAFM(afm);
return NULL;
}
continue;
}
if(!strncmp("FullName", buf, 8)) {
afm->FullName = HEAP_strdupA(PSDRV_Heap, 0, value);
if (afm->FullName == NULL) {
fclose(fp);
FreeAFM(afm);
return NULL;
}
continue;
}
if(!strncmp("FamilyName", buf, 10)) {
afm->FamilyName = HEAP_strdupA(PSDRV_Heap, 0, value);
if (afm->FamilyName == NULL) {
fclose(fp);
FreeAFM(afm);
return NULL;
}
continue;
}
......@@ -264,12 +358,21 @@ static AFM *PSDRV_AFMParse(char const *file)
if(!strncmp("StartCharMetrics", buf, 16)) {
sscanf(value, "%d", &(afm->NumofMetrics) );
PSDRV_AFMGetCharMetrics(afm, fp);
if (PSDRV_AFMGetCharMetrics(afm, fp) == FALSE) {
fclose(fp);
FreeAFM(afm);
return NULL;
}
continue;
}
if(!strncmp("EncodingScheme", buf, 14)) {
afm->EncodingScheme = HEAP_strdupA(PSDRV_Heap, 0, value);
if (afm->EncodingScheme == NULL) {
fclose(fp);
FreeAFM(afm);
return NULL;
}
continue;
}
......@@ -284,11 +387,21 @@ static AFM *PSDRV_AFMParse(char const *file)
if(afm->FontName == NULL) {
WARN("%s contains no FontName.\n", file);
afm->FontName = HEAP_strdupA(PSDRV_Heap, 0, "nofont");
if (afm->FontName == NULL) {
FreeAFM(afm);
return NULL;
}
}
if(afm->FullName == NULL)
afm->FullName = HEAP_strdupA(PSDRV_Heap, 0, afm->FontName);
if(afm->FamilyName == NULL)
afm->FamilyName = HEAP_strdupA(PSDRV_Heap, 0, afm->FontName);
afm->FamilyName = HEAP_strdupA(PSDRV_Heap, 0, afm->FontName);
if (afm->FullName == NULL || afm->FamilyName == NULL) {
FreeAFM(afm);
return NULL;
}
if(afm->Ascender == 0.0)
afm->Ascender = afm->FontBBox.ury;
if(afm->Descender == 0.0)
......@@ -351,7 +464,7 @@ AFM *PSDRV_FindAFMinList(FONTFAMILY *head, char *name)
* Adds an afm to the list whose head is pointed to by head. Creates new
* family node if necessary and always creates a new AFMLISTENTRY.
*/
void PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm)
BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm)
{
FONTFAMILY *family = *head;
FONTFAMILY **insert = head;
......@@ -359,6 +472,9 @@ void PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm)
newafmle = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
sizeof(*newafmle));
if (newafmle == NULL)
return FALSE;
newafmle->afm = afm;
while(family) {
......@@ -371,11 +487,20 @@ void PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm)
if(!family) {
family = HeapAlloc(PSDRV_Heap, HEAP_ZERO_MEMORY,
sizeof(*family));
if (family == NULL) {
HeapFree(PSDRV_Heap, 0, newafmle);
return FALSE;
}
*insert = family;
family->FamilyName = HEAP_strdupA(PSDRV_Heap, 0,
afm->FamilyName);
if (family->FamilyName == NULL) {
HeapFree(PSDRV_Heap, 0, family);
HeapFree(PSDRV_Heap, 0, newafmle);
return FALSE;
}
family->afmlist = newafmle;
return;
return TRUE;
}
tmpafmle = family->afmlist;
......@@ -384,7 +509,7 @@ void PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm)
tmpafmle->next = newafmle;
return;
return TRUE;
}
/**********************************************************
......@@ -446,11 +571,13 @@ static void PSDRV_DumpFontList(void)
*
* PSDRV_GetFontMetrics
*
* Only exported function in this file. Parses all afm files listed in
* [afmfiles] and [afmdirs] of wine.conf .
* Parses all afm files listed in [afmfiles] and [afmdirs] of wine.conf
*
* If this function fails, PSDRV_Init will destroy PSDRV_Heap, so don't worry
* about freeing all the memory that's been allocated.
*/
static void PSDRV_ReadAFMDir(const char* afmdir) {
static BOOL PSDRV_ReadAFMDir(const char* afmdir) {
DIR *dir;
AFM *afm;
......@@ -461,7 +588,12 @@ static void PSDRV_ReadAFMDir(const char* afmdir) {
if (strstr(dent->d_name,".afm")) {
char *afmfn;
afmfn=(char*)HeapAlloc(GetProcessHeap(),0,strlen(afmdir)+strlen(dent->d_name)+2);
afmfn=(char*)HeapAlloc(PSDRV_Heap,0,
strlen(afmdir)+strlen(dent->d_name)+2);
if (afmfn == NULL) {
closedir(dir);
return FALSE;
}
strcpy(afmfn,afmdir);
strcat(afmfn,"/");
strcat(afmfn,dent->d_name);
......@@ -472,13 +604,25 @@ static void PSDRV_ReadAFMDir(const char* afmdir) {
!strcmp(afm->EncodingScheme,"AdobeStandardEncoding")) {
PSDRV_ReencodeCharWidths(afm);
}
PSDRV_AddAFMtoList(&PSDRV_AFMFontList, afm);
if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, afm) == FALSE) {
closedir(dir);
FreeAFM(afm);
return FALSE;
}
}
else {
WARN("Error parsing %s\n", afmfn);
}
HeapFree(GetProcessHeap(),0,afmfn);
HeapFree(PSDRV_Heap,0,afmfn);
}
}
closedir(dir);
}
else {
WARN("Error opening %s\n", afmdir);
}
return TRUE;
}
BOOL PSDRV_GetFontMetrics(void)
......@@ -490,22 +634,29 @@ BOOL PSDRV_GetFontMetrics(void)
if (PSDRV_GlyphListInit() != 0)
return FALSE;
while (PROFILE_EnumWineIniString( "afmfiles", idx++, key, sizeof(key), value, sizeof(value)))
while (PROFILE_EnumWineIniString( "afmfiles", idx++, key, sizeof(key),
value, sizeof(value)))
{
AFM* afm = PSDRV_AFMParse(value);
if (afm)
{
if (afm) {
if(afm->EncodingScheme &&
!strcmp(afm->EncodingScheme, "AdobeStandardEncoding")) {
PSDRV_ReencodeCharWidths(afm);
}
PSDRV_AddAFMtoList(&PSDRV_AFMFontList, afm);
if (PSDRV_AddAFMtoList(&PSDRV_AFMFontList, afm) == FALSE) {
return FALSE;
}
}
else {
WARN("Error parsing %s\n", value);
}
}
for (idx = 0; PROFILE_EnumWineIniString ("afmdirs", idx, key, sizeof (key),
value, sizeof (value)); ++idx)
PSDRV_ReadAFMDir (value);
if (PSDRV_ReadAFMDir (value) == FALSE)
return FALSE;
PSDRV_DumpGlyphList();
PSDRV_DumpFontList();
......
......@@ -219,7 +219,6 @@ static PSDRV_DEVMODEA DefaultDevmode =
/* dummy */ 0
},
{ /* dmDrvPrivate */
/* ppdfilename */ "default.ppd",
/* numInstalledOptions */ 0
}
};
......@@ -467,27 +466,43 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
AFM *afm;
HANDLE hPrinter;
const char *ppd = NULL;
char ppdFileName[256];
TRACE("'%s'\n", name);
/*
* If this loop completes, last will point to the 'next' element of the
* final PRINTERINFO in the list
*/
for( ; pi; last = &pi->next, pi = pi->next)
if(!strcmp(pi->FriendlyName, name))
return pi;
pi = *last = HeapAlloc( PSDRV_Heap, 0, sizeof(*pi) );
pi = *last = HeapAlloc( PSDRV_Heap, HEAP_ZERO_MEMORY, sizeof(*pi) );
if (pi == NULL)
return NULL;
pi->FriendlyName = HEAP_strdupA( PSDRV_Heap, 0, name );
if (pi->FriendlyName == NULL)
goto fail;
/* Use Get|SetPrinterDataExA instead? */
res = DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
NULL, 0, &needed );
if(res == ERROR_INVALID_PRINTER_NAME || needed != sizeof(DefaultDevmode)) {
pi->Devmode = HeapAlloc( PSDRV_Heap, 0, sizeof(DefaultDevmode) );
if (pi->Devmode == NULL)
goto cleanup;
memcpy(pi->Devmode, &DefaultDevmode, sizeof(DefaultDevmode) );
strcpy(pi->Devmode->dmPublic.dmDeviceName,name);
DrvSetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE,
REG_BINARY, (LPBYTE)&DefaultDevmode, sizeof(DefaultDevmode) );
/* need to do something here AddPrinter?? */
} else {
}
else {
pi->Devmode = HeapAlloc( PSDRV_Heap, 0, needed );
DrvGetPrinterData16((LPSTR)name, (LPSTR)INT_PD_DEFAULT_DEVMODE, &type,
(LPBYTE)pi->Devmode, needed, &needed);
......@@ -497,29 +512,48 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
ERR ("OpenPrinterA failed with code %li\n", GetLastError ());
goto cleanup;
}
pi->Devmode->dmDrvPrivate.ppdFileName[0]='\0';
ppdFileName[0]='\0';
#ifdef HAVE_CUPS
{
ppd = cupsGetPPD(name);
if (ppd) {
strcpy(pi->Devmode->dmDrvPrivate.ppdFileName,ppd);
res = ERROR_SUCCESS;
/* we should unlink() that file later */
} else {
strncpy(ppdFileName, ppd, sizeof(ppdFileName));
res = ERROR_SUCCESS;
/* we should unlink() that file later */
}
else {
ERR("Did not find ppd for %s\n",name);
}
}
#endif
if (!pi->Devmode->dmDrvPrivate.ppdFileName[0]) {
res = GetPrinterDataA (hPrinter, "PPD File", NULL,
pi->Devmode->dmDrvPrivate.ppdFileName, 256, &needed);
if (!ppdFileName[0]) {
res = GetPrinterDataA (hPrinter, "PPD File", NULL, ppdFileName,
sizeof(ppdFileName), &needed);
}
if (res != ERROR_SUCCESS) {
ERR ("Error %li getting PPD file name for printer '%s'\n", res, name);
goto closeprinter;
}
ppdFileName[sizeof(ppdFileName) - 1] = '\0';
pi->ppd = PSDRV_ParsePPD(ppdFileName);
if(!pi->ppd) {
MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
ppdFileName);
goto closeprinter;
}
/*
* This is a hack. The default paper size should be read in as part of
* the Devmode structure, but Wine doesn't currently provide a convenient
* way to configure printers.
*/
res = GetPrinterDataA (hPrinter, "Paper Size", NULL, (LPBYTE) &dwPaperSize,
sizeof (DWORD), &needed);
if (res == ERROR_SUCCESS)
......@@ -533,10 +567,10 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
res = EnumPrinterDataExA (hPrinter, "PrinterDriverData\\FontSubTable", NULL,
0, &needed, &pi->FontSubTableSize);
if (res == ERROR_SUCCESS)
if (res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND) {
TRACE ("No 'FontSubTable' for printer '%s'\n", name);
else if (res == ERROR_MORE_DATA)
{
}
else if (res == ERROR_MORE_DATA) {
pi->FontSubTable = HeapAlloc (PSDRV_Heap, 0, needed);
if (pi->FontSubTable == NULL) {
ERR ("Failed to allocate %li bytes from heap\n", needed);
......@@ -550,9 +584,10 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
ERR ("EnumPrinterDataExA returned %li\n", res);
goto closeprinter;
}
} else {
FIXME ("EnumPrinterDataExA returned %li\n", res);
/* ignore error */
}
else {
ERR("EnumPrinterDataExA returned %li\n", res);
goto closeprinter;
}
if (ClosePrinter (hPrinter) == 0) {
......@@ -560,22 +595,21 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
goto cleanup;
}
pi->ppd = PSDRV_ParsePPD(pi->Devmode->dmDrvPrivate.ppdFileName);
if(!pi->ppd) {
MESSAGE("Couldn't find PPD file '%s', expect a crash now!\n",
pi->Devmode->dmDrvPrivate.ppdFileName);
goto cleanup;
}
pi->next = NULL;
pi->Fonts = NULL;
for(font = pi->ppd->InstalledFonts; font; font = font->next) {
afm = PSDRV_FindAFMinList(PSDRV_AFMFontList, font->Name);
if(!afm)
TRACE( "Couldn't find AFM file for installed printer font '%s' - ignoring\n", font->Name);
else
PSDRV_AddAFMtoList(&pi->Fonts, afm);
if(!afm) {
TRACE( "Couldn't find AFM file for installed printer font '%s' - "
"ignoring\n", font->Name);
}
else {
if (PSDRV_AddAFMtoList(&pi->Fonts, afm) == FALSE) {
PSDRV_FreeAFMList(pi->Fonts);
goto cleanup;
}
}
}
if (ppd) unlink(ppd);
......@@ -584,9 +618,13 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name)
closeprinter:
ClosePrinter(hPrinter);
cleanup:
HeapFree (PSDRV_Heap, 0, pi->FontSubTable);
HeapFree(PSDRV_Heap, 0, pi->FriendlyName);
HeapFree(PSDRV_Heap, 0, pi->Devmode);
if (pi->FontSubTable)
HeapFree(PSDRV_Heap, 0, pi->FontSubTable);
if (pi->FriendlyName)
HeapFree(PSDRV_Heap, 0, pi->FriendlyName);
if (pi->Devmode)
HeapFree(PSDRV_Heap, 0, pi->Devmode);
fail:
HeapFree(PSDRV_Heap, 0, pi);
if (ppd) unlink(ppd);
*last = NULL;
......
......@@ -170,7 +170,6 @@ typedef struct {
int dummy;
} dmDocPrivate;
struct _tagdrvprivate {
char ppdFileName[256]; /* Hack */
UINT numInstalledOptions; /* Options at end of struct */
} dmDrvPrivate;
......@@ -274,7 +273,7 @@ extern BOOL PSDRV_GetFontMetrics(void);
extern PPD *PSDRV_ParsePPD(char *fname);
extern PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name);
extern AFM *PSDRV_FindAFMinList(FONTFAMILY *head, char *name);
extern void PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm);
extern BOOL PSDRV_AddAFMtoList(FONTFAMILY **head, AFM *afm);
extern void PSDRV_FreeAFMList( FONTFAMILY *head );
extern BOOL WINAPI PSDRV_Init(HINSTANCE hinst, DWORD reason, LPVOID reserved);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment