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