Modified printer backend to allow dynamic backends.
This commit is contained in:
parent
2670d83cdd
commit
88c654ee1d
@ -18,39 +18,23 @@
|
||||
define_channel_client("printer")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
printer_main.c
|
||||
printer_main.h)
|
||||
|
||||
if(WITH_CUPS)
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
|
||||
printer_cups.c
|
||||
printer_cups.h)
|
||||
|
||||
include_directories(${CUPS_INCLUDE_DIR})
|
||||
add_definitions(-DWITH_CUPS)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT UWP)
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}
|
||||
printer_win.c
|
||||
printer_win.h)
|
||||
endif()
|
||||
printer_main.c)
|
||||
|
||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
|
||||
|
||||
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
||||
|
||||
if(WITH_CUPS)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CUPS_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
|
||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS)
|
||||
install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
|
||||
endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
||||
|
||||
if(WITH_CUPS)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "cups" "")
|
||||
endif()
|
||||
|
||||
if(WIN32 AND NOT UWP)
|
||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "win" "")
|
||||
endif()
|
||||
|
32
channels/printer/client/cups/CMakeLists.txt
Normal file
32
channels/printer/client/cups/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
# Copyright 2019 Thincast Technologies GmbH
|
||||
#
|
||||
# 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.
|
||||
define_channel_client_subsystem("printer" "cups" "")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
printer_cups.c)
|
||||
|
||||
include_directories(..)
|
||||
include_directories(${CUPS_INCLUDE_DIR})
|
||||
add_definitions(-DWITH_CUPS)
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CUPS_LIBRARIES})
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
@ -37,9 +37,7 @@
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
#include "printer_main.h"
|
||||
|
||||
#include "printer_cups.h"
|
||||
#include <freerdp/client/printer.h>
|
||||
|
||||
typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver;
|
||||
typedef struct rdp_cups_printer rdpCupsPrinter;
|
||||
@ -50,6 +48,7 @@ struct rdp_cups_printer_driver
|
||||
rdpPrinterDriver driver;
|
||||
|
||||
int id_sequence;
|
||||
size_t references;
|
||||
};
|
||||
|
||||
struct rdp_cups_printer
|
||||
@ -67,16 +66,16 @@ struct rdp_cups_print_job
|
||||
int printjob_id;
|
||||
};
|
||||
|
||||
static void printer_cups_get_printjob_name(char* buf, int size)
|
||||
static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id)
|
||||
{
|
||||
time_t tt;
|
||||
struct tm* t;
|
||||
|
||||
tt = time(NULL);
|
||||
t = localtime(&tt);
|
||||
sprintf_s(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
|
||||
sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %"PRIdz,
|
||||
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec);
|
||||
t->tm_hour, t->tm_min, t->tm_sec, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +125,7 @@ static void printer_cups_close_printjob(rdpPrintJob* printjob)
|
||||
{
|
||||
char buf[100];
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf), printjob->id);
|
||||
|
||||
if (cupsPrintFile(printjob->printer->name, (const char*) cups_printjob->printjob_object, buf, 0, NULL) == 0)
|
||||
{
|
||||
@ -188,7 +187,7 @@ static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf));
|
||||
printer_cups_get_printjob_name(buf, sizeof(buf), cups_printjob->printjob.id);
|
||||
|
||||
cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
|
||||
printer->name, buf, 0, NULL);
|
||||
@ -230,11 +229,29 @@ static void printer_cups_free_printer(rdpPrinter* printer)
|
||||
if (cups_printer->printjob)
|
||||
cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob);
|
||||
|
||||
if (printer->backend)
|
||||
printer->backend->ReleaseRef(printer->backend);
|
||||
free(printer->name);
|
||||
free(printer->driver);
|
||||
free(printer);
|
||||
}
|
||||
|
||||
static void printer_cups_add_ref_printer(rdpPrinter* printer)
|
||||
{
|
||||
if (printer)
|
||||
printer->references++;
|
||||
}
|
||||
|
||||
static void printer_cups_release_ref_printer(rdpPrinter* printer)
|
||||
{
|
||||
if (!printer)
|
||||
return;
|
||||
if (printer->references <= 1)
|
||||
printer_cups_free_printer(printer);
|
||||
else
|
||||
printer->references--;
|
||||
}
|
||||
|
||||
static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
|
||||
const char* name, const char* driverName, BOOL is_default)
|
||||
{
|
||||
@ -244,6 +261,8 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
|
||||
if (!cups_printer)
|
||||
return NULL;
|
||||
|
||||
cups_printer->printer.backend = &cups_driver->driver;
|
||||
|
||||
cups_printer->printer.id = cups_driver->id_sequence++;
|
||||
cups_printer->printer.name = _strdup(name);
|
||||
if (!cups_printer->printer.name)
|
||||
@ -266,9 +285,26 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
|
||||
|
||||
cups_printer->printer.CreatePrintJob = printer_cups_create_printjob;
|
||||
cups_printer->printer.FindPrintJob = printer_cups_find_printjob;
|
||||
cups_printer->printer.Free = printer_cups_free_printer;
|
||||
cups_printer->printer.AddRef = printer_cups_add_ref_printer;
|
||||
cups_printer->printer.ReleaseRef = printer_cups_release_ref_printer;
|
||||
|
||||
return (rdpPrinter*) cups_printer;
|
||||
|
||||
cups_printer->printer.AddRef(&cups_printer->printer);
|
||||
cups_printer->printer.backend->AddRef(cups_printer->printer.backend);
|
||||
return &cups_printer->printer;
|
||||
}
|
||||
|
||||
static void printer_cups_release_enum_printers(rdpPrinter** printers)
|
||||
{
|
||||
rdpPrinter** cur = printers;
|
||||
|
||||
while((cur != NULL) && ((*cur) != NULL))
|
||||
{
|
||||
if ((*cur)->ReleaseRef)
|
||||
(*cur)->ReleaseRef(*cur);
|
||||
cur++;
|
||||
}
|
||||
free(printers);
|
||||
}
|
||||
|
||||
static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
@ -291,8 +327,17 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||
{
|
||||
if (dest->instance == NULL)
|
||||
{
|
||||
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
|
||||
rdpPrinter* current = printers[num_printers];
|
||||
current = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
|
||||
dest->name, NULL, dest->is_default);
|
||||
if (!current)
|
||||
{
|
||||
printer_cups_release_enum_printers(printers);
|
||||
printers = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
printers[num_printers++] = current;
|
||||
}
|
||||
}
|
||||
cupsFreeDests(num_dests, dests);
|
||||
@ -309,11 +354,35 @@ static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver,
|
||||
cups_driver->id_sequence == 1 ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
static void printer_cups_add_ref_driver(rdpPrinterDriver* driver)
|
||||
{
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
|
||||
if (cups_driver)
|
||||
cups_driver->references++;
|
||||
}
|
||||
|
||||
/* Singleton */
|
||||
static rdpCupsPrinterDriver* cups_driver = NULL;
|
||||
|
||||
rdpPrinterDriver* printer_cups_get_driver(void)
|
||||
static void printer_cups_release_ref_driver(rdpPrinterDriver* driver)
|
||||
{
|
||||
if (cups_driver == NULL)
|
||||
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
|
||||
if (cups_driver->references <= 1)
|
||||
{
|
||||
free(cups_driver);
|
||||
cups_driver = NULL;
|
||||
}
|
||||
else
|
||||
cups_driver->references--;
|
||||
}
|
||||
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
rdpPrinterDriver *cups_freerdp_printer_client_subsystem_entry(void)
|
||||
#else
|
||||
FREERDP_API rdpPrinterDriver *freerdp_printer_client_subsystem_entry(void)
|
||||
#endif
|
||||
{
|
||||
if (!cups_driver)
|
||||
{
|
||||
cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver));
|
||||
|
||||
@ -321,11 +390,15 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
||||
return NULL;
|
||||
|
||||
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
|
||||
cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers;
|
||||
cups_driver->driver.GetPrinter = printer_cups_get_printer;
|
||||
|
||||
cups_driver->driver.AddRef = printer_cups_add_ref_driver;
|
||||
cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver;
|
||||
|
||||
cups_driver->id_sequence = 1;
|
||||
cups_driver->driver.AddRef(&cups_driver->driver);
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*) cups_driver;
|
||||
return &cups_driver->driver;
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_CHANNEL_PRINTER_CLIENT_CUPS_H
|
||||
#define FREERDP_CHANNEL_PRINTER_CLIENT_CUPS_H
|
||||
|
||||
#include "printer_main.h"
|
||||
|
||||
rdpPrinterDriver* printer_cups_get_driver(void);
|
||||
|
||||
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_CUPS_H */
|
||||
|
@ -42,15 +42,7 @@
|
||||
|
||||
#include "../printer.h"
|
||||
|
||||
#ifdef WITH_CUPS
|
||||
#include "printer_cups.h"
|
||||
#endif
|
||||
|
||||
#include "printer_main.h"
|
||||
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
#include "printer_win.h"
|
||||
#endif
|
||||
#include <freerdp/client/printer.h>
|
||||
|
||||
#include <freerdp/channels/log.h>
|
||||
|
||||
@ -863,7 +855,7 @@ static UINT printer_free(DEVICE* device)
|
||||
_aligned_free(printer_dev->pIrpList);
|
||||
|
||||
if (printer_dev->printer)
|
||||
printer_dev->printer->Free(printer_dev->printer);
|
||||
printer_dev->printer->ReleaseRef(printer_dev->printer);
|
||||
|
||||
Stream_Free(printer_dev->device.data, TRUE);
|
||||
free(printer_dev);
|
||||
@ -875,7 +867,7 @@ static UINT printer_free(DEVICE* device)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
static UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
rdpPrinter* printer)
|
||||
{
|
||||
PRINTER_DEVICE* printer_dev;
|
||||
@ -945,39 +937,69 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
printer->AddRef(printer);
|
||||
return CHANNEL_RC_OK;
|
||||
error_out:
|
||||
printer_free(&printer_dev->device);
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
#define DeviceServiceEntry printer_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
#endif
|
||||
static rdpPrinterDriver* printer_load_backend(const char* backend)
|
||||
{
|
||||
typedef rdpPrinterDriver* (*backend_load_t)(void);
|
||||
|
||||
backend_load_t entry = (backend_load_t)freerdp_load_channel_addin_entry("printer", backend, NULL, 0);
|
||||
if (!entry)
|
||||
return NULL;
|
||||
|
||||
return entry();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
UINT
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
printer_DeviceServiceEntry
|
||||
#else
|
||||
FREERDP_API DeviceServiceEntry
|
||||
#endif
|
||||
(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
{
|
||||
int i;
|
||||
char* name;
|
||||
char* driver_name;
|
||||
rdpPrinter* printer;
|
||||
rdpPrinter** printers;
|
||||
RDPDR_PRINTER* device;
|
||||
RDPDR_PRINTER* device = NULL;
|
||||
rdpPrinterDriver* driver = NULL;
|
||||
UINT error;
|
||||
#ifdef WITH_CUPS
|
||||
driver = printer_cups_get_driver();
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(_UWP)
|
||||
driver = printer_win_get_driver();
|
||||
#endif
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
size_t pos;
|
||||
|
||||
if (!pEntryPoints || !pEntryPoints->device)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
device = (RDPDR_PRINTER*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
driver_name = device->DriverName;
|
||||
|
||||
/* Secondary argument is one of the following:
|
||||
*
|
||||
* <driver_name> ... name of a printer driver
|
||||
* <driver_name>:<backend_name> ... name of a printer driver and local printer backend to use
|
||||
*/
|
||||
if (driver_name)
|
||||
{
|
||||
char* sep = strstr(driver_name, ":");
|
||||
if (sep)
|
||||
{
|
||||
const char* backend = sep + 1;
|
||||
*sep = '\0';
|
||||
driver = printer_load_backend(backend);
|
||||
}
|
||||
}
|
||||
else
|
||||
driver = printer_load_backend("");
|
||||
|
||||
if (!driver)
|
||||
{
|
||||
@ -985,47 +1007,52 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
}
|
||||
|
||||
device = (RDPDR_PRINTER*) pEntryPoints->device;
|
||||
name = device->Name;
|
||||
driver_name = device->DriverName;
|
||||
|
||||
if (name && name[0])
|
||||
{
|
||||
printer = driver->GetPrinter(driver, name, driver_name);
|
||||
rdpPrinter* printer = driver->GetPrinter(driver, name, driver_name);
|
||||
|
||||
if (!printer)
|
||||
{
|
||||
WLog_ERR(TAG, "Could not get printer %s!", name);
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
error = CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!printer_save_default_config(pEntryPoints->rdpcontext->settings, printer))
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
{
|
||||
error = CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
printer->ReleaseRef(printer);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((error = printer_register(pEntryPoints, printer)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
||||
return error;
|
||||
printer->ReleaseRef(printer);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printers = driver->EnumPrinters(driver);
|
||||
rdpPrinter** printers = driver->EnumPrinters(driver);
|
||||
rdpPrinter** current = printers;
|
||||
|
||||
for (i = 0; printers[i]; i++)
|
||||
for (i = 0; current[i]; i++)
|
||||
{
|
||||
printer = printers[i];
|
||||
rdpPrinter* printer = current[i];
|
||||
|
||||
if ((error = printer_register(pEntryPoints, printer)))
|
||||
{
|
||||
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
||||
free(printers);
|
||||
return error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(printers);
|
||||
driver->ReleaseEnumPrinters(printers);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
fail:
|
||||
driver->ReleaseRef(driver);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* 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 FREERDP_CHANNEL_PRINTER_CLIENT_WIN_H
|
||||
#define FREERDP_CHANNEL_PRINTER_CLIENT_WIN_H
|
||||
|
||||
#include <freerdp/channels/log.h>
|
||||
|
||||
rdpPrinterDriver* printer_win_get_driver(void);
|
||||
|
||||
#define PRINTER_TAG CHANNELS_TAG("printer.client")
|
||||
#ifdef WITH_DEBUG_WINPR
|
||||
#define DEBUG_WINPR(...) WLog_DBG(PRINTER_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_WINPR(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_WIN_H */
|
||||
|
29
channels/printer/client/win/CMakeLists.txt
Normal file
29
channels/printer/client/win/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2019 Armin Novak <armin.novak@thincast.com>
|
||||
# Copyright 2019 Thincast Technologies GmbH
|
||||
#
|
||||
# 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.
|
||||
define_channel_client_subsystem("printer" "win" "")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
printer_win.c)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
@ -34,9 +34,14 @@
|
||||
#include <string.h>
|
||||
#include <winspool.h>
|
||||
|
||||
#include "printer_main.h"
|
||||
#include <freerdp/client/printer.h>
|
||||
|
||||
#include "printer_win.h"
|
||||
#define PRINTER_TAG CHANNELS_TAG("printer.client")
|
||||
#ifdef WITH_DEBUG_WINPR
|
||||
#define DEBUG_WINPR(...) WLog_DBG(PRINTER_TAG, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_WINPR(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
typedef struct rdp_win_printer_driver rdpWinPrinterDriver;
|
||||
typedef struct rdp_win_printer rdpWinPrinter;
|
||||
@ -46,7 +51,8 @@ struct rdp_win_printer_driver
|
||||
{
|
||||
rdpPrinterDriver driver;
|
||||
|
||||
int id_sequence;
|
||||
size_t id_sequence;
|
||||
size_t references;
|
||||
};
|
||||
|
||||
struct rdp_win_printer
|
||||
@ -66,16 +72,26 @@ struct rdp_win_print_job
|
||||
int printjob_id;
|
||||
};
|
||||
|
||||
static void printer_win_get_printjob_name(char* buf, int size)
|
||||
static WCHAR* printer_win_get_printjob_name(size_t id)
|
||||
{
|
||||
time_t tt;
|
||||
struct tm* t;
|
||||
WCHAR* str;
|
||||
size_t len = 1024;
|
||||
int rc;
|
||||
|
||||
tt = time(NULL);
|
||||
t = localtime(&tt);
|
||||
sprintf_s(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
|
||||
|
||||
str = calloc(len, sizeof(WCHAR));
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
rc = swprintf_s(str, len, L"FreeRDP Print %04d-%02d-%02d% 02d-%02d-%02d - Job %lu\0",
|
||||
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
||||
t->tm_hour, t->tm_min, t->tm_sec);
|
||||
t->tm_hour, t->tm_min, t->tm_sec, id);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,15 +99,21 @@ static void printer_win_get_printjob_name(char* buf, int size)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
|
||||
static UINT printer_win_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size)
|
||||
{
|
||||
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob;
|
||||
|
||||
LPVOID pBuf = data;
|
||||
rdpWinPrinter* printer;
|
||||
LPCVOID pBuf = data;
|
||||
DWORD cbBuf = size;
|
||||
DWORD pcWritten;
|
||||
|
||||
if(!WritePrinter(((rdpWinPrinter*)printjob->printer)->hPrinter, pBuf, cbBuf, &pcWritten))
|
||||
if (!printjob || !data)
|
||||
return ERROR_BAD_ARGUMENTS;
|
||||
|
||||
printer = (rdpWinPrinter*)printjob->printer;
|
||||
if (!printer)
|
||||
return ERROR_BAD_ARGUMENTS;
|
||||
|
||||
if(!WritePrinter(printer->hPrinter, pBuf, cbBuf, &pcWritten))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
@ -99,19 +121,28 @@ static UINT printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int si
|
||||
static void printer_win_close_printjob(rdpPrintJob* printjob)
|
||||
{
|
||||
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob;
|
||||
rdpWinPrinter* win_printer;
|
||||
|
||||
if (!EndPagePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
|
||||
if (!printjob)
|
||||
return;
|
||||
|
||||
win_printer = (rdpWinPrinter*)printjob->printer;
|
||||
if (!win_printer)
|
||||
return;
|
||||
|
||||
if (!EndPagePrinter(win_printer->hPrinter))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (!ClosePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
|
||||
if (!ClosePrinter(win_printer->hPrinter))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
((rdpWinPrinter*) printjob->printer)->printjob = NULL;
|
||||
win_printer->printjob = NULL;
|
||||
|
||||
free(win_printjob->di.pDocName);
|
||||
free(win_printjob);
|
||||
}
|
||||
|
||||
@ -129,7 +160,7 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
|
||||
win_printjob->printjob.id = id;
|
||||
win_printjob->printjob.printer = printer;
|
||||
win_printjob->di.pDocName = L"FREERDPjob";
|
||||
win_printjob->di.pDocName = printer_win_get_printjob_name(id);
|
||||
win_printjob->di.pDatatype= NULL;
|
||||
win_printjob->di.pOutputFile = NULL;
|
||||
|
||||
@ -137,12 +168,14 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
|
||||
if (!win_printjob->handle)
|
||||
{
|
||||
free(win_printjob->di.pDocName);
|
||||
free(win_printjob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!StartPagePrinter(win_printer->hPrinter))
|
||||
{
|
||||
free(win_printjob->di.pDocName);
|
||||
free(win_printjob);
|
||||
return NULL;
|
||||
}
|
||||
@ -152,7 +185,7 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||
|
||||
win_printer->printjob = win_printjob;
|
||||
|
||||
return (rdpPrintJob*) win_printjob;
|
||||
return &win_printjob->printjob;
|
||||
}
|
||||
|
||||
static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id)
|
||||
@ -175,11 +208,30 @@ static void printer_win_free_printer(rdpPrinter* printer)
|
||||
if (win_printer->printjob)
|
||||
win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob);
|
||||
|
||||
if (printer->backend)
|
||||
printer->backend->ReleaseRef(printer->backend);
|
||||
|
||||
free(printer->name);
|
||||
free(printer->driver);
|
||||
free(printer);
|
||||
}
|
||||
|
||||
static void printer_win_add_ref_printer(rdpPrinter* printer)
|
||||
{
|
||||
if (printer)
|
||||
printer->references++;
|
||||
}
|
||||
|
||||
static void printer_win_release_ref_printer(rdpPrinter* printer)
|
||||
{
|
||||
if (!printer)
|
||||
return;
|
||||
if (printer->references <= 1)
|
||||
printer_win_free_printer(printer);
|
||||
else
|
||||
printer->references--;
|
||||
}
|
||||
|
||||
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||
const WCHAR* name, const WCHAR* drivername, BOOL is_default)
|
||||
{
|
||||
@ -192,6 +244,7 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||
if (!win_printer)
|
||||
return NULL;
|
||||
|
||||
win_printer->printer.backend = &win_driver->driver;
|
||||
win_printer->printer.id = win_driver->id_sequence++;
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, name, -1, &win_printer->printer.name, 0, NULL, NULL) < 1)
|
||||
{
|
||||
@ -208,7 +261,8 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||
|
||||
win_printer->printer.CreatePrintJob = printer_win_create_printjob;
|
||||
win_printer->printer.FindPrintJob = printer_win_find_printjob;
|
||||
win_printer->printer.Free = printer_win_free_printer;
|
||||
win_printer->printer.AddRef = printer_win_add_ref_printer;
|
||||
win_printer->printer.ReleaseRef = printer_win_release_ref_printer;
|
||||
|
||||
if (!OpenPrinter(name, &(win_printer->hPrinter), NULL))
|
||||
{
|
||||
@ -254,7 +308,22 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (rdpPrinter*)win_printer;
|
||||
win_printer->printer.AddRef(&win_printer->printer);
|
||||
win_printer->printer.backend->AddRef(win_printer->printer.backend);
|
||||
return &win_printer->printer;
|
||||
}
|
||||
|
||||
static void printer_win_release_enum_printers(rdpPrinter** printers)
|
||||
{
|
||||
rdpPrinter** cur = printers;
|
||||
|
||||
while((cur != NULL) && ((*cur) != NULL))
|
||||
{
|
||||
if ((*cur)->ReleaseRef)
|
||||
(*cur)->ReleaseRef(*cur);
|
||||
cur++;
|
||||
}
|
||||
free(printers);
|
||||
}
|
||||
|
||||
static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
|
||||
@ -291,8 +360,16 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
|
||||
|
||||
for (i = 0; i < (int) returned; i++)
|
||||
{
|
||||
printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver,
|
||||
rdpPrinter* current = printers[num_printers];
|
||||
current = printer_win_new_printer((rdpWinPrinterDriver*)driver,
|
||||
prninfo[i].pPrinterName, prninfo[i].pDriverName, 0);
|
||||
if (!current)
|
||||
{
|
||||
printer_win_release_enum_printers(printers);
|
||||
printers = NULL;
|
||||
break;
|
||||
}
|
||||
printers[num_printers++] = current;
|
||||
}
|
||||
|
||||
GlobalFree(prninfo);
|
||||
@ -303,9 +380,16 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
|
||||
const char* name, const char* driverName)
|
||||
{
|
||||
WCHAR* driverNameW = NULL;
|
||||
WCHAR* nameW = NULL;
|
||||
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
|
||||
rdpPrinter *myPrinter = NULL;
|
||||
|
||||
if (name)
|
||||
{
|
||||
ConvertToUnicode(CP_UTF8, 0, name, -1, &nameW, 0);
|
||||
if (!driverNameW)
|
||||
return NULL;
|
||||
}
|
||||
if (driverName)
|
||||
{
|
||||
ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0);
|
||||
@ -313,29 +397,64 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
myPrinter = printer_win_new_printer(win_driver, name, driverNameW,
|
||||
myPrinter = printer_win_new_printer(win_driver, nameW, driverNameW,
|
||||
win_driver->id_sequence == 1 ? TRUE : FALSE);
|
||||
free(driverNameW);
|
||||
free(nameW);
|
||||
|
||||
return myPrinter;
|
||||
}
|
||||
|
||||
|
||||
static void printer_win_add_ref_driver(rdpPrinterDriver* driver)
|
||||
{
|
||||
rdpWinPrinterDriver* win = (rdpWinPrinterDriver*) driver;
|
||||
if (win)
|
||||
win->references++;
|
||||
}
|
||||
|
||||
/* Singleton */
|
||||
static rdpWinPrinterDriver* win_driver = NULL;
|
||||
|
||||
rdpPrinterDriver* printer_win_get_driver(void)
|
||||
static void printer_win_release_ref_driver(rdpPrinterDriver* driver)
|
||||
{
|
||||
rdpWinPrinterDriver* win = (rdpWinPrinterDriver*) driver;
|
||||
if (win->references <= 1)
|
||||
{
|
||||
free(win);
|
||||
win_driver = NULL;
|
||||
}
|
||||
else
|
||||
win->references--;
|
||||
}
|
||||
|
||||
#ifdef BUILTIN_CHANNELS
|
||||
rdpPrinterDriver *win_freerdp_printer_client_subsystem_entry(void)
|
||||
#else
|
||||
FREERDP_API rdpPrinterDriver *freerdp_printer_client_subsystem_entry(void)
|
||||
#endif
|
||||
{
|
||||
if (!win_driver)
|
||||
{
|
||||
win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver));
|
||||
|
||||
if (!win_driver)
|
||||
return NULL;
|
||||
|
||||
win_driver->driver.EnumPrinters = printer_win_enum_printers;
|
||||
win_driver->driver.ReleaseEnumPrinters = printer_win_release_enum_printers;
|
||||
win_driver->driver.GetPrinter = printer_win_get_printer;
|
||||
|
||||
win_driver->driver.AddRef = printer_win_add_ref_driver;
|
||||
win_driver->driver.ReleaseRef = printer_win_release_ref_driver;
|
||||
|
||||
win_driver->id_sequence = 1;
|
||||
win_driver->driver.AddRef(&win_driver->driver);
|
||||
}
|
||||
|
||||
return (rdpPrinterDriver*) win_driver;
|
||||
return &win_driver->driver;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -20,8 +20,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H
|
||||
#define FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H
|
||||
#ifndef FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H
|
||||
#define FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H
|
||||
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
|
||||
@ -29,33 +29,44 @@ 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, const char* driverName);
|
||||
typedef void (*pcReferencePrinterDriver)(rdpPrinterDriver* driver);
|
||||
typedef rdpPrinter** (*pcEnumPrinters)(rdpPrinterDriver* driver);
|
||||
typedef void (*pcReleaseEnumPrinters)(rdpPrinter** printers);
|
||||
|
||||
typedef rdpPrinter* (*pcGetPrinter)(rdpPrinterDriver* driver, const char* name,
|
||||
const char* driverName);
|
||||
typedef void (*pcReferencePrinter)(rdpPrinter* printer);
|
||||
|
||||
struct rdp_printer_driver
|
||||
{
|
||||
pcEnumPrinters EnumPrinters;
|
||||
pcReleaseEnumPrinters ReleaseEnumPrinters;
|
||||
pcGetPrinter GetPrinter;
|
||||
|
||||
pcReferencePrinterDriver AddRef;
|
||||
pcReferencePrinterDriver ReleaseRef;
|
||||
};
|
||||
|
||||
typedef rdpPrintJob* (*pcCreatePrintJob) (rdpPrinter* printer, UINT32 id);
|
||||
typedef rdpPrintJob* (*pcFindPrintJob) (rdpPrinter* printer, UINT32 id);
|
||||
typedef void (*pcFreePrinter) (rdpPrinter* printer);
|
||||
typedef rdpPrintJob* (*pcCreatePrintJob)(rdpPrinter* printer, UINT32 id);
|
||||
typedef rdpPrintJob* (*pcFindPrintJob)(rdpPrinter* printer, UINT32 id);
|
||||
|
||||
struct rdp_printer
|
||||
{
|
||||
int id;
|
||||
size_t id;
|
||||
char* name;
|
||||
char* driver;
|
||||
BOOL is_default;
|
||||
|
||||
size_t references;
|
||||
rdpPrinterDriver* backend;
|
||||
pcCreatePrintJob CreatePrintJob;
|
||||
pcFindPrintJob FindPrintJob;
|
||||
pcFreePrinter Free;
|
||||
pcReferencePrinter AddRef;
|
||||
pcReferencePrinter ReleaseRef;
|
||||
};
|
||||
|
||||
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, const BYTE* data, size_t size);
|
||||
typedef void (*pcClosePrintJob) (rdpPrintJob* printjob);
|
||||
typedef UINT (*pcWritePrintJob)(rdpPrintJob* printjob, const BYTE* data, size_t size);
|
||||
typedef void (*pcClosePrintJob)(rdpPrintJob* printjob);
|
||||
|
||||
struct rdp_print_job
|
||||
{
|
||||
@ -66,4 +77,4 @@ struct rdp_print_job
|
||||
pcClosePrintJob Close;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H */
|
||||
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H */
|
Loading…
Reference in New Issue
Block a user