Added callback to handle printer custom components in printer backend.

This commit is contained in:
Armin Novak 2018-12-12 10:06:41 +01:00
parent 4dac07667c
commit 192680a001
5 changed files with 189 additions and 116 deletions

View File

@ -293,6 +293,44 @@ 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)
{
switch (component)
{
case RDPDR_CTYP_PRN:
switch (packetId)
{
case PAKID_PRN_CACHE_DATA:
{
UINT32 eventID;
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;
}
break;
default:
return ERROR_INVALID_DATA;
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
@ -357,6 +395,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
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;

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;