1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00
putty-source/windows/winprint.c
Simon Tatham 5d718ef64b Whitespace rationalisation of entire code base.
The number of people has been steadily increasing who read our source
code with an editor that thinks tab stops are 4 spaces apart, as
opposed to the traditional tty-derived 8 that the PuTTY code expects.

So I've been wondering for ages about just fixing it, and switching to
a spaces-only policy throughout the code. And I recently found out
about 'git blame -w', which should make this change not too disruptive
for the purposes of source-control archaeology; so perhaps now is the
time.

While I'm at it, I've also taken the opportunity to remove all the
trailing spaces from source lines (on the basis that git dislikes
them, and is the only thing that seems to have a strong opinion one
way or the other).
    
Apologies to anyone downstream of this code who has complicated patch
sets to rebase past this change. I don't intend it to be needed again.
2019-09-08 20:29:21 +01:00

225 lines
5.9 KiB
C

/*
* Printing interface for PuTTY.
*/
#include "putty.h"
#include <winspool.h>
struct printer_enum_tag {
int nprinters;
DWORD enum_level;
union {
LPPRINTER_INFO_4 i4;
LPPRINTER_INFO_5 i5;
} info;
};
struct printer_job_tag {
HANDLE hprinter;
};
DECL_WINDOWS_FUNCTION(static, BOOL, EnumPrinters,
(DWORD, LPTSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD));
DECL_WINDOWS_FUNCTION(static, BOOL, OpenPrinter,
(LPTSTR, LPHANDLE, LPPRINTER_DEFAULTS));
DECL_WINDOWS_FUNCTION(static, BOOL, ClosePrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, DWORD, StartDocPrinter, (HANDLE, DWORD, LPBYTE));
DECL_WINDOWS_FUNCTION(static, BOOL, EndDocPrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, BOOL, StartPagePrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, BOOL, EndPagePrinter, (HANDLE));
DECL_WINDOWS_FUNCTION(static, BOOL, WritePrinter,
(HANDLE, LPVOID, DWORD, LPDWORD));
static void init_winfuncs(void)
{
static bool initialised = false;
if (initialised)
return;
{
HMODULE winspool_module = load_system32_dll("winspool.drv");
/* Some MSDN documentation claims that some of the below functions
* should be loaded from spoolss.dll, but this doesn't seem to
* be reliable in practice.
* Nevertheless, we load spoolss.dll ourselves using our safe
* loading method, against the possibility that winspool.drv
* later loads it unsafely. */
(void) load_system32_dll("spoolss.dll");
GET_WINDOWS_FUNCTION_PP(winspool_module, EnumPrinters);
GET_WINDOWS_FUNCTION_PP(winspool_module, OpenPrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, ClosePrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, StartDocPrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, EndDocPrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, StartPagePrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, EndPagePrinter);
GET_WINDOWS_FUNCTION_PP(winspool_module, WritePrinter);
}
initialised = true;
}
static bool printer_add_enum(int param, DWORD level, char **buffer,
int offset, int *nprinters_ptr)
{
DWORD needed = 0, nprinters = 0;
init_winfuncs();
*buffer = sresize(*buffer, offset+512, char);
/*
* 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.
*/
p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
&needed, &nprinters);
if (needed < 512)
needed = 512;
*buffer = sresize(*buffer, offset+needed, char);
if (p_EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
needed, &needed, &nprinters) == 0)
return false;
*nprinters_ptr += nprinters;
return true;
}
printer_enum *printer_start_enum(int *nprinters_ptr)
{
printer_enum *ret = snew(printer_enum);
char *buffer = NULL;
*nprinters_ptr = 0; /* default return value */
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 (osPlatformId != VER_PLATFORM_WIN32_NT) {
ret->enum_level = 5;
} else {
ret->enum_level = 4;
}
if (!printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
ret->enum_level, &buffer, 0, nprinters_ptr))
goto error;
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;
error:
sfree(buffer);
sfree(ret);
*nprinters_ptr = 0;
return NULL;
}
char *printer_get_name(printer_enum *pe, int i)
{
if (!pe)
return NULL;
if (i < 0 || i >= pe->nprinters)
return NULL;
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;
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 = snew(printer_job);
DOC_INFO_1 docinfo;
bool jobstarted = false, pagestarted = false;
init_winfuncs();
ret->hprinter = NULL;
if (!p_OpenPrinter(printer, &ret->hprinter, NULL))
goto error;
docinfo.pDocName = "PuTTY remote printer output";
docinfo.pOutputFile = NULL;
docinfo.pDatatype = "RAW";
if (!p_StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
goto error;
jobstarted = true;
if (!p_StartPagePrinter(ret->hprinter))
goto error;
pagestarted = true;
return ret;
error:
if (pagestarted)
p_EndPagePrinter(ret->hprinter);
if (jobstarted)
p_EndDocPrinter(ret->hprinter);
if (ret->hprinter)
p_ClosePrinter(ret->hprinter);
sfree(ret);
return NULL;
}
void printer_job_data(printer_job *pj, const void *data, size_t len)
{
DWORD written;
if (!pj)
return;
p_WritePrinter(pj->hprinter, (void *)data, len, &written);
}
void printer_finish_job(printer_job *pj)
{
if (!pj)
return;
p_EndPagePrinter(pj->hprinter);
p_EndDocPrinter(pj->hprinter);
p_ClosePrinter(pj->hprinter);
sfree(pj);
}