26#include <winpr/assert.h>
27#include <freerdp/client/printer.h>
28#include <freerdp/channels/log.h>
30#define TAG CHANNELS_TAG("printer.client.android")
32#define PRINT_OUTPUT_DIR "/sdcard/Download/"
33#define PRINT_OUTPUT_PREFIX "rdp_print_"
34#define ANDROID_PRINTER_NAME "aFreeRDP Print"
35#define ANDROID_PRINTER_DRIVER "Microsoft Print to PDF"
39 rdpPrinterDriver driver;
42} rdpAndroidPrinterDriver;
54 rdpAndroidPrintJob* printjob;
57static UINT printer_android_write_printjob(rdpPrintJob* printjob,
const BYTE* data,
size_t size)
59 rdpAndroidPrintJob* aj = (rdpAndroidPrintJob*)printjob;
62 if (fwrite(data, 1, size, aj->file) != size)
63 WLog_WARN(TAG,
"Short write on print job file");
68static void printer_android_close_printjob(rdpPrintJob* printjob)
70 rdpAndroidPrintJob* aj = (rdpAndroidPrintJob*)printjob;
71 rdpAndroidPrinter* ap = (rdpAndroidPrinter*)printjob->printer;
77 WLog_INFO(TAG,
"Print job complete, saved to %s", aj->path);
80 ap->printjob =
nullptr;
84static rdpPrintJob* printer_android_create_printjob(rdpPrinter* printer, UINT32
id)
86 rdpAndroidPrinter* ap = (rdpAndroidPrinter*)printer;
90 if (ap->printjob !=
nullptr)
92 WLog_WARN(TAG,
"printjob [printer '%s'] already existing, abort!", printer->name);
96 rdpAndroidPrintJob* aj = calloc(1,
sizeof(*aj));
100 aj->printjob.id = id;
101 aj->printjob.printer = printer;
102 aj->printjob.Write = printer_android_write_printjob;
103 aj->printjob.Close = printer_android_close_printjob;
105 time_t t = time(NULL);
106 snprintf(aj->path,
sizeof(aj->path), PRINT_OUTPUT_DIR PRINT_OUTPUT_PREFIX
"%lld.pdf",
109 aj->file = fopen(aj->path,
"wb");
112 WLog_ERR(TAG,
"Failed to open dump file %s", aj->path);
118 return &aj->printjob;
121static rdpPrintJob* printer_android_find_printjob(rdpPrinter* printer, UINT32
id)
123 rdpAndroidPrinter* ap = (rdpAndroidPrinter*)printer;
127 if (ap->printjob == NULL)
129 if (ap->printjob->printjob.id !=
id)
132 return &ap->printjob->printjob;
135static void printer_android_free_printer(rdpPrinter* printer)
137 rdpAndroidPrinter* ap = (rdpAndroidPrinter*)printer;
143 WINPR_ASSERT(ap->printjob->printjob.Close);
144 ap->printjob->printjob.Close(&ap->printjob->printjob);
147 if (printer->backend)
149 WINPR_ASSERT(printer->backend->ReleaseRef);
150 printer->backend->ReleaseRef(printer->backend);
154 free(printer->driver);
158static void printer_android_add_ref_printer(rdpPrinter* printer)
161 printer->references++;
164static void printer_android_release_ref_printer(rdpPrinter* printer)
168 if (printer->references <= 1)
169 printer_android_free_printer(printer);
171 printer->references--;
174static rdpPrinter* printer_android_new_printer(rdpAndroidPrinterDriver* drv,
const char* name,
175 const char* driverName, BOOL isDefault)
177 rdpAndroidPrinter* ap = calloc(1,
sizeof(*ap));
181 ap->printer.backend = &drv->driver;
182 ap->printer.id = drv->id_sequence++;
183 ap->printer.name = _strdup(name ? name : ANDROID_PRINTER_NAME);
184 if (!ap->printer.name)
187 ap->printer.driver = _strdup(driverName ? driverName : ANDROID_PRINTER_DRIVER);
188 if (!ap->printer.driver)
191 ap->printer.is_default = isDefault;
192 ap->printer.CreatePrintJob = printer_android_create_printjob;
193 ap->printer.FindPrintJob = printer_android_find_printjob;
194 ap->printer.AddRef = printer_android_add_ref_printer;
195 ap->printer.ReleaseRef = printer_android_release_ref_printer;
197 WINPR_ASSERT(ap->printer.AddRef);
198 ap->printer.AddRef(&ap->printer);
200 WINPR_ASSERT(ap->printer.backend->AddRef);
201 ap->printer.backend->AddRef(ap->printer.backend);
206 printer_android_free_printer(&ap->printer);
210static rdpPrinter** printer_android_enum_printers(rdpPrinterDriver* driver)
212 rdpAndroidPrinterDriver* ad = (rdpAndroidPrinterDriver*)driver;
213 rdpPrinter** list = calloc(2,
sizeof(rdpPrinter*));
217 list[0] = printer_android_new_printer(ad, ANDROID_PRINTER_NAME, ANDROID_PRINTER_DRIVER, TRUE);
222static void printer_android_release_enum_printers(rdpPrinter** printers)
226 for (rdpPrinter** p = printers; *p; p++)
228 if ((*p)->ReleaseRef)
229 (*p)->ReleaseRef(*p);
234static rdpPrinter* printer_android_get_printer(rdpPrinterDriver* driver,
const char* name,
235 const char* driverName, BOOL isDefault)
237 return printer_android_new_printer((rdpAndroidPrinterDriver*)driver, name, driverName,
241static void printer_android_add_ref_driver(rdpPrinterDriver* driver)
243 rdpAndroidPrinterDriver* ad = (rdpAndroidPrinterDriver*)driver;
248static void printer_android_release_ref_driver(rdpPrinterDriver* driver)
250 rdpAndroidPrinterDriver* ad = (rdpAndroidPrinterDriver*)driver;
253 if (ad->references <= 1)
259FREERDP_ENTRY_POINT(UINT VCAPITYPE android_freerdp_printer_client_subsystem_entry(
void* arg))
261 rdpPrinterDriver** ppDriver = (rdpPrinterDriver**)arg;
264 return ERROR_INVALID_PARAMETER;
266 rdpAndroidPrinterDriver* drv = calloc(1,
sizeof(*drv));
268 return ERROR_OUTOFMEMORY;
270 drv->driver.EnumPrinters = printer_android_enum_printers;
271 drv->driver.ReleaseEnumPrinters = printer_android_release_enum_printers;
272 drv->driver.GetPrinter = printer_android_get_printer;
273 drv->driver.AddRef = printer_android_add_ref_driver;
274 drv->driver.ReleaseRef = printer_android_release_ref_driver;
275 drv->id_sequence = 1;
277 WINPR_ASSERT(drv->driver.AddRef);
278 drv->driver.AddRef(&drv->driver);
280 *ppDriver = &drv->driver;
281 return CHANNEL_RC_OK;