X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/a5751e2d5bb140a640ecf1810f45cf7c70028ac3..7440fd4419acfc9c784f142fb9dee3e64c9a18c2:/printing.c diff --git a/printing.c b/printing.c index 964f4b52..6248881d 100644 --- a/printing.c +++ b/printing.c @@ -2,53 +2,42 @@ * Printing interface for PuTTY. */ -#include #include "putty.h" -/* - * Boggle. Flipping between the two branches of this #if appears to - * make all the difference as to whether network printers show up - * under PRINTER_ENUM_CONNECTIONS on NT 4. I don't pretend to - * understand this... - */ -#if 0 -#define ENUM_LEVEL 5 -#define ENUM_PTR LPPRINTER_INFO_5 -#define ENUM_TYPE PRINTER_INFO_5 -#define ENUM_MEMBER pPrinterName -#else -#define ENUM_LEVEL 1 -#define ENUM_PTR LPPRINTER_INFO_1 -#define ENUM_TYPE PRINTER_INFO_1 -#define ENUM_MEMBER pName -#endif - struct printer_enum_tag { int nprinters; - ENUM_PTR info; + DWORD enum_level; + union { + LPPRINTER_INFO_4 i4; + LPPRINTER_INFO_5 i5; + } info; }; struct printer_job_tag { HANDLE hprinter; }; -static char *printer_add_enum(int param, char *buffer, +static char *printer_add_enum(int param, DWORD level, char *buffer, int offset, int *nprinters_ptr) { DWORD needed, nprinters; - buffer = srealloc(buffer, offset+512); + buffer = sresize(buffer, offset+512, char); - if (EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset, - 512, &needed, &nprinters) == 0) - return NULL; + /* + * Exploratory call to EnumPrinters to determine how much space + * we'll need for the output. Discard the return value since it + * will almost certainly be a failure due to lack of space. + */ + EnumPrinters(param, NULL, level, buffer+offset, 512, + &needed, &nprinters); if (needed < 512) needed = 512; - buffer = srealloc(buffer, offset+needed); + buffer = sresize(buffer, offset+needed, char); - if (EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset, + if (EnumPrinters(param, NULL, level, buffer+offset, needed, &needed, &nprinters) == 0) return NULL; @@ -59,20 +48,43 @@ static char *printer_add_enum(int param, char *buffer, printer_enum *printer_start_enum(int *nprinters_ptr) { - printer_enum *ret = smalloc(sizeof(printer_enum)); + printer_enum *ret = snew(printer_enum); char *buffer = NULL, *retval; *nprinters_ptr = 0; /* default return value */ - buffer = smalloc(512); + buffer = snewn(512, char); + + /* + * Determine what enumeration level to use. + * When enumerating printers, we need to use PRINTER_INFO_4 on + * NT-class systems to avoid Windows looking too hard for them and + * slowing things down; and we need to avoid PRINTER_INFO_5 as + * we've seen network printers not show up. + * On 9x-class systems, PRINTER_INFO_4 isn't available and + * PRINTER_INFO_5 is recommended. + * Bletch. + */ + if (osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT) { + ret->enum_level = 5; + } else { + ret->enum_level = 4; + } retval = printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - buffer, 0, nprinters_ptr); + ret->enum_level, buffer, 0, nprinters_ptr); if (!retval) goto error; else buffer = retval; - ret->info = (ENUM_PTR)buffer; + switch (ret->enum_level) { + case 4: + ret->info.i4 = (LPPRINTER_INFO_4)buffer; + break; + case 5: + ret->info.i5 = (LPPRINTER_INFO_5)buffer; + break; + } ret->nprinters = *nprinters_ptr; return ret; @@ -90,20 +102,34 @@ char *printer_get_name(printer_enum *pe, int i) return NULL; if (i < 0 || i >= pe->nprinters) return NULL; - return pe->info[i].ENUM_MEMBER; + switch (pe->enum_level) { + case 4: + return pe->info.i4[i].pPrinterName; + case 5: + return pe->info.i5[i].pPrinterName; + default: + return NULL; + } } void printer_finish_enum(printer_enum *pe) { if (!pe) return; - sfree(pe->info); + switch (pe->enum_level) { + case 4: + sfree(pe->info.i4); + break; + case 5: + sfree(pe->info.i5); + break; + } sfree(pe); } printer_job *printer_start_job(char *printer) { - printer_job *ret = smalloc(sizeof(printer_job)); + printer_job *ret = snew(printer_job); DOC_INFO_1 docinfo; int jobstarted = 0, pagestarted = 0;