Merge pull request #5140 from akallabeth/print_custom_component

Added callback to handle printer custom components in printer backend.
This commit is contained in:
David Fort
2019-01-29 15:18:53 +01:00
committed by GitHub
8 changed files with 701 additions and 167 deletions

View File

@@ -938,6 +938,7 @@ endif()
if(OPENSSL_FOUND)
add_definitions("-DWITH_OPENSSL")
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
if(MBEDTLS_FOUND)

View File

@@ -84,7 +84,7 @@ static void printer_cups_get_printjob_name(char* buf, int size)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size)
{
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;

View File

@@ -35,8 +35,10 @@
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/interlocked.h>
#include <winpr/path.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/crypto/crypto.h>
#include "../printer.h"
@@ -71,6 +73,364 @@ struct _PRINTER_DEVICE
char port[64];
};
typedef enum
{
PRN_CONF_PORT = 0,
PRN_CONF_PNP = 1,
PRN_CONF_DRIVER = 2,
PRN_CONF_DATA = 3
}
prn_conf_t;
static const char* filemap[] =
{
"PortDosName",
"PnPName",
"DriverName",
"CachedPrinterConfigData"
};
static char* get_printer_config_path(const rdpSettings* settings, const WCHAR* name, size_t length)
{
char* dir = GetCombinedPath(settings->ConfigPath, "printers");
char* bname = crypto_base64_encode((const BYTE*) name, (int)length);
char* config = GetCombinedPath(dir, bname);
if (config && !PathFileExistsA(config))
{
if (!PathMakePathA(config, NULL))
{
free(config);
config = NULL;
}
}
free(dir);
free(bname);
return config;
}
static BOOL printer_write_setting(const char* path, prn_conf_t type, const void* data,
size_t length)
{
DWORD written = 0;
BOOL rc = FALSE;
HANDLE file;
size_t b64len;
char* base64 = NULL;
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
if (!abs)
return FALSE;
file = CreateFileA(abs, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
if (length > 0)
{
base64 = crypto_base64_encode(data, length);
if (!base64)
goto fail;
b64len = strlen(base64);
rc = WriteFile(file, base64, b64len, &written, NULL);
if (b64len != written)
rc = FALSE;
}
else
rc = TRUE;
fail:
CloseHandle(file);
free(base64);
return rc;
}
static BOOL printer_config_valid(const char* path)
{
if (!path)
return FALSE;
if (!PathFileExistsA(path))
return FALSE;
return TRUE;
}
static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, size_t* length)
{
DWORD lowSize, highSize;
DWORD read = 0;
BOOL rc = FALSE;
HANDLE file;
BYTE* fdata = NULL;
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
if (!abs)
return FALSE;
file = CreateFileA(abs, GENERIC_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
lowSize = GetFileSize(file, &highSize);
if ((lowSize == INVALID_FILE_SIZE) || (highSize != 0))
goto fail;
if (lowSize != 0)
{
fdata = malloc(lowSize);
if (!fdata)
goto fail;
rc = ReadFile(file, fdata, lowSize, &read, NULL);
if (lowSize != read)
rc = FALSE;
}
fail:
CloseHandle(file);
if (rc)
{
int blen = 0;
crypto_base64_decode(fdata, lowSize, data, &blen);
if (*data)
*length = blen;
else
{
rc = FALSE;
*length = 0;
}
}
else
{
*length = 0;
*data = NULL;
}
free(fdata);
return rc;
}
static BOOL printer_save_to_config(const rdpSettings* settings,
const char* PortDosName, size_t PortDosNameLen,
const WCHAR* PnPName, size_t PnPNameLen,
const WCHAR* DriverName, size_t DriverNameLen,
const WCHAR* PrinterName, size_t PrintNameLen,
const BYTE* CachedPrinterConfigData, size_t CacheFieldsLen)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, PrinterName, PrintNameLen);
if (!path)
goto fail;
if (!printer_write_setting(path, PRN_CONF_PORT, PortDosName, PortDosNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_PNP, PnPName, PnPNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_DRIVER, DriverName, DriverNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_DATA, CachedPrinterConfigData, CacheFieldsLen))
goto fail;
fail:
free(path);
return rc;
}
static BOOL printer_update_to_config(const rdpSettings* settings, const WCHAR* name, size_t length,
const BYTE* data, size_t datalen)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, name, length);
rc = printer_write_setting(path, PRN_CONF_DATA, data, datalen);
free(path);
return rc;
}
static BOOL printer_remove_config(const rdpSettings* settings, const WCHAR* name, size_t length)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, name, length);
if (!printer_config_valid(path))
goto fail;
rc = RemoveDirectoryA(path);
fail:
free(path);
return rc;
}
static BOOL printer_move_config(const rdpSettings* settings, const WCHAR* oldName, size_t oldLength,
const WCHAR* newName, size_t newLength)
{
BOOL rc = FALSE;
char* oldPath = get_printer_config_path(settings, oldName, oldLength);
char* newPath = get_printer_config_path(settings, newName, newLength);
if (printer_config_valid(oldPath))
rc = MoveFileA(oldPath, newPath);
free(oldPath);
free(newPath);
return rc;
}
static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* printer,
PRINTER_DEVICE* printer_dev)
{
BOOL res = FALSE;
WCHAR* wname = NULL;
size_t wlen;
char* path = NULL;
int rc;
UINT32 flags = 0;
WCHAR* DriverName = NULL;
size_t DriverNameLen = 0;
WCHAR* PnPName = NULL;
size_t PnPNameLen = 0;
BYTE* CachedPrinterConfigData = NULL;
size_t CachedFieldsLen = 0;
size_t PrinterNameLen = 0;
if (!settings || !printer)
return FALSE;
rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0);
if (rc <= 0)
goto fail;
wlen = _wcslen(wname) + 1;
path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR));
PrinterNameLen = (wlen + 1) * sizeof(WCHAR);
if (!path)
goto fail;
if (printer->is_default)
flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
if (!printer_read_setting(path, PRN_CONF_PNP, &PnPName, &PnPNameLen))
{
}
if (!printer_read_setting(path, PRN_CONF_DRIVER, &DriverName, &DriverNameLen))
{
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
0) * 2 + 1;
}
if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen))
{
}
Stream_SetPosition(printer_dev->device.data, 0);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, 24))
goto fail;
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, PnPNameLen); /* PnPNameLen */
Stream_Write_UINT32(printer_dev->device.data, DriverNameLen);
Stream_Write_UINT32(printer_dev->device.data, PrinterNameLen);
Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PnPNameLen))
goto fail;
if (PnPNameLen > 0)
Stream_Write(printer_dev->device.data, PnPName, PnPNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, DriverNameLen))
goto fail;
Stream_Write(printer_dev->device.data, DriverName, DriverNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PrinterNameLen))
goto fail;
Stream_Write(printer_dev->device.data, wname, PrinterNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, CachedFieldsLen))
goto fail;
Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen);
res = TRUE;
fail:
free(path);
free(wname);
free(PnPName);
free(DriverName);
free(CachedPrinterConfigData);
return res;
}
static BOOL printer_save_default_config(const rdpSettings* settings, rdpPrinter* printer)
{
BOOL res = FALSE;
WCHAR* wname = NULL;
WCHAR* driver = NULL;
size_t wlen, dlen;
char* path = NULL;
int rc;
if (!settings || !printer)
return FALSE;
rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0);
if (rc <= 0)
goto fail;
rc = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &driver, 0);
if (rc <= 0)
goto fail;
wlen = _wcslen(wname) + 1;
dlen = _wcslen(driver) + 1;
path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR));
if (!path)
goto fail;
if (dlen > 1)
{
if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR)))
goto fail;
}
res = TRUE;
fail:
free(path);
free(wname);
free(driver);
return res;
}
/**
* Function description
*
@@ -293,6 +653,182 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
return CHANNEL_RC_OK;
}
static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s)
{
UINT32 eventID;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;
const rdpSettings* settings = printer_dev->rdpcontext->settings;
if (component != RDPDR_CTYP_PRN)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, eventID);
switch (packetId)
{
case PAKID_PRN_CACHE_DATA:
switch (eventID)
{
case RDPDR_ADD_PRINTER_EVENT:
{
char PortDosName[8];
UINT32 PnPNameLen, DriverNameLen, PrintNameLen, CacheFieldsLen;
const WCHAR* PnPName, *DriverName, *PrinterName;
const BYTE* CachedPrinterConfigData;
if (Stream_GetRemainingLength(s) < 24)
return ERROR_INVALID_DATA;
Stream_Read(s, PortDosName, sizeof(PortDosName));
Stream_Read_UINT32(s, PnPNameLen);
Stream_Read_UINT32(s, DriverNameLen);
Stream_Read_UINT32(s, PrintNameLen);
Stream_Read_UINT32(s, CacheFieldsLen);
if (Stream_GetRemainingLength(s) < PnPNameLen)
return ERROR_INVALID_DATA;
PnPName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PnPNameLen);
if (Stream_GetRemainingLength(s) < DriverNameLen)
return ERROR_INVALID_DATA;
DriverName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, DriverNameLen);
if (Stream_GetRemainingLength(s) < PrintNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrintNameLen);
if (Stream_GetRemainingLength(s) < CacheFieldsLen)
return ERROR_INVALID_DATA;
CachedPrinterConfigData = Stream_Pointer(s);
Stream_Seek(s, CacheFieldsLen);
if (!printer_save_to_config(settings,
PortDosName, sizeof(PortDosName),
PnPName, PnPNameLen,
DriverName, DriverNameLen,
PrinterName, PrintNameLen,
CachedPrinterConfigData, CacheFieldsLen))
return ERROR_INTERNAL_ERROR;
}
break;
case RDPDR_UPDATE_PRINTER_EVENT:
{
UINT32 PrinterNameLen, ConfigDataLen;
const WCHAR* PrinterName;
const BYTE* ConfigData;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
Stream_Read_UINT32(s, ConfigDataLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < ConfigDataLen)
return ERROR_INVALID_DATA;
ConfigData = Stream_Pointer(s);
Stream_Seek(s, ConfigDataLen);
if (!printer_update_to_config(settings, PrinterName, PrinterNameLen, ConfigData, ConfigDataLen))
return ERROR_INTERNAL_ERROR;
}
break;
case RDPDR_DELETE_PRINTER_EVENT:
{
UINT32 PrinterNameLen;
const WCHAR* PrinterName;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
printer_remove_config(settings, PrinterName, PrinterNameLen);
}
break;
case RDPDR_RENAME_PRINTER_EVENT:
{
UINT32 OldPrinterNameLen, NewPrinterNameLen;
const WCHAR* OldPrinterName;
const WCHAR* NewPrinterName;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, OldPrinterNameLen);
Stream_Read_UINT32(s, NewPrinterNameLen);
if (Stream_GetRemainingLength(s) < OldPrinterNameLen)
return ERROR_INVALID_DATA;
OldPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, OldPrinterNameLen);
if (Stream_GetRemainingLength(s) < NewPrinterNameLen)
return ERROR_INVALID_DATA;
NewPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, NewPrinterNameLen);
if (!printer_move_config(settings, OldPrinterName, OldPrinterNameLen, NewPrinterName,
NewPrinterNameLen))
return ERROR_INTERNAL_ERROR;
}
break;
default:
WLog_ERR(TAG, "Unknown cache data eventID: 0x%08"PRIX32"", eventID);
return ERROR_INVALID_DATA;
}
break;
case PAKID_PRN_USING_XPS:
{
UINT32 flags;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, flags);
WLog_ERR(TAG,
"Ignoring unhandled message PAKID_PRN_USING_XPS [printerID=%08"PRIx32", flags=%08"PRIx32"]",
eventID, flags);
}
break;
default:
WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
@@ -336,13 +872,6 @@ static UINT printer_free(DEVICE* device)
UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
rdpPrinter* printer)
{
UINT32 Flags;
int DriverNameLen;
WCHAR* DriverName = NULL;
int PrintNameLen;
WCHAR* PrintName = NULL;
UINT32 CachedFieldsLen;
BYTE* CachedPrinterConfigData;
PRINTER_DEVICE* printer_dev;
UINT error;
printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE));
@@ -353,55 +882,19 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
return CHANNEL_RC_NO_MEMORY;
}
printer_dev->device.data = Stream_New(NULL, 1024);
if (!printer_dev->device.data)
goto error_out;
sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id);
printer_dev->device.type = RDPDR_DTYP_PRINT;
printer_dev->device.name = printer_dev->port;
printer_dev->device.IRPRequest = printer_irp_request;
printer_dev->device.CustomComponentRequest = printer_custom_component;
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;
CachedFieldsLen = 0;
CachedPrinterConfigData = NULL;
Flags = 0;
if (printer->is_default)
Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
0) * 2;
PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName,
0) * 2;
printer_dev->device.data = Stream_New(NULL,
28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
if (!printer_dev->device.data)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
free(DriverName);
free(PrintName);
goto error_out;
}
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);
}
free(DriverName);
free(PrintName);
printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof(
WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
@@ -412,6 +905,9 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
goto error_out;
}
if (!printer_load_from_config(pEntryPoints->rdpcontext->settings, printer, printer_dev))
goto error_out;
InitializeSListHead(printer_dev->pIrpList);
if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
@@ -497,6 +993,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (!printer_save_default_config(pEntryPoints->rdpcontext->settings, printer))
return CHANNEL_RC_INITIALIZATION_ERROR;
if ((error = printer_register(pEntryPoints, printer)))
{
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);

View File

@@ -54,7 +54,7 @@ struct rdp_printer
pcFreePrinter Free;
};
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, BYTE* data, int size);
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, const BYTE* data, size_t size);
typedef void (*pcClosePrintJob) (rdpPrintJob* printjob);
struct rdp_print_job

View File

@@ -68,8 +68,8 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr)
devman->plugin = (void*) rdpdr;
devman->id_sequence = 1;
devman->devices = ListDictionary_New(TRUE);
if (!devman->devices)
{
WLog_INFO(TAG, "ListDictionary_New failed!");
@@ -78,7 +78,6 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr)
}
ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free;
return devman;
}
@@ -114,26 +113,57 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device)
return ERROR_INVALID_PARAMETER;
device->id = devman->id_sequence++;
key = (void*) (size_t) device->id;
key = (void*)(size_t) device->id;
if (!ListDictionary_Add(devman->devices, key, device))
{
WLog_INFO(TAG, "ListDictionary_Add failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id)
{
DEVICE* device = NULL;
void* key = (void*) (size_t) id;
void* key = (void*)(size_t) id;
if (!devman)
return NULL;
device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key);
return device;
}
DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
{
DEVICE* device = NULL;
ULONG_PTR* keys;
int count, x;
if (!devman)
return NULL;
ListDictionary_Lock(devman->devices);
count = ListDictionary_GetKeys(devman->devices, &keys);
for (x = 0; x < count; x++)
{
DEVICE* cur = (DEVICE*) ListDictionary_GetItemValue(devman->devices, keys[x]);
if (!cur)
continue;
if (cur->type != type)
continue;
device = cur;
break;
}
free(keys);
ListDictionary_Unlock(devman->devices);
return device;
}
@@ -178,7 +208,9 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext
WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name);
else
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL,
"DeviceServiceEntry", 0);
if (!entry)
{
@@ -190,6 +222,5 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext
ep.RegisterDevice = devman_register_device;
ep.device = device;
ep.rdpcontext = rdpcontext;
return entry(&ep);
}

View File

@@ -28,6 +28,7 @@
void devman_unregister_device(DEVMAN* devman, void* key);
UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext);
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type);
DEVMAN* devman_new(rdpdrPlugin* rdpdr);
void devman_free(DEVMAN* devman);

View File

@@ -135,7 +135,8 @@ BOOL check_path(char* path)
{
UINT type = GetDriveTypeA(path);
if (!(type == DRIVE_FIXED ||type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE))
if (!(type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_CDROM ||
type == DRIVE_REMOTE))
return FALSE;
return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0);
@@ -1324,6 +1325,31 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s)
return error;
}
static UINT rdpdr_process_component(rdpdrPlugin* rdpdr, UINT16 component, UINT16 packetId,
wStream* s)
{
UINT32 type;
DEVICE* device;
switch (component)
{
case RDPDR_CTYP_PRN:
type = RDPDR_DTYP_PRINT;
break;
default:
return ERROR_INVALID_DATA;
}
device = devman_get_device_by_type(rdpdr->devman, type);
if (!device)
return ERROR_INVALID_PARAMETER;
return IFCALLRESULT(ERROR_INVALID_PARAMETER, device->CustomComponentRequest, device, component,
packetId, s);
}
/**
* Function description
*
@@ -1368,141 +1394,114 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
UINT16 packetId;
UINT32 deviceId;
UINT32 status;
UINT error;
UINT error = ERROR_INVALID_DATA;
if (!rdpdr || !s)
return CHANNEL_RC_NULL_DATA;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, component); /* Component (2 bytes) */
Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */
if (component == RDPDR_CTYP_CORE)
if (Stream_GetRemainingLength(s) >= 4)
{
switch (packetId)
Stream_Read_UINT16(s, component); /* Component (2 bytes) */
Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */
if (component == RDPDR_CTYP_CORE)
{
case PAKID_CORE_SERVER_ANNOUNCE:
if ((error = rdpdr_process_server_announce_request(rdpdr, s)))
return error;
switch (packetId)
{
case PAKID_CORE_SERVER_ANNOUNCE:
if ((error = rdpdr_process_server_announce_request(rdpdr, s)))
{
}
else if ((error = rdpdr_send_client_announce_reply(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error);
}
else if ((error = rdpdr_send_client_name_request(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error);
}
else if ((error = rdpdr_process_init(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error);
}
if ((error = rdpdr_send_client_announce_reply(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error);
return error;
}
break;
if ((error = rdpdr_send_client_name_request(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error);
return error;
}
case PAKID_CORE_SERVER_CAPABILITY:
if ((error = rdpdr_process_capability_request(rdpdr, s)))
{
}
else if ((error = rdpdr_send_capability_response(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error);
}
if ((error = rdpdr_process_init(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error);
return error;
}
break;
break;
case PAKID_CORE_CLIENTID_CONFIRM:
if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s)))
{
}
else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
}
case PAKID_CORE_SERVER_CAPABILITY:
if ((error = rdpdr_process_capability_request(rdpdr, s)))
return error;
break;
if ((error = rdpdr_send_capability_response(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error);
return error;
}
case PAKID_CORE_USER_LOGGEDON:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
}
break;
break;
case PAKID_CORE_CLIENTID_CONFIRM:
if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s)))
return error;
case PAKID_CORE_DEVICE_REPLY:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
return error;
}
/* connect to a specific resource */
if (Stream_GetRemainingLength(s) >= 8)
{
Stream_Read_UINT32(s, deviceId);
Stream_Read_UINT32(s, status);
error = CHANNEL_RC_OK;
}
break;
break;
case PAKID_CORE_USER_LOGGEDON:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
return error;
}
case PAKID_CORE_DEVICE_IOREQUEST:
if ((error = rdpdr_process_irp(rdpdr, s)))
{
WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error);
return error;
}
else
s = NULL;
break;
break;
case PAKID_CORE_DEVICE_REPLY:
/* connect to a specific resource */
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, deviceId);
Stream_Read_UINT32(s, status);
break;
case PAKID_CORE_DEVICE_IOREQUEST:
if ((error = rdpdr_process_irp(rdpdr, s)))
{
WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error);
return error;
}
s = NULL;
break;
default:
WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
break;
default:
WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId);
error = ERROR_INVALID_DATA;
break;
}
}
}
else if (component == RDPDR_CTYP_PRN)
{
switch (packetId)
else
{
case PAKID_PRN_CACHE_DATA:
{
UINT32 eventID;
error = rdpdr_process_component(rdpdr, component, packetId, s);
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, eventID);
WLog_ERR(TAG,
"Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%08"PRIX32")", eventID);
}
break;
case PAKID_PRN_USING_XPS:
WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS");
break;
default:
WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component,
packetId);
}
}
}
else
{
WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component,
packetId);
return ERROR_INVALID_DATA;
}
Stream_Free(s, TRUE);
return CHANNEL_RC_OK;
return error;
}
/**

View File

@@ -316,6 +316,8 @@ typedef struct _DEVICE DEVICE;
typedef struct _IRP IRP;
typedef struct _DEVMAN DEVMAN;
typedef UINT(*pcCustomComponentRequest)(DEVICE* device, UINT16 component, UINT16 packetId,
wStream* s);
typedef UINT(*pcIRPRequest)(DEVICE* device, IRP* irp);
typedef UINT(*pcInitDevice)(DEVICE* device);
typedef UINT(*pcFreeDevice)(DEVICE* device);
@@ -328,6 +330,7 @@ struct _DEVICE
const char* name;
wStream* data;
pcCustomComponentRequest CustomComponentRequest;
pcIRPRequest IRPRequest;
pcInitDevice Init;
pcFreeDevice Free;