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 #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>
30 #include "rdpdr_constants.h"
31 #include "rdpdr_types.h"
34 #include "printer_cups.h"
37 #include "printer_main.h"
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;
304 driver = printer_cups_get_driver();
308 DEBUG_WARN("no driver.");
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);