]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - windows/winprint.c
A bunch of further warning fixes in the Windows code.
[PuTTY.git] / windows / winprint.c
1 /*
2  * Printing interface for PuTTY.
3  */
4
5 #include "putty.h"
6 #include <winspool.h>
7
8 struct printer_enum_tag {
9     int nprinters;
10     DWORD enum_level;
11     union {
12         LPPRINTER_INFO_4 i4;
13         LPPRINTER_INFO_5 i5;
14     } info;
15 };
16
17 struct printer_job_tag {
18     HANDLE hprinter;
19 };
20
21 static int printer_add_enum(int param, DWORD level, char **buffer,
22                             int offset, int *nprinters_ptr)
23 {
24     DWORD needed = 0, nprinters = 0;
25
26     *buffer = sresize(*buffer, offset+512, char);
27
28     /*
29      * Exploratory call to EnumPrinters to determine how much space
30      * we'll need for the output. Discard the return value since it
31      * will almost certainly be a failure due to lack of space.
32      */
33     EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset), 512,
34                  &needed, &nprinters);
35
36     if (needed < 512)
37         needed = 512;
38
39     *buffer = sresize(*buffer, offset+needed, char);
40
41     if (EnumPrinters(param, NULL, level, (LPBYTE)((*buffer)+offset),
42                      needed, &needed, &nprinters) == 0)
43         return FALSE;
44
45     *nprinters_ptr += nprinters;
46
47     return TRUE;
48 }
49
50 printer_enum *printer_start_enum(int *nprinters_ptr)
51 {
52     printer_enum *ret = snew(printer_enum);
53     char *buffer = NULL;
54
55     *nprinters_ptr = 0;                /* default return value */
56     buffer = snewn(512, char);
57
58     /*
59      * Determine what enumeration level to use.
60      * When enumerating printers, we need to use PRINTER_INFO_4 on
61      * NT-class systems to avoid Windows looking too hard for them and
62      * slowing things down; and we need to avoid PRINTER_INFO_5 as
63      * we've seen network printers not show up.
64      * On 9x-class systems, PRINTER_INFO_4 isn't available and
65      * PRINTER_INFO_5 is recommended.
66      * Bletch.
67      */
68     if (osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT) {
69         ret->enum_level = 5;
70     } else {
71         ret->enum_level = 4;
72     }
73
74     if (!printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
75                           ret->enum_level, &buffer, 0, nprinters_ptr))
76         goto error;
77
78     switch (ret->enum_level) {
79       case 4:
80         ret->info.i4 = (LPPRINTER_INFO_4)buffer;
81         break;
82       case 5:
83         ret->info.i5 = (LPPRINTER_INFO_5)buffer;
84         break;
85     }
86     ret->nprinters = *nprinters_ptr;
87     
88     return ret;
89
90     error:
91     sfree(buffer);
92     sfree(ret);
93     *nprinters_ptr = 0;
94     return NULL;
95 }
96
97 char *printer_get_name(printer_enum *pe, int i)
98 {
99     if (!pe)
100         return NULL;
101     if (i < 0 || i >= pe->nprinters)
102         return NULL;
103     switch (pe->enum_level) {
104       case 4:
105         return pe->info.i4[i].pPrinterName;
106       case 5:
107         return pe->info.i5[i].pPrinterName;
108       default:
109         return NULL;
110     }
111 }
112
113 void printer_finish_enum(printer_enum *pe)
114 {
115     if (!pe)
116         return;
117     switch (pe->enum_level) {
118       case 4:
119         sfree(pe->info.i4);
120         break;
121       case 5:
122         sfree(pe->info.i5);
123         break;
124     }
125     sfree(pe);
126 }
127
128 printer_job *printer_start_job(char *printer)
129 {
130     printer_job *ret = snew(printer_job);
131     DOC_INFO_1 docinfo;
132     int jobstarted = 0, pagestarted = 0;
133
134     ret->hprinter = NULL;
135     if (!OpenPrinter(printer, &ret->hprinter, NULL))
136         goto error;
137
138     docinfo.pDocName = "PuTTY remote printer output";
139     docinfo.pOutputFile = NULL;
140     docinfo.pDatatype = "RAW";
141
142     if (!StartDocPrinter(ret->hprinter, 1, (LPBYTE)&docinfo))
143         goto error;
144     jobstarted = 1;
145
146     if (!StartPagePrinter(ret->hprinter))
147         goto error;
148     pagestarted = 1;
149
150     return ret;
151
152     error:
153     if (pagestarted)
154         EndPagePrinter(ret->hprinter);
155     if (jobstarted)
156         EndDocPrinter(ret->hprinter);
157     if (ret->hprinter)
158         ClosePrinter(ret->hprinter);
159     sfree(ret);
160     return NULL;
161 }
162
163 void printer_job_data(printer_job *pj, void *data, int len)
164 {
165     DWORD written;
166
167     if (!pj)
168         return;
169
170     WritePrinter(pj->hprinter, data, len, &written);
171 }
172
173 void printer_finish_job(printer_job *pj)
174 {
175     if (!pj)
176         return;
177
178     EndPagePrinter(pj->hprinter);
179     EndDocPrinter(pj->hprinter);
180     ClosePrinter(pj->hprinter);
181     sfree(pj);
182 }