1
/* -*- c-basic-offset: 8 -*-
2
FreeRDP: A Remote Desktop Protocol client.
3
Redirected Printer Device Service
5
Copyright (C) Marc-Andre Moreau <marcandre.moreau@gmail.com> 2010
6
Copyright (C) Vic Lee <llyzs@163.com> 2010
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 2 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2
* FreeRDP: A Remote Desktop Protocol client.
3
* Print Virtual Channel
5
* Copyright 2010-2011 Vic Lee
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
11
* http://www.apache.org/licenses/LICENSE-2.0
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
24
22
#include <stdlib.h>
25
23
#include <string.h>
24
#include <freerdp/utils/stream.h>
25
#include <freerdp/utils/unicode.h>
26
#include <freerdp/utils/memory.h>
27
#include <freerdp/utils/thread.h>
28
#include <freerdp/utils/svc_plugin.h>
27
30
#include "rdpdr_constants.h"
28
31
#include "rdpdr_types.h"
34
#include "printer_cups.h"
30
37
#include "printer_main.h"
33
printer_get_filename(const char * name)
39
home = getenv("HOME");
43
filename = (char *) malloc(strlen(home) + strlen("/.freerdp/printer_") + strlen(name) + 1);
44
sprintf(filename, "%s/.freerdp", home);
45
if (stat(filename, &st) != 0)
47
mkdir(filename, 0700);
48
LLOGLN(0, ("printer_get_filename: created %s", filename));
50
strcat(filename, "/printer_");
51
strcat(filename, name);
56
printer_save_data(const char * name, const char * data, int data_len)
62
filename = printer_get_filename(name);
63
fp = fopen(filename, "w+b");
66
LLOGLN(0, ("printer_save_data: create %s failed.", filename));
70
len = (int) fwrite(data, 1, data_len, fp);
73
LLOGLN(0, ("printer_save_data: error writing %d bytes.", len));
81
printer_get_data(const char * name, int * len)
39
typedef struct _PRINTER_DEVICE PRINTER_DEVICE;
40
struct _PRINTER_DEVICE
47
freerdp_thread* thread;
50
static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
52
rdpPrintJob* printjob = NULL;
54
if (printer_dev->printer != NULL)
55
printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer, irp->devman->id_sequence++);
59
stream_write_uint32(irp->output, printjob->id); /* FileId */
61
DEBUG_SVC("printjob id: %d", printjob->id);
65
stream_write_uint32(irp->output, 0); /* FileId */
66
irp->IoStatus = STATUS_PRINT_QUEUE_FULL;
68
DEBUG_WARN("error creating print job.");
74
static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
76
rdpPrintJob* printjob = NULL;
78
if (printer_dev->printer != NULL)
79
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
83
irp->IoStatus = STATUS_UNSUCCESSFUL;
85
DEBUG_WARN("printjob id %d not found.", irp->FileId);
89
printjob->Close(printjob);
91
DEBUG_SVC("printjob id %d closed.", irp->FileId);
94
stream_write_zero(irp->output, 4); /* Padding(4) */
99
static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
101
rdpPrintJob* printjob = NULL;
105
stream_read_uint32(irp->input, Length);
106
stream_read_uint64(irp->input, Offset);
107
stream_seek(irp->input, 20); /* Padding */
109
if (printer_dev->printer != NULL)
110
printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
112
if (printjob == NULL)
114
irp->IoStatus = STATUS_UNSUCCESSFUL;
117
DEBUG_WARN("printjob id %d not found.", irp->FileId);
121
printjob->Write(printjob, stream_get_tail(irp->input), Length);
123
DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length);
126
stream_write_uint32(irp->output, Length);
127
stream_write_uint8(irp->output, 0); /* Padding */
132
static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
134
switch (irp->MajorFunction)
137
printer_process_irp_create(printer_dev, irp);
141
printer_process_irp_close(printer_dev, irp);
145
printer_process_irp_write(printer_dev, irp);
149
DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
150
irp->IoStatus = STATUS_NOT_SUPPORTED;
156
static void printer_process_irp_list(PRINTER_DEVICE* printer_dev)
162
if (freerdp_thread_is_stopped(printer_dev->thread))
165
freerdp_thread_lock(printer_dev->thread);
166
irp = (IRP*)list_dequeue(printer_dev->irp_list);
167
freerdp_thread_unlock(printer_dev->thread);
172
printer_process_irp(printer_dev, irp);
176
static void* printer_thread_func(void* arg)
178
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)arg;
182
freerdp_thread_wait(printer_dev->thread);
184
if (freerdp_thread_is_stopped(printer_dev->thread))
187
freerdp_thread_reset(printer_dev->thread);
188
printer_process_irp_list(printer_dev);
191
freerdp_thread_quit(printer_dev->thread);
196
static void printer_irp_request(DEVICE* device, IRP* irp)
198
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device;
200
freerdp_thread_lock(printer_dev->thread);
201
list_enqueue(printer_dev->irp_list, irp);
202
freerdp_thread_unlock(printer_dev->thread);
204
freerdp_thread_signal(printer_dev->thread);
207
static void printer_free(DEVICE* device)
209
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device;
212
freerdp_thread_stop(printer_dev->thread);
213
freerdp_thread_free(printer_dev->thread);
215
while ((irp = (IRP*)list_dequeue(printer_dev->irp_list)) != NULL)
217
list_free(printer_dev->irp_list);
219
if (printer_dev->printer)
220
printer_dev->printer->Free(printer_dev->printer);
222
xfree(printer_dev->device.name);
227
void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer)
229
PRINTER_DEVICE* printer_dev;
233
size_t DriverNameLen;
237
uint32 CachedFieldsLen;
238
uint8* CachedPrinterConfigData;
241
snprintf(port, 10, "PRN%d", printer->id);
243
printer_dev = xnew(PRINTER_DEVICE);
245
printer_dev->device.type = RDPDR_DTYP_PRINT;
246
printer_dev->device.name = port;
247
printer_dev->device.IRPRequest = printer_irp_request;
248
printer_dev->device.Free = printer_free;
250
printer_dev->printer = printer;
253
CachedPrinterConfigData = NULL;
255
DEBUG_SVC("Printer %s registered", printer->name);
258
if (printer->is_default)
259
Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
261
uniconv = freerdp_uniconv_new();
262
DriverName = freerdp_uniconv_out(uniconv, printer->driver, &DriverNameLen);
263
PrintName = freerdp_uniconv_out(uniconv, printer->name, &PrintNameLen);
264
freerdp_uniconv_free(uniconv);
266
printer_dev->device.data = stream_new(28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
268
stream_write_uint32(printer_dev->device.data, Flags);
269
stream_write_uint32(printer_dev->device.data, 0); /* CodePage, reserved */
270
stream_write_uint32(printer_dev->device.data, 0); /* PnPNameLen */
271
stream_write_uint32(printer_dev->device.data, DriverNameLen + 2);
272
stream_write_uint32(printer_dev->device.data, PrintNameLen + 2);
273
stream_write_uint32(printer_dev->device.data, CachedFieldsLen);
274
stream_write(printer_dev->device.data, DriverName, DriverNameLen);
275
stream_write_uint16(printer_dev->device.data, 0);
276
stream_write(printer_dev->device.data, PrintName, PrintNameLen);
277
stream_write_uint16(printer_dev->device.data, 0);
278
if (CachedFieldsLen > 0)
280
stream_write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen);
286
printer_dev->irp_list = list_new();
287
printer_dev->thread = freerdp_thread_new();
289
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)printer_dev);
291
freerdp_thread_start(printer_dev->thread, printer_thread_func, printer_dev);
294
int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
296
rdpPrinterDriver* driver = NULL;
297
rdpPrinter** printers;
88
filename = printer_get_filename(name);
89
fp = fopen(filename, "rb");
97
fseek(fp, 0, SEEK_END);
98
*len = (int) ftell(fp);
99
fseek(fp, 0, SEEK_SET);
100
buf = (char *) malloc(*len);
101
memset(buf, 0, *len);
102
i = fread(buf, 1, *len, fp);
109
printer_process_update_printer_event(SERVICE * srv, const char * data, int data_len)
111
uint32 printerNameLen;
113
uint32 configDataLen;
116
printerNameLen = GET_UINT32(data, 0);
117
configDataLen = GET_UINT32(data, 4);
119
if (printerNameLen + configDataLen + 8 > data_len)
121
LLOGLN(0, ("printer_process_update_printer_event: expect %d+%d+8 got %d",
122
printerNameLen, configDataLen, data_len));
304
driver = printer_cups_get_driver();
308
DEBUG_WARN("no driver.");
125
size = printerNameLen * 3 / 2 + 2;
126
printerName = (char *) malloc(size);
127
memset(printerName, 0, size);
128
freerdp_get_wstr(printerName, size, (char *)(data + 8), printerNameLen);
129
LLOGLN(10, ("printer_process_update_printer_event: %s %d", printerName, configDataLen));
130
printer_save_data(printerName, data + 8 + printerNameLen, configDataLen);
137
printer_process_delete_printer_event(SERVICE * srv, const char * data, int data_len)
139
uint32 printerNameLen;
144
printerNameLen = GET_UINT32(data, 0);
146
size = printerNameLen * 3 / 2 + 2;
147
printerName = (char *) malloc(size);
148
memset(printerName, 0, size);
149
freerdp_get_wstr(printerName, size, (char *)(data + 4), printerNameLen);
151
filename = printer_get_filename(printerName);
153
LLOGLN(0, ("printer_process_delete_printer_event: %s deleted", filename));
161
printer_process_cache_data(SERVICE * srv, const char * data, int data_len)
165
eventID = GET_UINT32(data, 0);
168
case RDPDR_ADD_PRINTER_EVENT:
169
LLOGLN(0, ("RDPDR_ADD_PRINTER_EVENT"));
172
case RDPDR_UPDATE_PRINTER_EVENT:
173
LLOGLN(10, ("RDPDR_UPDATE_PRINTER_EVENT"));
174
printer_process_update_printer_event(srv, &data[4], data_len - 4);
177
case RDPDR_DELETE_PRINTER_EVENT:
178
LLOGLN(10, ("RDPDR_DELETE_PRINTER_EVENT"));
179
printer_process_delete_printer_event(srv, &data[4], data_len - 4);
182
case RDPDR_RENAME_PRINTER_EVENT:
183
LLOGLN(0, ("RDPDR_RENAME_PRINTER_EVENT"));
187
LLOGLN(0, ("RDPDR printer unsupported eventID %i", eventID));
194
printer_process_data(SERVICE * srv, int type, const char * data, int data_len)
198
case PAKID_PRN_CACHE_DATA:
199
LLOGLN(10, ("PAKID_PRN_CACHE_DATA"));
200
printer_process_cache_data(srv, data, data_len);
204
LLOGLN(0, ("RDPDR printer component, packetID: 0x%02X", type));
211
printer_register_service(PDEVMAN pDevman, PDEVMAN_ENTRY_POINTS pEntryPoints)
215
srv = pEntryPoints->pDevmanRegisterService(pDevman);
217
srv->create = printer_hw_create;
218
srv->close = printer_hw_close;
220
srv->write = printer_hw_write;
222
srv->query_volume_info = NULL;
223
srv->query_info = NULL;
224
srv->set_info = NULL;
225
srv->query_directory = NULL;
226
srv->notify_change_directory = NULL;
227
srv->lock_control = NULL;
228
srv->free = printer_free;
229
srv->process_data = printer_process_data;
230
srv->type = RDPDR_DTYP_PRINT;
231
srv->get_event = NULL;
232
srv->file_descriptor = NULL;
233
srv->get_timeouts = NULL;
239
printer_register(PDEVMAN pDevman, PDEVMAN_ENTRY_POINTS pEntryPoints, SERVICE * srv,
240
const char * name, const char * driver, int is_default, int * port)
251
LLOGLN(0, ("printer_register: %s (default=%d)", name, is_default));
255
/* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */
256
driver = "MS Publisher Imagesetter";
259
snprintf(buf, sizeof(buf) - 1, "PRN%d", *port);
261
dev = pEntryPoints->pDevmanRegisterDevice(pDevman, srv, buf);
262
dev->info = printer_hw_new(name);
264
cache_data = printer_get_data(name, &cache_data_len);
266
size = 24 + 4 + (strlen(name) + 1) * 2 + (strlen(driver) + 1) * 2 + cache_data_len;
267
dev->data = malloc(size);
268
memset(dev->data, 0, size);
270
/*flags = RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT;*/
273
flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
275
SET_UINT32 (dev->data, 0, flags); /* Flags */
276
SET_UINT32 (dev->data, 4, 0); /* CodePage, reserved */
277
SET_UINT32 (dev->data, 8, 0); /* PnPNameLen */
278
SET_UINT32 (dev->data, 20, cache_data_len); /* CachedFieldsLen */
280
len = freerdp_set_wstr(&dev->data[offset], size - offset, (char *) driver, strlen(driver) + 1);
281
SET_UINT32 (dev->data, 12, len); /* DriverNameLen */
283
len = freerdp_set_wstr(&dev->data[offset], size - offset, (char *) name, strlen(name) + 1);
284
SET_UINT32 (dev->data, 16, len); /* PrintNameLen */
288
memcpy(&dev->data[offset], cache_data, cache_data_len);
289
offset += cache_data_len;
293
dev->data_len = offset;
299
printer_free(DEVICE * dev)
301
printer_hw_free(dev->info);
311
DeviceServiceEntry(PDEVMAN pDevman, PDEVMAN_ENTRY_POINTS pEntryPoints)
313
SERVICE * srv = NULL;
314
RD_PLUGIN_DATA * data;
317
data = (RD_PLUGIN_DATA *) pEntryPoints->pExtendedData;
318
while (data && data->size > 0)
320
if (strcmp((char*)data->data[0], "printer") == 0)
323
srv = printer_register_service(pDevman, pEntryPoints);
325
if (data->data[1] == NULL)
326
printer_hw_register_auto(pDevman, pEntryPoints, srv, &port);
328
printer_register(pDevman, pEntryPoints, srv, data->data[1], data->data[2], (port == 1), &port);
331
data = (RD_PLUGIN_DATA *) (((void *) data) + data->size);
312
name = (char*)pEntryPoints->plugin_data->data[1];
313
driver_name = (char*)pEntryPoints->plugin_data->data[2];
317
printer = driver->GetPrinter(driver, name);
320
DEBUG_WARN("printer %s not found.", name);
323
if (driver_name && driver_name[0])
324
printer->driver = driver_name;
326
printer_register(pEntryPoints, printer);
330
printers = driver->EnumPrinters(driver);
331
for (i = 0; printers[i]; i++)
333
printer = printers[i];
334
printer_register(pEntryPoints, printer);