Merge pull request #5569 from akallabeth/dynamic_printer_backend

Dynamic printer backend
This commit is contained in:
Martin Fleisz 2019-09-06 10:08:40 +02:00 committed by GitHub
commit 79d19b5f71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 447 additions and 222 deletions

View File

@ -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,
LPCSTR pszType, DWORD dwFlags)
{
int i, j;
STATIC_SUBSYSTEM_ENTRY* subsystems;
for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
const STATIC_ADDIN_TABLE* table = CLIENT_STATIC_ADDIN_TABLE;
for (; table->name != NULL; table++)
{
if (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0)
if (strcmp(table->name, pszName) == 0)
{
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 (strcmp(subsystems[j].type, pszType) == 0)
return (PVIRTUALCHANNELENTRY) subsystems[j].entry;
if (strcmp(subsystems->type, pszType) == 0)
return (PVIRTUALCHANNELENTRY) subsystems->entry;
}
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 (PVIRTUALCHANNELENTRY) CLIENT_STATIC_ADDIN_TABLE[i].entry;
return (PVIRTUALCHANNELENTRY) table->entry;
}
}
}

View File

@ -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()

View 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})

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View 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})

View File

@ -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;
}

View File

@ -167,11 +167,11 @@ DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
return device;
}
static char DRIVE_SERVICE_NAME[] = "drive";
static char PRINTER_SERVICE_NAME[] = "printer";
static char SMARTCARD_SERVICE_NAME[] = "smartcard";
static char SERIAL_SERVICE_NAME[] = "serial";
static char PARALLEL_SERVICE_NAME[] = "parallel";
static const char DRIVE_SERVICE_NAME[] = "drive";
static const char PRINTER_SERVICE_NAME[] = "printer";
static const char SMARTCARD_SERVICE_NAME[] = "smartcard";
static const char SERIAL_SERVICE_NAME[] = "serial";
static const char PARALLEL_SERVICE_NAME[] = "parallel";
/**
* Function description
@ -180,7 +180,7 @@ static char PARALLEL_SERVICE_NAME[] = "parallel";
*/
UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext)
{
char* ServiceName = NULL;
const char* ServiceName = NULL;
DEVICE_SERVICE_ENTRY_POINTS ep;
PDEVICE_SERVICE_ENTRY entry = NULL;

View File

@ -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 */

View File

@ -65,29 +65,43 @@ struct rdp_nego
rdpTransport* transport;
};
static const char* const NEGO_STATE_STRINGS[] =
static const char* nego_state_string(NEGO_STATE state)
{
"NEGO_STATE_INITIAL",
"NEGO_STATE_EXT",
"NEGO_STATE_NLA",
"NEGO_STATE_TLS",
"NEGO_STATE_RDP",
"NEGO_STATE_FAIL",
"NEGO_STATE_FINAL"
};
static const char* const NEGO_STATE_STRINGS[] =
{
"NEGO_STATE_INITIAL",
"NEGO_STATE_EXT",
"NEGO_STATE_NLA",
"NEGO_STATE_TLS",
"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",
"TLS",
"NLA",
"UNK",
"UNK",
"UNK",
"UNK",
"UNK",
"EXT"
};
static const char* PROTOCOL_SECURITY_STRINGS[] =
{
"RDP",
"TLS",
"NLA",
"UNK",
"UNK",
"UNK",
"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_disconnect(rdpNego* nego);
@ -185,7 +199,7 @@ BOOL nego_connect(rdpNego* nego)
{
do
{
WLog_DBG(TAG, "state: %s", NEGO_STATE_STRINGS[nego->state]);
WLog_DBG(TAG, "state: %s", nego_state_string(nego->state));
nego_send(nego);
if (nego->state == NEGO_STATE_FAIL)
@ -200,7 +214,7 @@ BOOL nego_connect(rdpNego* nego)
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 */
settings->RequestedProtocols = nego->RequestedProtocols;
settings->SelectedProtocol = nego->SelectedProtocol;
@ -225,7 +239,7 @@ BOOL nego_connect(rdpNego* nego)
if (!nego_security_connect(nego))
{
WLog_DBG(TAG, "Failed to connect with %s security",
PROTOCOL_SECURITY_STRINGS[nego->SelectedProtocol]);
protocol_security_string(nego->SelectedProtocol));
return FALSE;
}
@ -428,7 +442,7 @@ static void nego_attempt_ext(rdpNego* nego)
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)
{
@ -473,7 +487,7 @@ static void nego_attempt_nla(rdpNego* nego)
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)
{