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