]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - printing.c
Move MODULE files out of individual project directories into a
[PuTTY.git] / printing.c
1 /*
2  * Printing interface for PuTTY.
3  */
4
5 #include <windows.h>
6 #include "putty.h"
7
8 /*
9  * Boggle. Flipping between the two branches of this #if appears to
10  * make all the difference as to whether network printers show up
11  * under PRINTER_ENUM_CONNECTIONS on NT 4. I don't pretend to
12  * understand this...
13  */
14 #if 0
15 #define ENUM_LEVEL 5
16 #define ENUM_PTR LPPRINTER_INFO_5
17 #define ENUM_TYPE PRINTER_INFO_5
18 #define ENUM_MEMBER pPrinterName
19 #else
20 #define ENUM_LEVEL 1
21 #define ENUM_PTR LPPRINTER_INFO_1
22 #define ENUM_TYPE PRINTER_INFO_1
23 #define ENUM_MEMBER pName
24 #endif
25
26 struct printer_enum_tag {
27     int nprinters;
28     ENUM_PTR info;
29 };
30
31 struct printer_job_tag {
32     HANDLE hprinter;
33 };
34
35 static char *printer_add_enum(int param, char *buffer,
36                               int offset, int *nprinters_ptr)
37 {
38     DWORD needed, nprinters;
39
40     buffer = srealloc(buffer, offset+512);
41
42     /*
43      * Exploratory call to EnumPrinters to determine how much space
44      * we'll need for the output. Discard the return value since it
45      * will almost certainly be a failure due to lack of space.
46      */
47     EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset, 512,
48                  &needed, &nprinters);
49
50     if (needed < 512)
51         needed = 512;
52
53     buffer = srealloc(buffer, offset+needed);
54
55     if (EnumPrinters(param, NULL, ENUM_LEVEL, buffer+offset,
56                      needed, &needed, &nprinters) == 0)
57         return NULL;
58
59     *nprinters_ptr += nprinters;
60
61     return buffer;
62 }
63
64 printer_enum *printer_start_enum(int *nprinters_ptr)
65 {
66     printer_enum *ret = smalloc(sizeof(printer_enum));
67     char *buffer = NULL, *retval;
68
69     *nprinters_ptr = 0;                /* default return value */
70     buffer = smalloc(512);
71
72     retval = printer_add_enum(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
73                               buffer, 0, nprinters_ptr);
74     if (!retval)
75         goto error;
76     else
77         buffer = retval;
78
79     ret->info = (ENUM_PTR)buffer;
80     ret->nprinters = *nprinters_ptr;
81     
82     return ret;
83
84     error:
85     sfree(buffer);
86     sfree(ret);
87     *nprinters_ptr = 0;
88     return NULL;
89 }
90
91 char *printer_get_name(printer_enum *pe, int i)
92 {
93     if (!pe)
94         return NULL;
95     if (i < 0 || i >= pe->nprinters)
96         return NULL;
97     return pe->info[i].ENUM_MEMBER;
98 }
99
100 void printer_finish_enum(printer_enum *pe)
101 {
102     if (!pe)
103         return;
104     sfree(pe->info);
105     sfree(pe);
106 }
107
108 printer_job *printer_start_job(char *printer)
109 {
110     printer_job *ret = smalloc(sizeof(printer_job));
111     DOC_INFO_1 docinfo;
112     int jobstarted = 0, pagestarted = 0;
113
114     ret->hprinter = NULL;
115     if (!OpenPrinter(printer, &ret->hprinter, NULL))
116         goto error;
117
118     docinfo.pDocName = "PuTTY remote printer output";
119     docinfo.pOutputFile = NULL;
120     docinfo.pDatatype = "RAW";
121
122     if (!StartDocPrinter(ret->hprinter, 1, (LPSTR)&docinfo))
123         goto error;
124     jobstarted = 1;
125
126     if (!StartPagePrinter(ret->hprinter))
127         goto error;
128     pagestarted = 1;
129
130     return ret;
131
132     error:
133     if (pagestarted)
134         EndPagePrinter(ret->hprinter);
135     if (jobstarted)
136         EndDocPrinter(ret->hprinter);
137     if (ret->hprinter)
138         ClosePrinter(ret->hprinter);
139     sfree(ret);
140     return NULL;
141 }
142
143 void printer_job_data(printer_job *pj, void *data, int len)
144 {
145     DWORD written;
146
147     if (!pj)
148         return;
149
150     WritePrinter(pj->hprinter, data, len, &written);
151 }
152
153 void printer_finish_job(printer_job *pj)
154 {
155     if (!pj)
156         return;
157
158     EndPagePrinter(pj->hprinter);
159     EndDocPrinter(pj->hprinter);
160     ClosePrinter(pj->hprinter);
161     sfree(pj);
162 }