1 /* -*- c-basic-offset: 8 -*-
2    rdesktop: A Remote Desktop Protocol client.
3    Copyright (C) Matthew Chapman 1999-2005
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License along
16    with this program; if not, write to the Free Software Foundation, Inc.,
17    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include "rdesktop.h"
21 
22 static PRINTER *
get_printer_data(RDPCLIENT * This,NTHANDLE handle)23 get_printer_data(RDPCLIENT * This, NTHANDLE handle)
24 {
25 	int index;
26 
27 	for (index = 0; index < RDPDR_MAX_DEVICES; index++)
28 	{
29 		if (handle == This->rdpdr_device[index].handle)
30 			return (PRINTER *) This->rdpdr_device[index].pdevice_data;
31 	}
32 	return NULL;
33 }
34 
35 int
printer_enum_devices(RDPCLIENT * This,uint32 * id,char * optarg)36 printer_enum_devices(RDPCLIENT * This, uint32 * id, char *optarg)
37 {
38 	PRINTER *pprinter_data;
39 
40 	char *pos = optarg;
41 	char *pos2;
42 	int count = 0;
43 	int already = 0;
44 
45 	/* we need to know how many printers we've already set up
46 	   supplied from other -r flags than this one. */
47 	while (count < *id)
48 	{
49 		if (This->rdpdr_device[count].device_type == DEVICE_TYPE_PRINTER)
50 			already++;
51 		count++;
52 	}
53 
54 	count = 0;
55 
56 	if (*optarg == ':')
57 		optarg++;
58 
59 	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
60 	{
61 		pprinter_data = (PRINTER *) xmalloc(sizeof(PRINTER));
62 
63 		strcpy(This->rdpdr_device[*id].name, "PRN");
64 		strcat(This->rdpdr_device[*id].name, l_to_a(already + count + 1, 10));
65 
66 		/* first printer is set as default printer */
67 		if ((already + count) == 0)
68 			pprinter_data->default_printer = True;
69 		else
70 			pprinter_data->default_printer = False;
71 
72 		pos2 = next_arg(optarg, '=');
73 		if (*optarg == (char) 0x00)
74 			pprinter_data->printer = "mydeskjet";	/* set default */
75 		else
76 		{
77 			pprinter_data->printer = xmalloc(strlen(optarg) + 1);
78 			strcpy(pprinter_data->printer, optarg);
79 		}
80 
81 		if (!pos2 || (*pos2 == (char) 0x00))
82 			pprinter_data->driver = "HP Color LaserJet 8500 PS";	/* no printer driver supplied set default */
83 		else
84 		{
85 			pprinter_data->driver = xmalloc(strlen(pos2) + 1);
86 			strcpy(pprinter_data->driver, pos2);
87 		}
88 
89 		printf("PRINTER %s to %s driver %s\n", This->rdpdr_device[*id].name,
90 		       pprinter_data->printer, pprinter_data->driver);
91 		This->rdpdr_device[*id].device_type = DEVICE_TYPE_PRINTER;
92 		This->rdpdr_device[*id].pdevice_data = (void *) pprinter_data;
93 		count++;
94 		(*id)++;
95 
96 		optarg = pos;
97 	}
98 	return count;
99 }
100 
101 static NTSTATUS
printer_create(RDPCLIENT * This,uint32 device_id,uint32 access,uint32 share_mode,uint32 disposition,uint32 flags,char * filename,NTHANDLE * handle)102 printer_create(RDPCLIENT * This, uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, uint32 flags,
103 	       char *filename, NTHANDLE * handle)
104 {
105 	char cmd[256];
106 	PRINTER *pprinter_data;
107 
108 	pprinter_data = (PRINTER *) This->rdpdr_device[device_id].pdevice_data;
109 
110 	/* default printer name use default printer queue as well in unix */
111 	if (pprinter_data->printer == "mydeskjet")
112 	{
113 		pprinter_data->printer_fp = popen("lpr", "w");
114 	}
115 	else
116 	{
117 		sprintf(cmd, "lpr -P %s", pprinter_data->printer);
118 		pprinter_data->printer_fp = popen(cmd, "w");
119 	}
120 
121 	This->rdpdr_device[device_id].handle = fileno(pprinter_data->printer_fp);
122 	*handle = This->rdpdr_device[device_id].handle;
123 	return STATUS_SUCCESS;
124 }
125 
126 static NTSTATUS
printer_close(RDPCLIENT * This,NTHANDLE handle)127 printer_close(RDPCLIENT * This, NTHANDLE handle)
128 {
129 	int i = get_device_index(This, handle);
130 	if (i >= 0)
131 	{
132 		PRINTER *pprinter_data = This->rdpdr_device[i].pdevice_data;
133 		if (pprinter_data)
134 			pclose(pprinter_data->printer_fp);
135 		This->rdpdr_device[i].handle = 0;
136 	}
137 	return STATUS_SUCCESS;
138 }
139 
140 static NTSTATUS
printer_write(RDPCLIENT * This,NTHANDLE handle,uint8 * data,uint32 length,uint32 offset,uint32 * result)141 printer_write(RDPCLIENT * This, NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
142 {
143 	PRINTER *pprinter_data;
144 
145 	pprinter_data = get_printer_data(This, handle);
146 	*result = length * fwrite(data, length, 1, pprinter_data->printer_fp);
147 
148 	if (ferror(pprinter_data->printer_fp))
149 	{
150 		*result = 0;
151 		return STATUS_INVALID_HANDLE;
152 	}
153 	return STATUS_SUCCESS;
154 }
155 
156 DEVICE_FNS printer_fns = {
157 	printer_create,
158 	printer_close,
159 	NULL,			/* read */
160 	printer_write,
161 	NULL			/* device_control */
162 };
163