rdpdr/printer: migrate/redesign printer virtual channel plugin.
authorVic Lee <llyzs@163.com>
Wed, 17 Aug 2011 13:57:09 +0000 (21:57 +0800)
committerVic Lee <llyzs@163.com>
Wed, 17 Aug 2011 13:57:09 +0000 (21:57 +0800)
CMakeLists.txt
channels/rdpdr/CMakeLists.txt
channels/rdpdr/printer/CMakeLists.txt [new file with mode: 0644]
channels/rdpdr/printer/printer_cups.c [new file with mode: 0644]
channels/rdpdr/printer/printer_cups.h [new file with mode: 0644]
channels/rdpdr/printer/printer_main.c [new file with mode: 0644]
channels/rdpdr/printer/printer_main.h [new file with mode: 0644]
config.h.in

index 43a9b0c..52b0744 100644 (file)
@@ -72,6 +72,7 @@ if(NOT WIN32)
        find_package(ZLIB REQUIRED)
        find_package(ALSA)
        find_package(PulseAudio)
+       find_package(Cups)
 endif()
 
 # Endian
index 059f4a4..be54ca6 100644 (file)
@@ -38,3 +38,5 @@ target_link_libraries(rdpdr freerdp-utils)
 install(TARGETS rdpdr DESTINATION ${FREERDP_PLUGIN_PATH})
 
 add_subdirectory(disk)
+add_subdirectory(printer)
+
diff --git a/channels/rdpdr/printer/CMakeLists.txt b/channels/rdpdr/printer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fc7784f
--- /dev/null
@@ -0,0 +1,45 @@
+# FreeRDP: A Remote Desktop Protocol Client
+# FreeRDP cmake build script
+#
+# Copyright 2011 O.S. Systems Software Ltda.
+# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
+# Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set(PRINTER_SRCS
+       printer_main.c
+       printer_main.h
+)
+
+if(CUPS_FOUND)
+       set(PRINTER_SRCS
+               ${PRINTER_SRCS}
+               printer_cups.c
+               printer_cups.h
+       )
+       include_directories(${CUPS_INCLUDE_DIR})
+endif()
+
+include_directories(..)
+
+add_library(printer SHARED ${PRINTER_SRCS})
+set_target_properties(printer PROPERTIES PREFIX "")
+
+target_link_libraries(printer freerdp-utils)
+
+if(CUPS_FOUND)
+       target_link_libraries(printer ${CUPS_LIBRARIES})
+endif()
+
+install(TARGETS printer DESTINATION ${FREERDP_PLUGIN_PATH})
diff --git a/channels/rdpdr/printer/printer_cups.c b/channels/rdpdr/printer/printer_cups.c
new file mode 100644 (file)
index 0000000..dc8861d
--- /dev/null
@@ -0,0 +1,284 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel - CUPS driver
+ *
+ * Copyright 2010-2011 Vic Lee
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <time.h>
+#include <cups/cups.h>
+#include <freerdp/utils/memory.h>
+#include <freerdp/utils/svc_plugin.h>
+
+#include "rdpdr_constants.h"
+#include "rdpdr_types.h"
+#include "printer_main.h"
+
+#include "printer_cups.h"
+
+typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver;
+typedef struct rdp_cups_printer rdpCupsPrinter;
+typedef struct rdp_cups_print_job rdpCupsPrintJob;
+
+struct rdp_cups_printer_driver
+{
+       rdpPrinterDriver driver;
+
+       int id_sequence;
+};
+
+struct rdp_cups_printer
+{
+       rdpPrinter printer;
+
+       rdpCupsPrintJob* printjob;
+};
+
+struct rdp_cups_print_job
+{
+       rdpPrintJob printjob;
+
+       void* printjob_object;
+       int printjob_id;
+};
+
+static void printer_cups_get_printjob_name(char* buf, int size)
+{
+       time_t tt;
+       struct tm* t;
+
+       tt = time(NULL);
+       t = localtime(&tt);
+       snprintf(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
+               t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+               t->tm_hour, t->tm_min, t->tm_sec);
+}
+
+static void printer_cups_write_printjob(rdpPrintJob* printjob, uint8* data, int size)
+{
+       rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
+
+#ifndef _CUPS_API_1_4
+
+       {
+               FILE* fp;
+
+               fp = fopen((const char*)cups_printjob->printjob_object, "a+b");
+               if (fp == NULL)
+               {
+                       DEBUG_WARN("failed to open file %s", (char*)cups_printjob->printjob_object);
+                       return;
+               }
+               if (fwrite(data, 1, size, fp) < size)
+               {
+                       DEBUG_WARN("failed to write file %s", (char*)cups_printjob->printjob_object);
+               }
+               fclose(fp);
+       }
+
+#else
+
+       cupsWriteRequestData((http_t*)cups_printjob->printjob_object, (const char*)data, size);
+
+#endif
+}
+
+static void printer_cups_close_printjob(rdpPrintJob* printjob)
+{
+       rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
+
+#ifndef _CUPS_API_1_4
+
+       {
+               char buf[100];
+
+               printer_cups_get_printjob_name(buf, sizeof(buf));
+               if (cupsPrintFile(printjob->printer->name, (const char *)cups_printjob->printjob_object, buf, 0, NULL) == 0)
+               {
+                       DEBUG_WARN("cupsPrintFile: %s", cupsLastErrorString());
+               }
+               unlink(cups_printjob->printjob_object);
+               xfree(cups_printjob->printjob_object);
+       }
+
+#else
+
+       cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name);
+       cups_printjob->printjob_id = 0;
+       httpClose((http_t*)cups_printjob->printjob_object);
+
+#endif
+
+       xfree(cups_printjob);
+
+       ((rdpCupsPrinter*)printjob->printer)->printjob = NULL;
+}
+
+static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, uint32 id)
+{
+       rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
+       rdpCupsPrintJob* cups_printjob;
+
+       if (cups_printer->printjob != NULL)
+               return NULL;
+
+       cups_printjob = xnew(rdpCupsPrintJob);
+
+       cups_printjob->printjob.id = id;
+       cups_printjob->printjob.printer = printer;
+
+       cups_printjob->printjob.Write = printer_cups_write_printjob;
+       cups_printjob->printjob.Close = printer_cups_close_printjob;
+
+#ifndef _CUPS_API_1_4
+
+       cups_printjob->printjob_object = xstrdup(tmpnam(NULL));
+
+#else
+       {
+               char buf[100];
+
+               cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
+               if (cups_printjob->printjob_object == NULL)
+               {
+                       DEBUG_WARN("httpConnectEncrypt: %s", cupsLastErrorString());
+                       xfree(cups_printjob);
+                       return NULL;
+               }
+
+               printer_cups_get_printjob_name(buf, sizeof(buf));
+               cups_printjob->printjob_id = cupsCreateJob((http_t*)cups_printjob->printjob_object,
+                       printer->name, buf, 0, NULL);
+
+               if (cups_printjob->printjob_id == 0)
+               {
+                       DEBUG_WARN("cupsCreateJob: %s", cupsLastErrorString());
+                       httpClose((http_t*)cups_printjob->printjob_object);
+                       xfree(cups_printjob);
+                       return NULL;
+               }
+               cupsStartDocument((http_t*)cups_printjob->printjob_object,
+                       printer->name, cups_printjob->printjob_id, buf,
+                       CUPS_FORMAT_POSTSCRIPT, 1);
+       }
+
+#endif
+
+       cups_printer->printjob = cups_printjob;
+       
+       return (rdpPrintJob*)cups_printjob;
+}
+
+static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, uint32 id)
+{
+       rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
+
+       if (cups_printer->printjob == NULL)
+               return NULL;
+       if (cups_printer->printjob->printjob.id != id)
+               return NULL;
+
+       return (rdpPrintJob*)cups_printer->printjob;
+}
+
+static void printer_cups_free_printer(rdpPrinter* printer)
+{
+       rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer;
+
+       if (cups_printer->printjob)
+               cups_printer->printjob->printjob.Close((rdpPrintJob*)cups_printer->printjob);
+       xfree(printer->name);
+       xfree(printer);
+}
+
+static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, boolean is_default)
+{
+       rdpCupsPrinter* cups_printer;
+
+       cups_printer = xnew(rdpCupsPrinter);
+printf("*** created printer %s %X of size %d\n", name, cups_printer, sizeof(rdpCupsPrinter));
+
+       cups_printer->printer.id = cups_driver->id_sequence++;
+       cups_printer->printer.name = xstrdup(name);
+       /* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */
+       cups_printer->printer.driver = "MS Publisher Imagesetter";
+       cups_printer->printer.is_default = is_default;
+
+       cups_printer->printer.CreatePrintJob = printer_cups_create_printjob;
+       cups_printer->printer.FindPrintJob = printer_cups_find_printjob;
+       cups_printer->printer.Free = printer_cups_free_printer;
+
+       return (rdpPrinter*)cups_printer;
+}
+
+static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
+{
+       rdpPrinter** printers;
+       int num_printers;
+       cups_dest_t *dests;
+       cups_dest_t *dest;
+       int num_dests;
+       int i;
+
+       num_dests = cupsGetDests(&dests);
+       printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (num_dests + 1));
+       num_printers = 0;
+       for (i = 0, dest = dests; i < num_dests; i++, dest++)
+       {
+               if (dest->instance == NULL)
+               {
+                       printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*)driver,
+                               dest->name, dest->is_default);
+               }
+       }
+       cupsFreeDests(num_dests, dests);
+
+       return printers;
+}
+
+static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name)
+{
+       rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver;
+
+       return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? True : False);
+}
+
+static rdpCupsPrinterDriver* cups_driver = NULL;
+
+rdpPrinterDriver* printer_cups_get_driver(void)
+{
+       if (cups_driver == NULL)
+       {
+               cups_driver = xnew(rdpCupsPrinterDriver);
+
+               cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
+               cups_driver->driver.GetPrinter = printer_cups_get_printer;
+
+               cups_driver->id_sequence = 1;
+
+#ifdef _CUPS_API_1_4
+               DEBUG_SVC("using CUPS API 1.4");
+#else
+               DEBUG_SVC("using CUPS API 1.2");
+#endif
+       }
+
+       return (rdpPrinterDriver*)cups_driver;
+}
+
diff --git a/channels/rdpdr/printer/printer_cups.h b/channels/rdpdr/printer/printer_cups.h
new file mode 100644 (file)
index 0000000..c6e1ff5
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel - CUPS driver
+ *
+ * Copyright 2010-2011 Vic Lee
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PRINTER_CUPS_H
+#define __PRINTER_CUPS_H
+
+#include "printer_main.h"
+
+rdpPrinterDriver* printer_cups_get_driver(void);
+
+#endif
+
diff --git a/channels/rdpdr/printer/printer_main.c b/channels/rdpdr/printer/printer_main.c
new file mode 100644 (file)
index 0000000..b35e8c6
--- /dev/null
@@ -0,0 +1,339 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel
+ *
+ * Copyright 2010-2011 Vic Lee
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <freerdp/utils/stream.h>
+#include <freerdp/utils/unicode.h>
+#include <freerdp/utils/memory.h>
+#include <freerdp/utils/thread.h>
+#include <freerdp/utils/svc_plugin.h>
+
+#include "rdpdr_constants.h"
+#include "rdpdr_types.h"
+
+#ifdef CUPS_FOUND
+#include "printer_cups.h"
+#endif
+
+#include "printer_main.h"
+
+typedef struct _PRINTER_DEVICE PRINTER_DEVICE;
+struct _PRINTER_DEVICE
+{
+       DEVICE device;
+
+       rdpPrinter* printer;
+
+       LIST* irp_list;
+       freerdp_thread* thread;
+};
+
+static void printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp)
+{
+       rdpPrintJob* printjob = NULL;
+
+       if (printer_dev->printer != NULL)
+               printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer, irp->devman->id_sequence++);
+
+       if (printjob != NULL)
+       {
+               stream_write_uint32(irp->output, printjob->id); /* FileId */
+
+               DEBUG_SVC("printjob id: %d", printjob->id);
+       }
+       else
+       {
+               stream_write_uint32(irp->output, 0); /* FileId */
+               irp->IoStatus = STATUS_PRINT_QUEUE_FULL;
+
+               DEBUG_WARN("error creating print job.");
+       }
+
+       irp->Complete(irp);
+}
+
+static void printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp)
+{
+       rdpPrintJob* printjob = NULL;
+
+       if (printer_dev->printer != NULL)
+               printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
+
+       if (printjob == NULL)
+       {
+               irp->IoStatus = STATUS_UNSUCCESSFUL;
+
+               DEBUG_WARN("printjob id %d not found.", irp->FileId);
+       }
+       else
+       {
+               printjob->Close(printjob);
+
+               DEBUG_SVC("printjob id %d closed.", irp->FileId);
+       }
+
+       stream_write_zero(irp->output, 4); /* Padding(4) */
+
+       irp->Complete(irp);
+}
+
+static void printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp)
+{
+       rdpPrintJob* printjob = NULL;
+       uint32 Length;
+       uint64 Offset;
+
+       stream_read_uint32(irp->input, Length);
+       stream_read_uint64(irp->input, Offset);
+       stream_seek(irp->input, 20); /* Padding */
+
+       if (printer_dev->printer != NULL)
+               printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId);
+
+       if (printjob == NULL)
+       {
+               irp->IoStatus = STATUS_UNSUCCESSFUL;
+               Length = 0;
+
+               DEBUG_WARN("printjob id %d not found.", irp->FileId);
+       }
+       else
+       {
+               printjob->Write(printjob, stream_get_tail(irp->input), Length);
+
+               DEBUG_SVC("printjob id %d written %d bytes.", irp->FileId, Length);
+       }
+
+       stream_write_uint32(irp->output, Length);
+       stream_write_uint8(irp->output, 0); /* Padding */
+
+       irp->Complete(irp);
+}
+
+static void printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp)
+{
+       switch (irp->MajorFunction)
+       {
+               case IRP_MJ_CREATE:
+                       printer_process_irp_create(printer_dev, irp);
+                       break;
+
+               case IRP_MJ_CLOSE:
+                       printer_process_irp_close(printer_dev, irp);
+                       break;
+
+               case IRP_MJ_WRITE:
+                       printer_process_irp_write(printer_dev, irp);
+                       break;
+
+               default:
+                       DEBUG_WARN("MajorFunction 0x%X not supported", irp->MajorFunction);
+                       irp->IoStatus = STATUS_NOT_SUPPORTED;
+                       irp->Complete(irp);
+                       break;
+       }
+}
+
+static void printer_process_irp_list(PRINTER_DEVICE* printer_dev)
+{
+       IRP* irp;
+
+       while (1)
+       {
+               if (freerdp_thread_is_stopped(printer_dev->thread))
+                       break;
+
+               freerdp_thread_lock(printer_dev->thread);
+               irp = (IRP*)list_dequeue(printer_dev->irp_list);
+               freerdp_thread_unlock(printer_dev->thread);
+
+               if (irp == NULL)
+                       break;
+
+               printer_process_irp(printer_dev, irp);
+       }
+}
+
+static void* printer_thread_func(void* arg)
+{
+       PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)arg;
+
+       while (1)
+       {
+               freerdp_thread_wait(printer_dev->thread);
+
+               if (freerdp_thread_is_stopped(printer_dev->thread))
+                       break;
+
+               freerdp_thread_reset(printer_dev->thread);
+               printer_process_irp_list(printer_dev);
+       }
+
+       freerdp_thread_quit(printer_dev->thread);
+
+       return NULL;
+}
+
+static void printer_irp_request(DEVICE* device, IRP* irp)
+{
+       PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device;
+
+       freerdp_thread_lock(printer_dev->thread);
+       list_enqueue(printer_dev->irp_list, irp);
+       freerdp_thread_unlock(printer_dev->thread);
+
+       freerdp_thread_signal(printer_dev->thread);
+}
+
+static void printer_free(DEVICE* device)
+{
+       PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device;
+       IRP* irp;
+
+       freerdp_thread_stop(printer_dev->thread);
+       
+       while ((irp = (IRP*)list_dequeue(printer_dev->irp_list)) != NULL)
+               irp->Discard(irp);
+       list_free(printer_dev->irp_list);
+
+       if (printer_dev->printer)
+               printer_dev->printer->Free(printer_dev->printer);
+
+       xfree(printer_dev->device.name);
+
+       xfree(printer_dev);
+}
+
+void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer)
+{
+       PRINTER_DEVICE* printer_dev;
+       char* port;
+       UNICONV* uniconv;
+       uint32 Flags;
+       size_t DriverNameLen;
+       char* DriverName;
+       size_t PrintNameLen;
+       char* PrintName;
+       uint32 CachedFieldsLen;
+       uint8* CachedPrinterConfigData;
+
+       port = xmalloc(10);
+       snprintf(port, 10, "PRN%d", printer->id);
+
+       printer_dev = xnew(PRINTER_DEVICE);
+
+       printer_dev->device.type = RDPDR_DTYP_PRINT;
+       printer_dev->device.name = port;
+       printer_dev->device.IRPRequest = printer_irp_request;
+       printer_dev->device.Free = printer_free;
+
+       printer_dev->printer = printer;
+
+       CachedFieldsLen = 0;
+       CachedPrinterConfigData = NULL;
+
+printf("**** printer %s %X register\n", printer->name, printer);
+
+       Flags = 0;
+       if (printer->is_default)
+               Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
+
+       uniconv = freerdp_uniconv_new();
+       DriverName = freerdp_uniconv_out(uniconv, printer->driver, &DriverNameLen);
+       PrintName = freerdp_uniconv_out(uniconv, printer->name, &PrintNameLen);
+       freerdp_uniconv_free(uniconv);
+
+       printer_dev->device.data = stream_new(28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
+
+       stream_write_uint32(printer_dev->device.data, Flags);
+       stream_write_uint32(printer_dev->device.data, 0); /* CodePage, reserved */
+       stream_write_uint32(printer_dev->device.data, 0); /* PnPNameLen */
+       stream_write_uint32(printer_dev->device.data, DriverNameLen + 2);
+       stream_write_uint32(printer_dev->device.data, PrintNameLen + 2);
+       stream_write_uint32(printer_dev->device.data, CachedFieldsLen);
+       stream_write(printer_dev->device.data, DriverName, DriverNameLen);
+       stream_write_uint16(printer_dev->device.data, 0);
+       stream_write(printer_dev->device.data, PrintName, PrintNameLen);
+       stream_write_uint16(printer_dev->device.data, 0);
+       if (CachedFieldsLen > 0)
+       {
+               stream_write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen);
+       }
+
+       xfree(DriverName);
+       xfree(PrintName);
+
+       printer_dev->irp_list = list_new();
+       printer_dev->thread = freerdp_thread_new();
+
+       pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)printer_dev);
+
+       freerdp_thread_start(printer_dev->thread, printer_thread_func, printer_dev);
+}
+
+int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
+{
+       rdpPrinterDriver* driver = NULL;
+       rdpPrinter** printers;
+       rdpPrinter* printer;
+       int i;
+       char* name;
+       char* driver_name;
+
+#ifdef CUPS_FOUND
+       driver = printer_cups_get_driver();
+#endif
+       if (driver == NULL)
+       {
+               DEBUG_WARN("no driver.");
+               return 1;
+       }
+
+       name = (char*)pEntryPoints->plugin_data->data[1];
+       driver_name = (char*)pEntryPoints->plugin_data->data[2];
+
+       if (name && name[0])
+       {
+               printer = driver->GetPrinter(driver, name);
+               if (printer == NULL)
+               {
+                       DEBUG_WARN("printer %s not found.", name);
+                       return 1;
+               }
+               if (driver_name && driver_name[0])
+                       printer->driver = driver_name;
+
+               printer_register(pEntryPoints, printer);
+       }
+       else
+       {
+               printers = driver->EnumPrinters(driver);
+               for (i = 0; printers[i]; i++)
+               {
+                       printer = printers[i];
+                       printer_register(pEntryPoints, printer);
+               }
+               xfree(printers);
+       }
+
+       return 0;
+}
diff --git a/channels/rdpdr/printer/printer_main.h b/channels/rdpdr/printer/printer_main.h
new file mode 100644 (file)
index 0000000..256c4a7
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel
+ *
+ * Copyright 2010-2011 Vic Lee
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PRINTER_MAIN_H
+#define __PRINTER_MAIN_H
+
+#include "rdpdr_types.h"
+
+/* SERVER_PRINTER_CACHE_EVENT.cachedata */
+#define RDPDR_ADD_PRINTER_EVENT             0x00000001
+#define RDPDR_UPDATE_PRINTER_EVENT          0x00000002
+#define RDPDR_DELETE_PRINTER_EVENT          0x00000003
+#define RDPDR_RENAME_PRINTER_EVENT          0x00000004
+
+/* DR_PRN_DEVICE_ANNOUNCE.Flags */
+#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII           0x00000001
+#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER  0x00000002
+#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER  0x00000004
+#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER       0x00000008
+#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT       0x00000010
+
+typedef struct rdp_printer_driver rdpPrinterDriver;
+typedef struct rdp_printer rdpPrinter;
+typedef struct rdp_print_job rdpPrintJob;
+
+typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver);
+typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name);
+
+struct rdp_printer_driver
+{
+       pcEnumPrinters EnumPrinters;
+       pcGetPrinter GetPrinter;
+};
+
+typedef rdpPrintJob* (*pcCreatePrintJob) (rdpPrinter* printer, uint32 id);
+typedef rdpPrintJob* (*pcFindPrintJob) (rdpPrinter* printer, uint32 id);
+typedef void (*pcFreePrinter) (rdpPrinter* printer);
+
+struct rdp_printer
+{
+       int id;
+       char* name;
+       char* driver;
+       boolean is_default;
+
+       pcCreatePrintJob CreatePrintJob;
+       pcFindPrintJob FindPrintJob;
+       pcFreePrinter Free;
+};
+
+typedef void (*pcWritePrintJob) (rdpPrintJob* printjob, uint8* data, int size);
+typedef void (*pcClosePrintJob) (rdpPrintJob* printjob);
+
+struct rdp_print_job
+{
+       uint32 id;
+       rdpPrinter* printer;
+
+       pcWritePrintJob Write;
+       pcClosePrintJob Close;
+};
+
+#endif
index 5cc5057..360067b 100644 (file)
@@ -10,6 +10,9 @@
 #cmakedefine HAVE_FCNTL_H
 #cmakedefine HAVE_UNISTD_H
 
+/* Found packages */
+#cmakedefine CUPS_FOUND
+
 /* Endian */
 #cmakedefine BIG_ENDIAN