win32: make rdpdr printer plugin working on win32
authorrichterger <richter@ecos.de>
Tue, 2 Oct 2012 07:10:21 +0000 (09:10 +0200)
committerrichterger <richter@ecos.de>
Tue, 2 Oct 2012 07:10:21 +0000 (09:10 +0200)
channels/rdpdr/client/CMakeLists.txt
channels/rdpdr/client/printer/CMakeLists.txt
channels/rdpdr/client/printer/printer_main.c
channels/rdpdr/client/printer/printer_win.c [new file with mode: 0644]
channels/rdpdr/client/printer/printer_win.h [new file with mode: 0644]
client/Windows/CMakeLists.txt
client/Windows/wfreerdp.c

index 8547706..a3fa82e 100644 (file)
@@ -41,8 +41,8 @@ endif()
 install(TARGETS rdpdr DESTINATION ${FREERDP_PLUGIN_PATH})
 
 add_subdirectory(disk)
+add_subdirectory(printer)
 if(NOT WIN32)
-       add_subdirectory(printer)
        add_subdirectory(parallel)
        add_subdirectory(serial)
 endif()
index ea4e19f..91dd648 100644 (file)
@@ -31,6 +31,13 @@ if(WITH_CUPS)
        add_definitions(-DWITH_CUPS)
 endif()
 
+if(WIN32)
+       set(PRINTER_SRCS
+               ${PRINTER_SRCS}
+               printer_win.c
+               printer_win.h)
+endif()
+
 include_directories(..)
 
 add_library(printer ${PRINTER_SRCS})
index a4db937..2716472 100644 (file)
 
 #include "printer_main.h"
 
+#ifdef WIN32
+#include "printer_win.h"
+#endif
+
 typedef struct _PRINTER_DEVICE PRINTER_DEVICE;
 struct _PRINTER_DEVICE
 {
@@ -294,7 +298,11 @@ void printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* pri
        freerdp_thread_start(printer_dev->thread, printer_thread_func, printer_dev);
 }
 
+#ifdef WITH_STATIC_PLUGINS
+int printer_entry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
+#else
 int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
+#endif
 {
        rdpPrinterDriver* driver = NULL;
        rdpPrinter** printers;
@@ -306,6 +314,9 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
 #ifdef WITH_CUPS
        driver = printer_cups_get_driver();
 #endif
+#ifdef WIN32
+       driver = printer_win_get_driver();
+#endif
        if (driver == NULL)
        {
                DEBUG_WARN("no driver.");
diff --git a/channels/rdpdr/client/printer/printer_win.c b/channels/rdpdr/client/printer/printer_win.c
new file mode 100644 (file)
index 0000000..6b00704
--- /dev/null
@@ -0,0 +1,283 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel - WIN driver
+ *
+ * Copyright 2012 Gerald Richter
+ *
+ * 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 <windows.h>
+#include <winspool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "config.h"
+#include <freerdp/utils/memory.h>
+#include <freerdp/utils/svc_plugin.h>
+
+#include "rdpdr_types.h"
+#include "printer_main.h"
+
+#include "printer_win.h"
+
+typedef struct rdp_win_printer_driver rdpWinPrinterDriver;
+typedef struct rdp_win_printer rdpWinPrinter;
+typedef struct rdp_win_print_job rdpWinPrintJob;
+
+struct rdp_win_printer_driver
+{
+       rdpPrinterDriver driver;
+
+       int id_sequence;
+};
+
+struct rdp_win_printer
+{
+       rdpPrinter printer;
+       HANDLE hPrinter;
+       rdpWinPrintJob* printjob;
+};
+
+struct rdp_win_print_job
+{
+       rdpPrintJob printjob;
+       DOC_INFO_1 di;
+       DWORD handle;
+
+       void* printjob_object;
+       int printjob_id;
+};
+
+static void printer_win_get_printjob_name(char* buf, int size)
+{
+       time_t tt;
+       struct tm* t;
+
+       DEBUG_WINPR("");
+
+       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);
+
+       DEBUG_WINPR("buf: %s", buf);
+
+}
+
+static void printer_win_write_printjob(rdpPrintJob* printjob, uint8* data, int size)
+{
+       rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob;
+
+       LPVOID pBuf = data;
+       DWORD cbBuf = size;
+       DWORD pcWritten;
+
+       if( ! WritePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten ) ) 
+                       DEBUG_WINPR("WritePrinter failed");
+;
+}
+
+static void printer_win_close_printjob(rdpPrintJob* printjob)
+{
+       rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob;
+
+       DEBUG_WINPR("");
+
+       if ( ! EndPagePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) )
+               DEBUG_WINPR("EndPagePrinter failed");;
+       if ( ! ClosePrinter( ((rdpWinPrinter*)printjob->printer)->hPrinter ) ) 
+               DEBUG_WINPR("ClosePrinter failed");;
+
+       ((rdpWinPrinter*)printjob->printer)->printjob = NULL;
+       xfree(win_printjob) ;
+}
+
+static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, uint32 id)
+{
+       rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
+       rdpWinPrintJob* win_printjob;
+
+       DEBUG_WINPR("");
+
+       if (win_printer->printjob != NULL)
+               return NULL;
+
+       win_printjob = xnew(rdpWinPrintJob);
+
+       win_printjob->printjob.id = id;
+       win_printjob->printjob.printer = printer;
+       win_printjob->di.pDocName = L"FREERDPjob";
+       win_printjob->di.pDatatype= NULL;
+       win_printjob->di.pOutputFile = NULL;
+
+       win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE)&(win_printjob->di) );
+       if(! win_printjob->handle) DEBUG_WINPR("StartDocPrinter failed");
+       if ( ! StartPagePrinter(win_printer->hPrinter) )
+                               DEBUG_WINPR("ClosePrinter failed");
+
+
+       win_printjob->printjob.Write = printer_win_write_printjob;
+       win_printjob->printjob.Close = printer_win_close_printjob;
+
+
+
+       win_printer->printjob = win_printjob;
+       
+       return (rdpPrintJob*)win_printjob;
+}
+
+static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, uint32 id)
+{
+       rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
+
+               DEBUG_WINPR("");
+
+       if (win_printer->printjob == NULL)
+               return NULL;
+       if (win_printer->printjob->printjob.id != id)
+               return NULL;
+
+       return (rdpPrintJob*)win_printer->printjob;
+}
+
+static void printer_win_free_printer(rdpPrinter* printer)
+{
+       rdpWinPrinter* win_printer = (rdpWinPrinter*)printer;
+
+               DEBUG_WINPR("");
+
+       if (win_printer->printjob)
+               win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob);
+       xfree(printer->name);
+       xfree(printer);
+}
+
+static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, boolean is_default)
+{
+       rdpWinPrinter* win_printer;
+    wchar_t wname[256];
+       DWORD needed;
+       PRINTER_INFO_2 *prninfo=NULL;
+       size_t charsConverted;
+       DEBUG_WINPR("");
+
+       win_printer = xnew(rdpWinPrinter);
+
+       win_printer->printer.id = win_driver->id_sequence++;
+       win_printer->printer.name = xstrdup(name);
+       win_printer->printer.is_default = is_default;
+
+       win_printer->printer.CreatePrintJob = printer_win_create_printjob;
+       win_printer->printer.FindPrintJob = printer_win_find_printjob;
+       win_printer->printer.Free = printer_win_free_printer;
+
+    swprintf(wname, 256, L"%hs", name);
+       OpenPrinter(wname, &(win_printer->hPrinter), NULL);
+       DEBUG_WINPR("handle: 0x%08X", win_printer->hPrinter);
+
+       GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, 0, &needed);
+       prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
+       GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, needed, &needed);
+
+       win_printer->printer.driver = xmalloc(1000);
+       wcstombs_s(&charsConverted, win_printer->printer.driver, 1000, prninfo->pDriverName, _TRUNCATE);
+
+       return (rdpPrinter*)win_printer;
+}
+
+static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
+{
+       rdpPrinter** printers;
+       int num_printers;
+       int i;
+       char pname[1000];
+       size_t charsConverted;
+
+       PRINTER_INFO_2 *prninfo=NULL;
+    DWORD needed, returned;
+    DEBUG_WINPR("");
+
+
+    //find required size for the buffer
+    EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, &returned);
+
+
+    //allocate array of PRINTER_INFO structures
+    prninfo = (PRINTER_INFO_2*) GlobalAlloc(GPTR,needed);
+    //call again
+    if ( !EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE) prninfo, needed, &needed, &returned) ) {
+               DEBUG_WINPR("EnumPrinters failed");
+
+       } ; /* eRROR... */
+
+       DEBUG_WINPR("printers found: %d", returned);
+
+
+       printers = (rdpPrinter**)xzalloc(sizeof(rdpPrinter*) * (returned + 1));
+       num_printers = 0;       
+
+       for (i = 0; i < (int)returned; i++)
+       {
+               wcstombs_s(&charsConverted, pname, 1000, prninfo[i].pPrinterName, _TRUNCATE);
+               printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver,
+                       pname, prninfo[i].pDriverName, 0);
+       }
+
+       GlobalFree(prninfo);
+       return printers;
+}
+
+static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* name)
+{
+       rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
+       rdpPrinter *myPrinter = NULL;
+
+       DEBUG_WINPR("printer %s", name);
+       
+       myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? true : false);
+       
+       return myPrinter;
+}
+
+static rdpWinPrinterDriver* win_driver = NULL;
+
+rdpPrinterDriver* printer_win_get_driver(void)
+{
+       DEBUG_WINPR("");
+
+       if (win_driver == NULL)
+       {
+               win_driver = xnew(rdpWinPrinterDriver);
+
+               win_driver->driver.EnumPrinters = printer_win_enum_printers;
+               win_driver->driver.GetPrinter = printer_win_get_printer;
+
+               win_driver->id_sequence = 1;
+
+//#ifdef _win_API_1_4
+//             DEBUG_SVC("using win API 1.4");
+//#else
+//             DEBUG_SVC("using win API 1.2");
+//#endif
+       }
+
+       return (rdpPrinterDriver*)win_driver;
+}
+
diff --git a/channels/rdpdr/client/printer/printer_win.h b/channels/rdpdr/client/printer/printer_win.h
new file mode 100644 (file)
index 0000000..5b694ac
--- /dev/null
@@ -0,0 +1,37 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol client.
+ * Print Virtual Channel - win driver
+ *
+ * Copyright 2012 Gerald Richter
+ *
+ * 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_WIN_H
+#define __PRINTER_WIN_H
+
+
+rdpPrinterDriver* printer_win_get_driver(void);
+
+#ifdef WITH_DEBUG_WINPR
+#define DEBUG_WINPR(fmt, ...) DEBUG_CLASS(WINPR, fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_WINPR(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
+#endif
+
+#endif
+
+#ifdef WIN32
+#define snprintf _snprintf
+#endif 
+
index 527ab1b..d3ba988 100644 (file)
@@ -36,7 +36,7 @@ add_executable(wfreerdp WIN32 ${FREERDP_CLIENT_WINDOWS_SRCS})
 if(WITH_MONOLITHIC_BUILD)
        set(FREERDP_CLIENT_WINDOWS_LIBS ${FREERDP_CLIENT_WINDOWS_LIBS} freerdp)
     if(WITH_RDPDR)
-        set(FREERDP_CLIENT_WINDOWS_LIBS ${FREERDP_CLIENT_WINDOWS_LIBS} rdpdr disk)
+        set(FREERDP_CLIENT_WINDOWS_LIBS ${FREERDP_CLIENT_WINDOWS_LIBS} rdpdr disk printer)
     endif()
 else()
        set(FREERDP_CLIENT_WINDOWS_LIBS ${FREERDP_CLIENT_WINDOWS_LIBS}
index f44572c..04cfc7a 100644 (file)
@@ -636,6 +636,7 @@ static DWORD WINAPI kbd_thread_func(LPVOID lpParam)
 #ifdef WITH_RDPDR
 DEFINE_SVC_PLUGIN_ENTRY(rdpdr) ;
 DEFINE_DEV_PLUGIN_ENTRY(disk) ;
+DEFINE_DEV_PLUGIN_ENTRY(printer) ;
 #endif
 
 
@@ -699,6 +700,7 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
 #ifdef WITH_RDPDR
         REGISTER_SVC_PLUGIN_ENTRY(rdpdr) ;
         REGISTER_DEV_PLUGIN_ENTRY(disk) ;
+        REGISTER_DEV_PLUGIN_ENTRY(printer) ;
 #endif
 
         if (!CreateThread(NULL, 0, kbd_thread_func, NULL, 0, NULL))