mirror of https://github.com/FreeRDP/FreeRDP
Merge pull request #5569 from akallabeth/dynamic_printer_backend
Dynamic printer backend
This commit is contained in:
commit
79d19b5f71
|
@ -348,29 +348,28 @@ BOOL freerdp_channels_is_virtual_channel_entry_ex(LPCSTR pszName)
|
||||||
PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
|
PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem,
|
||||||
LPCSTR pszType, DWORD dwFlags)
|
LPCSTR pszType, DWORD dwFlags)
|
||||||
{
|
{
|
||||||
int i, j;
|
const STATIC_ADDIN_TABLE* table = CLIENT_STATIC_ADDIN_TABLE;
|
||||||
STATIC_SUBSYSTEM_ENTRY* subsystems;
|
for (; table->name != NULL; table++)
|
||||||
|
|
||||||
for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
|
|
||||||
{
|
{
|
||||||
if (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0)
|
if (strcmp(table->name, pszName) == 0)
|
||||||
{
|
{
|
||||||
if (pszSubsystem != NULL)
|
if (pszSubsystem != NULL)
|
||||||
{
|
{
|
||||||
subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table;
|
const STATIC_SUBSYSTEM_ENTRY* subsystems = (const STATIC_SUBSYSTEM_ENTRY*) table->table;
|
||||||
|
|
||||||
for (j = 0; subsystems[j].name != NULL; j++)
|
for (; subsystems->name != NULL; subsystems++)
|
||||||
{
|
{
|
||||||
if (strcmp(subsystems[j].name, pszSubsystem) == 0)
|
/* If the pszSubsystem is an empty string use the default backend. */
|
||||||
|
if ((strlen(pszSubsystem) == 0) || (strcmp(subsystems->name, pszSubsystem) == 0))
|
||||||
{
|
{
|
||||||
if (pszType)
|
if (pszType)
|
||||||
{
|
{
|
||||||
if (strcmp(subsystems[j].type, pszType) == 0)
|
if (strcmp(subsystems->type, pszType) == 0)
|
||||||
return (PVIRTUALCHANNELENTRY) subsystems[j].entry;
|
return (PVIRTUALCHANNELENTRY) subsystems->entry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (PVIRTUALCHANNELENTRY) subsystems[j].entry;
|
return (PVIRTUALCHANNELENTRY) subsystems->entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,7 +382,7 @@ PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LP
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PVIRTUALCHANNELENTRY) CLIENT_STATIC_ADDIN_TABLE[i].entry;
|
return (PVIRTUALCHANNELENTRY) table->entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,39 +18,23 @@
|
||||||
define_channel_client("printer")
|
define_channel_client("printer")
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_SRCS
|
set(${MODULE_PREFIX}_SRCS
|
||||||
printer_main.c
|
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()
|
|
||||||
|
|
||||||
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
|
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
|
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})
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
|
||||||
if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_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)
|
install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")
|
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()
|
||||||
|
|
|
@ -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 <freerdp/channels/rdpdr.h>
|
||||||
|
|
||||||
#include "printer_main.h"
|
#include <freerdp/client/printer.h>
|
||||||
|
|
||||||
#include "printer_cups.h"
|
|
||||||
|
|
||||||
typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver;
|
typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver;
|
||||||
typedef struct rdp_cups_printer rdpCupsPrinter;
|
typedef struct rdp_cups_printer rdpCupsPrinter;
|
||||||
|
@ -50,6 +48,7 @@ struct rdp_cups_printer_driver
|
||||||
rdpPrinterDriver driver;
|
rdpPrinterDriver driver;
|
||||||
|
|
||||||
int id_sequence;
|
int id_sequence;
|
||||||
|
size_t references;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rdp_cups_printer
|
struct rdp_cups_printer
|
||||||
|
@ -67,16 +66,16 @@ struct rdp_cups_print_job
|
||||||
int printjob_id;
|
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;
|
time_t tt;
|
||||||
struct tm* t;
|
struct tm* t;
|
||||||
|
|
||||||
tt = time(NULL);
|
tt = time(NULL);
|
||||||
t = localtime(&tt);
|
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_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];
|
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)
|
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;
|
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,
|
cups_printjob->printjob_id = cupsCreateJob((http_t*) cups_printjob->printjob_object,
|
||||||
printer->name, buf, 0, NULL);
|
printer->name, buf, 0, NULL);
|
||||||
|
@ -230,11 +229,29 @@ static void printer_cups_free_printer(rdpPrinter* printer)
|
||||||
if (cups_printer->printjob)
|
if (cups_printer->printjob)
|
||||||
cups_printer->printjob->printjob.Close((rdpPrintJob*) 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->name);
|
||||||
free(printer->driver);
|
free(printer->driver);
|
||||||
free(printer);
|
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,
|
static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
|
||||||
const char* name, const char* driverName, BOOL is_default)
|
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)
|
if (!cups_printer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
cups_printer->printer.backend = &cups_driver->driver;
|
||||||
|
|
||||||
cups_printer->printer.id = cups_driver->id_sequence++;
|
cups_printer->printer.id = cups_driver->id_sequence++;
|
||||||
cups_printer->printer.name = _strdup(name);
|
cups_printer->printer.name = _strdup(name);
|
||||||
if (!cups_printer->printer.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.CreatePrintJob = printer_cups_create_printjob;
|
||||||
cups_printer->printer.FindPrintJob = printer_cups_find_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)
|
static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||||
|
@ -291,8 +327,17 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
|
||||||
{
|
{
|
||||||
if (dest->instance == NULL)
|
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);
|
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);
|
cupsFreeDests(num_dests, dests);
|
||||||
|
@ -309,11 +354,35 @@ static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver,
|
||||||
cups_driver->id_sequence == 1 ? TRUE : FALSE);
|
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;
|
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));
|
cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver));
|
||||||
|
|
||||||
|
@ -321,11 +390,15 @@ rdpPrinterDriver* printer_cups_get_driver(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
|
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.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->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"
|
#include "../printer.h"
|
||||||
|
|
||||||
#ifdef WITH_CUPS
|
#include <freerdp/client/printer.h>
|
||||||
#include "printer_cups.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "printer_main.h"
|
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_UWP)
|
|
||||||
#include "printer_win.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <freerdp/channels/log.h>
|
#include <freerdp/channels/log.h>
|
||||||
|
|
||||||
|
@ -863,7 +855,7 @@ static UINT printer_free(DEVICE* device)
|
||||||
_aligned_free(printer_dev->pIrpList);
|
_aligned_free(printer_dev->pIrpList);
|
||||||
|
|
||||||
if (printer_dev->printer)
|
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);
|
Stream_Free(printer_dev->device.data, TRUE);
|
||||||
free(printer_dev);
|
free(printer_dev);
|
||||||
|
@ -875,7 +867,7 @@ static UINT printer_free(DEVICE* device)
|
||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @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)
|
rdpPrinter* printer)
|
||||||
{
|
{
|
||||||
PRINTER_DEVICE* printer_dev;
|
PRINTER_DEVICE* printer_dev;
|
||||||
|
@ -945,39 +937,69 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printer->AddRef(printer);
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
error_out:
|
error_out:
|
||||||
printer_free(&printer_dev->device);
|
printer_free(&printer_dev->device);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BUILTIN_CHANNELS
|
static rdpPrinterDriver* printer_load_backend(const char* backend)
|
||||||
#define DeviceServiceEntry printer_DeviceServiceEntry
|
{
|
||||||
#else
|
typedef rdpPrinterDriver* (*backend_load_t)(void);
|
||||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
|
||||||
#endif
|
backend_load_t entry = (backend_load_t)freerdp_load_channel_addin_entry("printer", backend, NULL, 0);
|
||||||
|
if (!entry)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return entry();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function description
|
* Function description
|
||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @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;
|
int i;
|
||||||
char* name;
|
char* name;
|
||||||
char* driver_name;
|
char* driver_name;
|
||||||
rdpPrinter* printer;
|
RDPDR_PRINTER* device = NULL;
|
||||||
rdpPrinter** printers;
|
|
||||||
RDPDR_PRINTER* device;
|
|
||||||
rdpPrinterDriver* driver = NULL;
|
rdpPrinterDriver* driver = NULL;
|
||||||
UINT error;
|
UINT error = CHANNEL_RC_OK;
|
||||||
#ifdef WITH_CUPS
|
size_t pos;
|
||||||
driver = printer_cups_get_driver();
|
|
||||||
#endif
|
if (!pEntryPoints || !pEntryPoints->device)
|
||||||
#if defined(_WIN32) && !defined(_UWP)
|
return ERROR_INVALID_PARAMETER;
|
||||||
driver = printer_win_get_driver();
|
|
||||||
#endif
|
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)
|
if (!driver)
|
||||||
{
|
{
|
||||||
|
@ -985,47 +1007,52 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
device = (RDPDR_PRINTER*) pEntryPoints->device;
|
|
||||||
name = device->Name;
|
|
||||||
driver_name = device->DriverName;
|
|
||||||
|
|
||||||
if (name && name[0])
|
if (name && name[0])
|
||||||
{
|
{
|
||||||
printer = driver->GetPrinter(driver, name, driver_name);
|
rdpPrinter* printer = driver->GetPrinter(driver, name, driver_name);
|
||||||
|
|
||||||
if (!printer)
|
if (!printer)
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "Could not get printer %s!", name);
|
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))
|
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)))
|
if ((error = printer_register(pEntryPoints, printer)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
||||||
return error;
|
printer->ReleaseRef(printer);
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)))
|
if ((error = printer_register(pEntryPoints, printer)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);
|
||||||
free(printers);
|
break;
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
|
@ -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 <string.h>
|
||||||
#include <winspool.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_driver rdpWinPrinterDriver;
|
||||||
typedef struct rdp_win_printer rdpWinPrinter;
|
typedef struct rdp_win_printer rdpWinPrinter;
|
||||||
|
@ -46,7 +51,8 @@ struct rdp_win_printer_driver
|
||||||
{
|
{
|
||||||
rdpPrinterDriver driver;
|
rdpPrinterDriver driver;
|
||||||
|
|
||||||
int id_sequence;
|
size_t id_sequence;
|
||||||
|
size_t references;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rdp_win_printer
|
struct rdp_win_printer
|
||||||
|
@ -66,16 +72,26 @@ struct rdp_win_print_job
|
||||||
int printjob_id;
|
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;
|
time_t tt;
|
||||||
struct tm* t;
|
struct tm* t;
|
||||||
|
WCHAR* str;
|
||||||
|
size_t len = 1024;
|
||||||
|
int rc;
|
||||||
|
|
||||||
tt = time(NULL);
|
tt = time(NULL);
|
||||||
t = localtime(&tt);
|
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_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
|
* @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;
|
rdpWinPrinter* printer;
|
||||||
|
LPCVOID pBuf = data;
|
||||||
LPVOID pBuf = data;
|
|
||||||
DWORD cbBuf = size;
|
DWORD cbBuf = size;
|
||||||
DWORD pcWritten;
|
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 ERROR_INTERNAL_ERROR;
|
||||||
return CHANNEL_RC_OK;
|
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)
|
static void printer_win_close_printjob(rdpPrintJob* printjob)
|
||||||
{
|
{
|
||||||
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) 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);
|
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.id = id;
|
||||||
win_printjob->printjob.printer = printer;
|
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.pDatatype= NULL;
|
||||||
win_printjob->di.pOutputFile = NULL;
|
win_printjob->di.pOutputFile = NULL;
|
||||||
|
|
||||||
|
@ -137,12 +168,14 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||||
|
|
||||||
if (!win_printjob->handle)
|
if (!win_printjob->handle)
|
||||||
{
|
{
|
||||||
|
free(win_printjob->di.pDocName);
|
||||||
free(win_printjob);
|
free(win_printjob);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StartPagePrinter(win_printer->hPrinter))
|
if (!StartPagePrinter(win_printer->hPrinter))
|
||||||
{
|
{
|
||||||
|
free(win_printjob->di.pDocName);
|
||||||
free(win_printjob);
|
free(win_printjob);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -152,7 +185,7 @@ static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id)
|
||||||
|
|
||||||
win_printer->printjob = win_printjob;
|
win_printer->printjob = win_printjob;
|
||||||
|
|
||||||
return (rdpPrintJob*) win_printjob;
|
return &win_printjob->printjob;
|
||||||
}
|
}
|
||||||
|
|
||||||
static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id)
|
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)
|
if (win_printer->printjob)
|
||||||
win_printer->printjob->printjob.Close((rdpPrintJob*) 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->name);
|
||||||
free(printer->driver);
|
free(printer->driver);
|
||||||
free(printer);
|
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,
|
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||||
const WCHAR* name, const WCHAR* drivername, BOOL is_default)
|
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)
|
if (!win_printer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
win_printer->printer.backend = &win_driver->driver;
|
||||||
win_printer->printer.id = win_driver->id_sequence++;
|
win_printer->printer.id = win_driver->id_sequence++;
|
||||||
if (ConvertFromUnicode(CP_UTF8, 0, name, -1, &win_printer->printer.name, 0, NULL, NULL) < 1)
|
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.CreatePrintJob = printer_win_create_printjob;
|
||||||
win_printer->printer.FindPrintJob = printer_win_find_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))
|
if (!OpenPrinter(name, &(win_printer->hPrinter), NULL))
|
||||||
{
|
{
|
||||||
|
@ -254,7 +308,22 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
|
||||||
return NULL;
|
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)
|
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++)
|
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);
|
prninfo[i].pPrinterName, prninfo[i].pDriverName, 0);
|
||||||
|
if (!current)
|
||||||
|
{
|
||||||
|
printer_win_release_enum_printers(printers);
|
||||||
|
printers = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printers[num_printers++] = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalFree(prninfo);
|
GlobalFree(prninfo);
|
||||||
|
@ -303,9 +380,16 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
|
||||||
const char* name, const char* driverName)
|
const char* name, const char* driverName)
|
||||||
{
|
{
|
||||||
WCHAR* driverNameW = NULL;
|
WCHAR* driverNameW = NULL;
|
||||||
|
WCHAR* nameW = NULL;
|
||||||
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
|
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
|
||||||
rdpPrinter *myPrinter = NULL;
|
rdpPrinter *myPrinter = NULL;
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
ConvertToUnicode(CP_UTF8, 0, name, -1, &nameW, 0);
|
||||||
|
if (!driverNameW)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (driverName)
|
if (driverName)
|
||||||
{
|
{
|
||||||
ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0);
|
ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0);
|
||||||
|
@ -313,29 +397,64 @@ static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
|
||||||
return NULL;
|
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);
|
win_driver->id_sequence == 1 ? TRUE : FALSE);
|
||||||
free(driverNameW);
|
free(driverNameW);
|
||||||
|
free(nameW);
|
||||||
|
|
||||||
return myPrinter;
|
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;
|
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)
|
if (!win_driver)
|
||||||
{
|
{
|
||||||
win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver));
|
win_driver = (rdpWinPrinterDriver*) calloc(1, sizeof(rdpWinPrinterDriver));
|
||||||
|
|
||||||
if (!win_driver)
|
if (!win_driver)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
win_driver->driver.EnumPrinters = printer_win_enum_printers;
|
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.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->id_sequence = 1;
|
||||||
|
win_driver->driver.AddRef(&win_driver->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (rdpPrinterDriver*) win_driver;
|
return &win_driver->driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -167,11 +167,11 @@ DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char DRIVE_SERVICE_NAME[] = "drive";
|
static const char DRIVE_SERVICE_NAME[] = "drive";
|
||||||
static char PRINTER_SERVICE_NAME[] = "printer";
|
static const char PRINTER_SERVICE_NAME[] = "printer";
|
||||||
static char SMARTCARD_SERVICE_NAME[] = "smartcard";
|
static const char SMARTCARD_SERVICE_NAME[] = "smartcard";
|
||||||
static char SERIAL_SERVICE_NAME[] = "serial";
|
static const char SERIAL_SERVICE_NAME[] = "serial";
|
||||||
static char PARALLEL_SERVICE_NAME[] = "parallel";
|
static const char PARALLEL_SERVICE_NAME[] = "parallel";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function description
|
* Function description
|
||||||
|
@ -180,7 +180,7 @@ static char PARALLEL_SERVICE_NAME[] = "parallel";
|
||||||
*/
|
*/
|
||||||
UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext)
|
UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext)
|
||||||
{
|
{
|
||||||
char* ServiceName = NULL;
|
const char* ServiceName = NULL;
|
||||||
DEVICE_SERVICE_ENTRY_POINTS ep;
|
DEVICE_SERVICE_ENTRY_POINTS ep;
|
||||||
PDEVICE_SERVICE_ENTRY entry = NULL;
|
PDEVICE_SERVICE_ENTRY entry = NULL;
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H
|
#ifndef FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H
|
||||||
#define FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H
|
#define FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H
|
||||||
|
|
||||||
#include <freerdp/channels/rdpdr.h>
|
#include <freerdp/channels/rdpdr.h>
|
||||||
|
|
||||||
|
@ -29,33 +29,44 @@ typedef struct rdp_printer_driver rdpPrinterDriver;
|
||||||
typedef struct rdp_printer rdpPrinter;
|
typedef struct rdp_printer rdpPrinter;
|
||||||
typedef struct rdp_print_job rdpPrintJob;
|
typedef struct rdp_print_job rdpPrintJob;
|
||||||
|
|
||||||
typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver);
|
typedef void (*pcReferencePrinterDriver)(rdpPrinterDriver* driver);
|
||||||
typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name, const char* driverName);
|
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
|
struct rdp_printer_driver
|
||||||
{
|
{
|
||||||
pcEnumPrinters EnumPrinters;
|
pcEnumPrinters EnumPrinters;
|
||||||
|
pcReleaseEnumPrinters ReleaseEnumPrinters;
|
||||||
pcGetPrinter GetPrinter;
|
pcGetPrinter GetPrinter;
|
||||||
|
|
||||||
|
pcReferencePrinterDriver AddRef;
|
||||||
|
pcReferencePrinterDriver ReleaseRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef rdpPrintJob* (*pcCreatePrintJob) (rdpPrinter* printer, UINT32 id);
|
typedef rdpPrintJob* (*pcCreatePrintJob)(rdpPrinter* printer, UINT32 id);
|
||||||
typedef rdpPrintJob* (*pcFindPrintJob) (rdpPrinter* printer, UINT32 id);
|
typedef rdpPrintJob* (*pcFindPrintJob)(rdpPrinter* printer, UINT32 id);
|
||||||
typedef void (*pcFreePrinter) (rdpPrinter* printer);
|
|
||||||
|
|
||||||
struct rdp_printer
|
struct rdp_printer
|
||||||
{
|
{
|
||||||
int id;
|
size_t id;
|
||||||
char* name;
|
char* name;
|
||||||
char* driver;
|
char* driver;
|
||||||
BOOL is_default;
|
BOOL is_default;
|
||||||
|
|
||||||
|
size_t references;
|
||||||
|
rdpPrinterDriver* backend;
|
||||||
pcCreatePrintJob CreatePrintJob;
|
pcCreatePrintJob CreatePrintJob;
|
||||||
pcFindPrintJob FindPrintJob;
|
pcFindPrintJob FindPrintJob;
|
||||||
pcFreePrinter Free;
|
pcReferencePrinter AddRef;
|
||||||
|
pcReferencePrinter ReleaseRef;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, const BYTE* data, size_t size);
|
typedef UINT (*pcWritePrintJob)(rdpPrintJob* printjob, const BYTE* data, size_t size);
|
||||||
typedef void (*pcClosePrintJob) (rdpPrintJob* printjob);
|
typedef void (*pcClosePrintJob)(rdpPrintJob* printjob);
|
||||||
|
|
||||||
struct rdp_print_job
|
struct rdp_print_job
|
||||||
{
|
{
|
||||||
|
@ -66,4 +77,4 @@ struct rdp_print_job
|
||||||
pcClosePrintJob Close;
|
pcClosePrintJob Close;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_MAIN_H */
|
#endif /* FREERDP_CHANNEL_PRINTER_CLIENT_PRINTER_H */
|
|
@ -65,29 +65,43 @@ struct rdp_nego
|
||||||
rdpTransport* transport;
|
rdpTransport* transport;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* const NEGO_STATE_STRINGS[] =
|
static const char* nego_state_string(NEGO_STATE state)
|
||||||
{
|
{
|
||||||
"NEGO_STATE_INITIAL",
|
static const char* const NEGO_STATE_STRINGS[] =
|
||||||
"NEGO_STATE_EXT",
|
{
|
||||||
"NEGO_STATE_NLA",
|
"NEGO_STATE_INITIAL",
|
||||||
"NEGO_STATE_TLS",
|
"NEGO_STATE_EXT",
|
||||||
"NEGO_STATE_RDP",
|
"NEGO_STATE_NLA",
|
||||||
"NEGO_STATE_FAIL",
|
"NEGO_STATE_TLS",
|
||||||
"NEGO_STATE_FINAL"
|
"NEGO_STATE_RDP",
|
||||||
};
|
"NEGO_STATE_FAIL",
|
||||||
|
"NEGO_STATE_FINAL",
|
||||||
|
"NEGO_STATE_INVALID"
|
||||||
|
};
|
||||||
|
if (state >= ARRAYSIZE(NEGO_STATE_STRINGS))
|
||||||
|
return NEGO_STATE_STRINGS[ARRAYSIZE(NEGO_STATE_STRINGS) - 1];
|
||||||
|
return NEGO_STATE_STRINGS[state];
|
||||||
|
}
|
||||||
|
|
||||||
static const char PROTOCOL_SECURITY_STRINGS[9][4] =
|
static const char* protocol_security_string(UINT32 security)
|
||||||
{
|
{
|
||||||
"RDP",
|
static const char* PROTOCOL_SECURITY_STRINGS[] =
|
||||||
"TLS",
|
{
|
||||||
"NLA",
|
"RDP",
|
||||||
"UNK",
|
"TLS",
|
||||||
"UNK",
|
"NLA",
|
||||||
"UNK",
|
"UNK",
|
||||||
"UNK",
|
"UNK",
|
||||||
"UNK",
|
"UNK",
|
||||||
"EXT"
|
"UNK",
|
||||||
};
|
"UNK",
|
||||||
|
"EXT",
|
||||||
|
"UNK"
|
||||||
|
};
|
||||||
|
if (security >= ARRAYSIZE(PROTOCOL_SECURITY_STRINGS))
|
||||||
|
return PROTOCOL_SECURITY_STRINGS[ARRAYSIZE(PROTOCOL_SECURITY_STRINGS) - 1];
|
||||||
|
return PROTOCOL_SECURITY_STRINGS[security];
|
||||||
|
}
|
||||||
|
|
||||||
static BOOL nego_transport_connect(rdpNego* nego);
|
static BOOL nego_transport_connect(rdpNego* nego);
|
||||||
static BOOL nego_transport_disconnect(rdpNego* nego);
|
static BOOL nego_transport_disconnect(rdpNego* nego);
|
||||||
|
@ -185,7 +199,7 @@ BOOL nego_connect(rdpNego* nego)
|
||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
WLog_DBG(TAG, "state: %s", NEGO_STATE_STRINGS[nego->state]);
|
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
|
||||||
nego_send(nego);
|
nego_send(nego);
|
||||||
|
|
||||||
if (nego->state == NEGO_STATE_FAIL)
|
if (nego->state == NEGO_STATE_FAIL)
|
||||||
|
@ -200,7 +214,7 @@ BOOL nego_connect(rdpNego* nego)
|
||||||
while (nego->state != NEGO_STATE_FINAL);
|
while (nego->state != NEGO_STATE_FINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_DBG(TAG, "Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->SelectedProtocol]);
|
WLog_DBG(TAG, "Negotiated %s security", protocol_security_string(nego->SelectedProtocol));
|
||||||
/* update settings with negotiated protocol security */
|
/* update settings with negotiated protocol security */
|
||||||
settings->RequestedProtocols = nego->RequestedProtocols;
|
settings->RequestedProtocols = nego->RequestedProtocols;
|
||||||
settings->SelectedProtocol = nego->SelectedProtocol;
|
settings->SelectedProtocol = nego->SelectedProtocol;
|
||||||
|
@ -225,7 +239,7 @@ BOOL nego_connect(rdpNego* nego)
|
||||||
if (!nego_security_connect(nego))
|
if (!nego_security_connect(nego))
|
||||||
{
|
{
|
||||||
WLog_DBG(TAG, "Failed to connect with %s security",
|
WLog_DBG(TAG, "Failed to connect with %s security",
|
||||||
PROTOCOL_SECURITY_STRINGS[nego->SelectedProtocol]);
|
protocol_security_string(nego->SelectedProtocol));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +442,7 @@ static void nego_attempt_ext(rdpNego* nego)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_DBG(TAG, "state: %s", NEGO_STATE_STRINGS[nego->state]);
|
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
|
||||||
|
|
||||||
if (nego->state != NEGO_STATE_FINAL)
|
if (nego->state != NEGO_STATE_FINAL)
|
||||||
{
|
{
|
||||||
|
@ -473,7 +487,7 @@ static void nego_attempt_nla(rdpNego* nego)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WLog_DBG(TAG, "state: %s", NEGO_STATE_STRINGS[nego->state]);
|
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
|
||||||
|
|
||||||
if (nego->state != NEGO_STATE_FINAL)
|
if (nego->state != NEGO_STATE_FINAL)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue