From 0c63012b6dcfac42a4462c261dfd156eaf8cdd7f Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Wed, 9 May 2001 17:10:41 +0000 Subject: [PATCH] Implemented /etc/printcap based printing support. Changed 'CUPS:printername' to 'LPR:printername'. Some fixes in AddPrinterW(). --- dlls/gdi/printdrv.c | 8 +- dlls/wineps/init.c | 18 ++- dlls/winspool/info.c | 271 +++++++++++++++++++++++++++++++++-------- dlls/winspool/wspool.c | 6 +- 4 files changed, 241 insertions(+), 62 deletions(-) diff --git a/dlls/gdi/printdrv.c b/dlls/gdi/printdrv.c index db30e69d66f..40b89a9c812 100644 --- a/dlls/gdi/printdrv.c +++ b/dlls/gdi/printdrv.c @@ -384,7 +384,7 @@ INT16 WINAPI InsertPQ16(HPQ16 hPQ, INT16 tag, INT16 key) { struct hpq *queueItem = HeapAlloc(GetProcessHeap(), 0, sizeof(struct hpq)); if(queueItem == NULL) { - ERR("Memory exausted!"); + ERR("Memory exausted!\n"); return FALSE; } queueItem->next = hpqueue; @@ -456,8 +456,8 @@ static int CreateSpoolFile(LPCSTR pszOutput) if (pszOutput == NULL || *pszOutput == '\0') return -1; - if (!strncmp("CUPS:",pszOutput,5)) - sprintf(psCmd,"|lpr -P%s",pszOutput+5); + if (!strncmp("LPR:",pszOutput,4)) + sprintf(psCmd,"|lpr -P%s",pszOutput+4); else PROFILE_GetWineIniString("spooler",pszOutput,"",psCmd,sizeof(psCmd)); TRACE("Got printerSpoolCommand '%s' for output device '%s'\n", @@ -555,7 +555,7 @@ HPJOB16 WINAPI OpenJob16(LPCSTR lpOutput, LPCSTR lpTitle, HDC16 hDC) { pPrintJob = HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTJOB)); if(pPrintJob == NULL) { - WARN("Memory exausted!"); + WARN("Memory exausted!\n"); return hHandle; } diff --git a/dlls/wineps/init.c b/dlls/wineps/init.c index fada0192b53..00cdbad8fb1 100644 --- a/dlls/wineps/init.c +++ b/dlls/wineps/init.c @@ -522,9 +522,9 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) strncpy(ppdFileName, ppd, sizeof(ppdFileName)); res = ERROR_SUCCESS; /* we should unlink() that file later */ - } - else { - ERR("Did not find ppd for %s\n",name); + } else { + res = ERROR_FILE_NOT_FOUND; + WARN("Did not find ppd for %s\n",name); } } #endif @@ -533,7 +533,17 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) res = GetPrinterDataA (hPrinter, "PPD File", NULL, ppdFileName, sizeof(ppdFileName), &needed); } - + /* Look for a ppd file for this printer in the config file. + * First look for the names of the printer, then for 'generic' + */ + if ((res!=ERROR_SUCCESS) && + !PROFILE_GetWineIniString("ppd",name,"",ppdFileName,sizeof(ppdFileName)) && + !PROFILE_GetWineIniString("ppd","generic","",ppdFileName,sizeof(ppdFileName)) + ) + res = ERROR_FILE_NOT_FOUND; + else + res = ERROR_SUCCESS; + if (res != ERROR_SUCCESS) { ERR ("Error %li getting PPD file name for printer '%s'\n", res, name); goto closeprinter; diff --git a/dlls/winspool/info.c b/dlls/winspool/info.c index a0978dbe451..9bc6e76f133 100644 --- a/dlls/winspool/info.c +++ b/dlls/winspool/info.c @@ -76,46 +76,37 @@ static WCHAR Share_NameW[] = {'S','h','a','r','e',' ','N','a','m','e',0}; static WCHAR WinPrintW[] = {'W','i','n','P','r','i','n','t',0}; static HKEY WINSPOOL_OpenDriverReg( LPVOID pEnvironment, BOOL unicode); +static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment, + DWORD Level, LPBYTE pDriverInfo, + DWORD cbBuf, LPDWORD pcbNeeded, + BOOL unicode); #ifdef HAVE_CUPS -void +BOOL CUPS_LoadPrinters(void) { cups_dest_t *dests; - int i,nrofdests; + int i,nrofdests,hadprinter = FALSE; PRINTER_INFO_2A pinfo2a; - DRIVER_INFO_3A di3a; const char* def = cupsGetDefault(); nrofdests = cupsGetDests(&dests); - di3a.cVersion = 0x400; - di3a.pName = "PS Driver"; - di3a.pEnvironment = NULL; /* NULL means auto */ - di3a.pDriverPath = "wineps.drv"; - di3a.pDataFile = ""; - di3a.pConfigFile = "wineps.drv"; - di3a.pHelpFile = ""; - di3a.pDependentFiles = ""; - di3a.pMonitorName = ""; - di3a.pDefaultDataType = "RAW"; - - - if (!AddPrinterDriverA(NULL,3,(LPBYTE)&di3a)) { - ERR("Failed adding PS Driver (%ld)\n",GetLastError()); - return; - } for (i=0;i=CCHDEVICENAME-1) + devname = name; + if (strlen(devname)>=CCHDEVICENAME-1) + return FALSE; + if (isfirst) { + char *buf = HeapAlloc(GetProcessHeap(),0,strlen(name)+strlen(devname)+strlen(",WINEPS,LPR:")+1); + + sprintf(buf,"%s,WINEPS,LPR:%s",devname,name); + WriteProfileStringA("windows","device",buf); + HeapFree(GetProcessHeap(),0,buf); + } + memset(&pinfo2a,0,sizeof(pinfo2a)); + pinfo2a.pPrinterName = devname; + pinfo2a.pDatatype = "RAW"; + pinfo2a.pPrintProcessor = "WinPrint"; + pinfo2a.pDriverName = "PS Driver"; + pinfo2a.pComment = "WINEPS Printer using LPR"; + pinfo2a.pLocation = prettyname; + port = HeapAlloc(GetProcessHeap(),0,strlen("LPR:")+strlen(name)+1); + sprintf(port,"LPR:%s",name); + pinfo2a.pPortName = port; + pinfo2a.pParameters = ""; + pinfo2a.pShareName = ""; + pinfo2a.pSepFile = ""; + + devline=HeapAlloc(GetProcessHeap(),0,strlen("WINEPS,")+strlen(port)+1); + sprintf(devline,"WINEPS,%s",port); + WriteProfileStringA("devices",devname,devline); + HeapFree(GetProcessHeap(),0,devline); + + if (!AddPrinterA(NULL,2,(LPBYTE)&pinfo2a)) { + if (GetLastError()!=ERROR_PRINTER_ALREADY_EXISTS) + ERR("%s not added by AddPrinterA (%ld)\n",name,GetLastError()); + } + HeapFree(GetProcessHeap(),0,port); + return TRUE; +} + +static BOOL +PRINTCAP_LoadPrinters(void) { + BOOL hadprinter = FALSE, isfirst = TRUE; + char buf[200]; + FILE *f; + + f = fopen("/etc/printcap","r"); + if (!f) + return FALSE; + + while (fgets(buf,sizeof(buf),f)) { + char *pent = NULL; + do { + char *s; + s=strchr(buf,'\n'); if (s) *s='\0'; + if ((buf[0]=='#') || (buf[0]=='\0')) + continue; + + if (pent) { + pent=HeapReAlloc(GetProcessHeap(),0,pent,strlen(pent)+strlen(buf)+2); + strcat(pent,buf); + } else { + pent=HeapAlloc(GetProcessHeap(),0,strlen(buf)+1); + strcpy(pent,buf); + } + + if (strlen(pent) && (pent[strlen(pent)-1] == '\\')) + pent[strlen(pent)-1] = '\0'; + else + break; + } while (fgets(buf,sizeof(buf),f)); + if (pent) + hadprinter |= PRINTCAP_ParseEntry(pent,isfirst); + isfirst = FALSE; + if (pent) HeapFree(GetProcessHeap(),0,pent); + pent = NULL; + if (feof(f)) break; + } + fclose(f); + return hadprinter; +} + +void +WINSPOOL_LoadSystemPrinters() { + DRIVER_INFO_3A di3a; + di3a.cVersion = 0x400; + di3a.pName = "PS Driver"; + di3a.pEnvironment = NULL; /* NULL means auto */ + di3a.pDriverPath = "wineps.drv"; + di3a.pDataFile = ""; + di3a.pConfigFile = "wineps.drv"; + di3a.pHelpFile = ""; + di3a.pDependentFiles = ""; + di3a.pMonitorName = ""; + di3a.pDefaultDataType = "RAW"; + + if (!AddPrinterDriverA(NULL,3,(LPBYTE)&di3a)) { + ERR("Failed adding PS Driver (%ld)\n",GetLastError()); + return; + } +#ifdef HAVE_CUPS + /* If we have any CUPS based printers, skip looking for printcap printers */ + if (CUPS_LoadPrinters()) + return; +#endif + PRINTCAP_LoadPrinters(); +} + /****************************************************************** * WINSPOOL_GetOpenedPrinterEntry @@ -792,6 +944,13 @@ HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) SetLastError(ERROR_INVALID_LEVEL); return 0; } + if (strlenW(pi->pPrinterName) >= CCHDEVICENAME) { + ERR("Printername %s must not exceed length of DEVMODE.dmDeviceName !\n", + debugstr_w(pi->pPrinterName) + ); + SetLastError(ERROR_INVALID_LEVEL); + return 0; + } if(!pPrinter) { SetLastError(ERROR_INVALID_PARAMETER); return 0; @@ -801,12 +960,14 @@ HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) ERR("Can't create Printers key\n"); return 0; } - if(RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) == - ERROR_SUCCESS) { - SetLastError(ERROR_PRINTER_ALREADY_EXISTS); + if(!RegOpenKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter)) { + if (!RegQueryValueA(hkeyPrinter,"Attributes",NULL,NULL)) { + SetLastError(ERROR_PRINTER_ALREADY_EXISTS); + RegCloseKey(hkeyPrinter); + RegCloseKey(hkeyPrinters); + return 0; + } RegCloseKey(hkeyPrinter); - RegCloseKey(hkeyPrinters); - return 0; } hkeyDrivers = WINSPOOL_OpenDriverReg( NULL, TRUE); if(!hkeyDrivers) { @@ -832,34 +993,44 @@ HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) return 0; } - /* See if we can load the driver. We may need the devmode structure anyway - */ - size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0); - if(size < 0) { - FIXME("DocumentProperties fails\n"); - size = sizeof(DEVMODEW); - } - if(pi->pDevMode) { - dmW = pi->pDevMode; - } else { - dmW = HeapAlloc(GetProcessHeap(), 0, size); - dmW->dmSize = size; - DocumentPropertiesW(0, -1, pi->pPrinterName, dmW, NULL, DM_OUT_BUFFER); - } - if(RegCreateKeyW(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) != ERROR_SUCCESS) { FIXME("Can't create printer %s\n", debugstr_w(pi->pPrinterName)); SetLastError(ERROR_INVALID_PRINTER_NAME); RegCloseKey(hkeyPrinters); - if(!pi->pDevMode) - HeapFree(GetProcessHeap(), 0, dmW); return 0; } RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD, (LPBYTE)&pi->Attributes, sizeof(DWORD)); RegSetValueExW(hkeyPrinter, DatatypeW, 0, REG_SZ, (LPBYTE)pi->pDatatype, 0); + + /* See if we can load the driver. We may need the devmode structure anyway + * + * FIXME: + * Note that DocumentPropertiesW will briefly try to open the printer we + * just create to find a DEVMODEA struct (it will use the WINEPS default + * one in case it is not there, so we are ok). + */ + size = DocumentPropertiesW(0, -1, pi->pPrinterName, NULL, NULL, 0); + if(size < 0) { + FIXME("DocumentProperties fails\n"); + size = sizeof(DEVMODEW); + } + if(pi->pDevMode) + dmW = pi->pDevMode; + else { + dmW = HeapAlloc(GetProcessHeap(), 0, size); + dmW->dmSize = size; + if (0>DocumentPropertiesW(0,-1,pi->pPrinterName,dmW,NULL,DM_OUT_BUFFER)) { + ERR("DocumentPropertiesW failed!\n"); + SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); + return 0; + } + /* set devmode to printer name */ + strcpyW(dmW->dmDeviceName,pi->pPrinterName); + } + /* Write DEVMODEA not DEVMODEW into reg. This is what win9x does and we support these drivers. NT writes DEVMODEW so somehow we'll need to distinguish between these when we support NT @@ -1165,7 +1336,7 @@ static BOOL WINSPOOL_GetDevModeFromReg(HKEY hkey, LPCWSTR ValueName, if (sz < sizeof(DEVMODEA)) { ERR("corrupted registry for %s ( size %ld)\n",debugstr_w(ValueName),sz); - sz = sizeof(DEVMODEA); + return FALSE; } /* ensures that dmSize is not erratically bogus if registry is invalid */ if (ptr && ((DEVMODEA*)ptr)->dmSize < sizeof(DEVMODEA)) @@ -2123,7 +2294,7 @@ BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo) return FALSE; } if(!pDriverInfo) { - WARN("pDriverInfo == NULL"); + WARN("pDriverInfo == NULL\n"); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } diff --git a/dlls/winspool/wspool.c b/dlls/winspool/wspool.c index 992c474afd1..e36e474915e 100644 --- a/dlls/winspool/wspool.c +++ b/dlls/winspool/wspool.c @@ -26,10 +26,8 @@ BOOL WINAPI WINSPOOL_EntryPoint(HINSTANCE hInstance, switch (reason) { case DLL_PROCESS_ATTACH: { -#ifdef HAVE_CUPS - extern void CUPS_LoadPrinters(); - CUPS_LoadPrinters(); -#endif + extern void WINSPOOL_LoadSystemPrinters(); + WINSPOOL_LoadSystemPrinters(); break; } case DLL_PROCESS_DETACH: