mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
[channels,rdpdr] refactoring server callbacks
* Add callbacks for all messages exchanged between client and server to allow server implementations to intercept them. * Unify logging * Add device tracking
This commit is contained in:
committed by
Martin Fleisz
parent
3b5347e229
commit
37d7b98449
@@ -4,8 +4,9 @@
|
||||
*
|
||||
* Copyright 2014 Dell Software <Mike.McDonald@software.dell.com>
|
||||
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015-2022 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2022 Armin Novak <anovak@thincast.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,6 +40,113 @@
|
||||
#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
|
||||
#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
|
||||
|
||||
#define RDPDR_HEADER_LENGTH 4
|
||||
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
|
||||
|
||||
struct s_rdpdr_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
|
||||
UINT32 ClientId;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
char* ClientComputerName;
|
||||
|
||||
BOOL UserLoggedOnPdu;
|
||||
|
||||
wListDictionary* IrpList;
|
||||
UINT32 NextCompletionId;
|
||||
|
||||
wHashTable* devicelist;
|
||||
};
|
||||
|
||||
static void rdpdr_device_free(RdpdrDevice* device)
|
||||
{
|
||||
if (!device)
|
||||
return;
|
||||
free(device->DeviceData);
|
||||
free(device);
|
||||
}
|
||||
|
||||
static void rdpdr_device_free_h(void* obj)
|
||||
{
|
||||
RdpdrDevice* other = obj;
|
||||
rdpdr_device_free(other);
|
||||
}
|
||||
|
||||
static UINT32 rdpdr_deviceid_hash(const void* id)
|
||||
{
|
||||
WINPR_ASSERT(id);
|
||||
return *((const UINT32*)id);
|
||||
}
|
||||
|
||||
static RdpdrDevice* rdpdr_device_new(void)
|
||||
{
|
||||
return calloc(1, sizeof(RdpdrDevice));
|
||||
}
|
||||
|
||||
static void* rdpdr_device_clone(const void* val)
|
||||
{
|
||||
const RdpdrDevice* other = val;
|
||||
RdpdrDevice* tmp;
|
||||
|
||||
if (!other)
|
||||
return NULL;
|
||||
|
||||
tmp = rdpdr_device_new();
|
||||
if (!tmp)
|
||||
goto fail;
|
||||
|
||||
*tmp = *other;
|
||||
if (other->DeviceData)
|
||||
{
|
||||
tmp->DeviceData = malloc(other->DeviceDataLength);
|
||||
if (!tmp->DeviceData)
|
||||
goto fail;
|
||||
memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
|
||||
}
|
||||
return tmp;
|
||||
|
||||
fail:
|
||||
rdpdr_device_free(tmp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
|
||||
{
|
||||
WINPR_ASSERT(priv);
|
||||
|
||||
return HashTable_GetItemValue(priv->devicelist, &DeviceId);
|
||||
}
|
||||
|
||||
static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
|
||||
{
|
||||
const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
|
||||
WINPR_ASSERT(priv);
|
||||
|
||||
if (!device)
|
||||
{
|
||||
WLog_WARN(TAG, "[del] Device Id: 0x%08" PRIX32 ": no such device", DeviceId);
|
||||
return FALSE;
|
||||
}
|
||||
WLog_DBG(TAG, "[del] Device Name: %s Id: 0x%08" PRIX32 " DataLength: %" PRIu32 "",
|
||||
device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
|
||||
return HashTable_Remove(priv->devicelist, &DeviceId);
|
||||
}
|
||||
|
||||
static BOOL rdpdr_add_device(RdpdrServerPrivate* priv, const RdpdrDevice* device)
|
||||
{
|
||||
WINPR_ASSERT(priv);
|
||||
WINPR_ASSERT(device);
|
||||
|
||||
WLog_DBG(TAG, "[add] Device Name: %s Id: 0x%08" PRIX32 " DataLength: %" PRIu32 "",
|
||||
device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
|
||||
|
||||
return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
|
||||
}
|
||||
|
||||
static UINT32 g_ClientId = 0;
|
||||
|
||||
static const WCHAR* rdpdr_read_ustring(wStream* s, size_t bytelen)
|
||||
@@ -58,8 +166,7 @@ static const WCHAR* rdpdr_read_ustring(wStream* s, size_t bytelen)
|
||||
|
||||
static RDPDR_IRP* rdpdr_server_irp_new(void)
|
||||
{
|
||||
RDPDR_IRP* irp;
|
||||
irp = (RDPDR_IRP*)calloc(1, sizeof(RDPDR_IRP));
|
||||
RDPDR_IRP* irp = (RDPDR_IRP*)calloc(1, sizeof(RDPDR_IRP));
|
||||
return irp;
|
||||
}
|
||||
|
||||
@@ -96,6 +203,18 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
||||
Stream_SealLength(s);
|
||||
length = Stream_Length(s);
|
||||
WINPR_ASSERT(length <= ULONG_MAX);
|
||||
Stream_SetPosition(s, 0);
|
||||
|
||||
if (length >= RDPDR_HEADER_LENGTH)
|
||||
{
|
||||
RDPDR_HEADER header = { 0 };
|
||||
Stream_Read_UINT16(s, header.Component);
|
||||
Stream_Read_UINT16(s, header.PacketId);
|
||||
|
||||
WLog_DBG(TAG, "sending message {Component %s[%04" PRIx16 "], PacketId %s[%04" PRIx16 "]",
|
||||
rdpdr_component_string(header.Component), header.Component,
|
||||
rdpdr_packetid_string(header.PacketId), header.PacketId);
|
||||
}
|
||||
winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
|
||||
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s),
|
||||
(ULONG)length, &written);
|
||||
@@ -110,14 +229,20 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
|
||||
*/
|
||||
static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
||||
{
|
||||
UINT error;
|
||||
wStream* s;
|
||||
RDPDR_HEADER header = { 0 };
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(context->priv);
|
||||
WLog_DBG(TAG, "RdpdrServerSendAnnounceRequest");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
|
||||
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
|
||||
|
||||
if (!s)
|
||||
@@ -140,7 +265,7 @@ static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s,
|
||||
RDPDR_HEADER* header)
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 ClientId;
|
||||
UINT16 VersionMajor;
|
||||
@@ -162,7 +287,9 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
||||
" ClientId: 0x%08" PRIX32 "",
|
||||
VersionMajor, VersionMinor, ClientId);
|
||||
context->priv->ClientId = ClientId;
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
|
||||
VersionMinor, ClientId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,7 +298,7 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s,
|
||||
RDPDR_HEADER* header)
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 UnicodeFlag;
|
||||
UINT32 CodePage;
|
||||
@@ -251,7 +378,8 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->ClientComputerName = _strdup((char*)Stream_Pointer(s));
|
||||
const char* name = (const char*)Stream_Pointer(s);
|
||||
context->priv->ClientComputerName = _strdup(name);
|
||||
Stream_Seek(s, ComputerNameLen);
|
||||
|
||||
if (!context->priv->ClientComputerName)
|
||||
@@ -262,7 +390,8 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
||||
}
|
||||
|
||||
WLog_DBG(TAG, "ClientComputerName: %s", context->priv->ClientComputerName);
|
||||
return CHANNEL_RC_OK;
|
||||
return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
|
||||
context->priv->ClientComputerName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +416,8 @@ static UINT rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
|
||||
static UINT rdpdr_server_write_capability_set_header(wStream* s,
|
||||
const RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
WINPR_ASSERT(header);
|
||||
if (!Stream_EnsureRemainingCapacity(s, 8))
|
||||
@@ -302,6 +432,16 @@ static UINT rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILIT
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context, wStream* s,
|
||||
const RDPDR_CAPABILITY_HEADER* header)
|
||||
{
|
||||
UINT error = rdpdr_server_write_capability_set_header(s, header);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@@ -421,7 +561,12 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
rdpdr_server_write_capability_set_header(s, &header);
|
||||
UINT error = rdpdr_server_write_capability_set_header(s, &header);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
const BYTE* data = Stream_Pointer(s);
|
||||
const size_t start = Stream_GetPosition(s);
|
||||
Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */
|
||||
Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */
|
||||
Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
|
||||
@@ -433,7 +578,8 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* contex
|
||||
Stream_Write_UINT32(
|
||||
s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
|
||||
Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
|
||||
return CHANNEL_RC_OK;
|
||||
const size_t end = Stream_GetPosition(s);
|
||||
return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -477,7 +623,7 @@ static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* contex
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return rdpdr_server_write_capability_set_header(s, &header);
|
||||
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -519,7 +665,7 @@ static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return rdpdr_server_write_capability_set_header(s, &header);
|
||||
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -562,7 +708,7 @@ static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
return rdpdr_server_write_capability_set_header(s, &header);
|
||||
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -604,7 +750,7 @@ static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* cont
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
return rdpdr_server_write_capability_set_header(s, &header);
|
||||
return rdpdr_server_write_capability_set_header_cb(context, s, &header);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -620,21 +766,22 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
||||
UINT error;
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(context->priv);
|
||||
WLog_DBG(TAG, "RdpdrServerSendCoreCapabilityRequest");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
|
||||
numCapabilities = 1;
|
||||
|
||||
if (context->supportsDrives)
|
||||
if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
|
||||
numCapabilities++;
|
||||
|
||||
if (context->supportsPorts)
|
||||
if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
|
||||
((context->supported & RDPDR_DTYP_SERIAL) != 0))
|
||||
numCapabilities++;
|
||||
|
||||
if (context->supportsPrinters)
|
||||
if ((context->supported & RDPDR_DTYP_PRINT) != 0)
|
||||
numCapabilities++;
|
||||
|
||||
if (context->supportsSmartcards)
|
||||
if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
||||
numCapabilities++;
|
||||
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
|
||||
@@ -657,7 +804,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (context->supportsDrives)
|
||||
if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
|
||||
{
|
||||
if ((error = rdpdr_server_write_drive_capability_set(context, s)))
|
||||
{
|
||||
@@ -667,7 +814,8 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
||||
}
|
||||
}
|
||||
|
||||
if (context->supportsPorts)
|
||||
if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
|
||||
((context->supported & RDPDR_DTYP_SERIAL) != 0))
|
||||
{
|
||||
if ((error = rdpdr_server_write_port_capability_set(context, s)))
|
||||
{
|
||||
@@ -677,7 +825,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
||||
}
|
||||
}
|
||||
|
||||
if (context->supportsPrinters)
|
||||
if ((context->supported & RDPDR_DTYP_PRINT) != 0)
|
||||
{
|
||||
if ((error = rdpdr_server_write_printer_capability_set(context, s)))
|
||||
{
|
||||
@@ -688,7 +836,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* contex
|
||||
}
|
||||
}
|
||||
|
||||
if (context->supportsSmartcards)
|
||||
if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
||||
{
|
||||
if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
|
||||
{
|
||||
@@ -711,7 +859,7 @@ out:
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s,
|
||||
RDPDR_HEADER* header)
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT16 i = 0;
|
||||
UINT status = 0;
|
||||
@@ -728,6 +876,7 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
||||
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
|
||||
Stream_Seek_UINT16(s); /* Padding (2 bytes) */
|
||||
|
||||
UINT16 caps = 0;
|
||||
for (i = 0; i < numCapabilities; i++)
|
||||
{
|
||||
RDPDR_CAPABILITY_HEADER capabilityHeader = { 0 };
|
||||
@@ -740,6 +889,12 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
||||
return status;
|
||||
}
|
||||
|
||||
status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
|
||||
Stream_GetRemainingLength(s), Stream_Pointer(s));
|
||||
if (status != CHANNEL_RC_OK)
|
||||
return status;
|
||||
|
||||
caps |= capabilityHeader.CapabilityType;
|
||||
switch (capabilityHeader.CapabilityType)
|
||||
{
|
||||
case CAP_GENERAL_TYPE:
|
||||
@@ -819,6 +974,21 @@ static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* co
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
for (UINT16 x = 0; x < 16; x++)
|
||||
{
|
||||
const UINT16 mask = (UINT16)(1 << x);
|
||||
if (((caps & mask) != 0) && ((context->supported & mask) == 0))
|
||||
{
|
||||
WLog_WARN(TAG, "[%s] client sent capability %s we did not announce!", __FUNCTION__,
|
||||
freerdp_rdpdr_dtyp_string(x));
|
||||
}
|
||||
|
||||
/* we assume the server supports the capability. so only deactivate what the client did
|
||||
* not respond with */
|
||||
if ((caps & mask) == 0)
|
||||
context->supported &= ~mask;
|
||||
}
|
||||
|
||||
const size_t end = Stream_GetPosition(s);
|
||||
const size_t diff = end - start;
|
||||
if (diff != capabilityHeader.CapabilityLength)
|
||||
@@ -846,7 +1016,7 @@ static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(context->priv);
|
||||
WLog_DBG(TAG, "RdpdrServerSendClientIdConfirm");
|
||||
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
|
||||
@@ -890,83 +1060,76 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
||||
|
||||
for (i = 0; i < DeviceCount; i++)
|
||||
{
|
||||
UINT32 DeviceType = 0;
|
||||
UINT32 DeviceId = 0;
|
||||
UINT32 DeviceDataLength = 0;
|
||||
char PreferredDosName[9] = { 0 };
|
||||
UINT error;
|
||||
RdpdrDevice device = { 0 };
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 20))
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */
|
||||
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
||||
Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */
|
||||
Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */
|
||||
Stream_Read_UINT32(s, device.DeviceType); /* DeviceType (4 bytes) */
|
||||
Stream_Read_UINT32(s, device.DeviceId); /* DeviceId (4 bytes) */
|
||||
Stream_Read(s, device.PreferredDosName, 8); /* PreferredDosName (8 bytes) */
|
||||
Stream_Read_UINT32(s, device.DeviceDataLength); /* DeviceDataLength (4 bytes) */
|
||||
device.DeviceData = Stream_Pointer(s);
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, DeviceDataLength))
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, device.DeviceDataLength))
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
WLog_DBG(TAG, "Device %" PRIu32 " Name: %s Id: 0x%08" PRIX32 " DataLength: %" PRIu32 "", i,
|
||||
PreferredDosName, DeviceId, DeviceDataLength);
|
||||
if (!rdpdr_add_device(context->priv, &device))
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
switch (DeviceType)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
switch (device.DeviceType)
|
||||
{
|
||||
case RDPDR_DTYP_FILESYSTEM:
|
||||
if (context->supportsDrives)
|
||||
{
|
||||
IFCALL(context->OnDriveCreate, context, DeviceId, PreferredDosName);
|
||||
}
|
||||
|
||||
if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PRINT:
|
||||
if (context->supportsPrinters)
|
||||
{
|
||||
IFCALL(context->OnPrinterCreate, context, DeviceId, PreferredDosName);
|
||||
}
|
||||
|
||||
if ((context->supported & RDPDR_DTYP_PRINT) != 0)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SERIAL:
|
||||
if (DeviceDataLength != 0)
|
||||
if (device.DeviceDataLength != 0)
|
||||
{
|
||||
WLog_WARN(TAG, "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32 "]",
|
||||
DeviceDataLength);
|
||||
device.DeviceDataLength);
|
||||
error = ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (context->supportsPorts)
|
||||
{
|
||||
IFCALL(context->OnPortCreate, context, DeviceId, PreferredDosName);
|
||||
}
|
||||
|
||||
else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PARALLEL:
|
||||
if (DeviceDataLength != 0)
|
||||
if (device.DeviceDataLength != 0)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32 "]",
|
||||
DeviceDataLength);
|
||||
device.DeviceDataLength);
|
||||
error = ERROR_INVALID_DATA;
|
||||
}
|
||||
if (context->supportsPorts)
|
||||
{
|
||||
IFCALL(context->OnPortCreate, context, DeviceId, PreferredDosName);
|
||||
}
|
||||
|
||||
else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
|
||||
&device);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SMARTCARD:
|
||||
if (DeviceDataLength != 0)
|
||||
if (device.DeviceDataLength != 0)
|
||||
{
|
||||
WLog_WARN(TAG,
|
||||
"[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32 "]",
|
||||
DeviceDataLength);
|
||||
device.DeviceDataLength);
|
||||
error = ERROR_INVALID_DATA;
|
||||
}
|
||||
if (context->supportsSmartcards)
|
||||
{
|
||||
IFCALL(context->OnSmartcardCreate, context, DeviceId, PreferredDosName);
|
||||
}
|
||||
|
||||
else if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardCreate, context, &device);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -974,11 +1137,15 @@ static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext
|
||||
"[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
|
||||
"(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
|
||||
" at position %" PRIu32,
|
||||
DeviceType, i);
|
||||
device.DeviceType, i);
|
||||
error = ERROR_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
Stream_Seek(s, DeviceDataLength);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
Stream_Seek(s, device.DeviceDataLength);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
@@ -1009,51 +1176,64 @@ static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext*
|
||||
|
||||
for (i = 0; i < DeviceCount; i++)
|
||||
{
|
||||
UINT error;
|
||||
const RdpdrDevice* device;
|
||||
|
||||
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
|
||||
device = rdpdr_get_device_by_id(context->priv, DeviceId);
|
||||
WLog_DBG(TAG, "Device %" PRIu32 " Id: 0x%08" PRIX32 "", i, DeviceId);
|
||||
DeviceType = 0; /* TODO: Save the device type on the announce request. */
|
||||
DeviceType = 0;
|
||||
if (device)
|
||||
DeviceType = device->DeviceType;
|
||||
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
switch (DeviceType)
|
||||
{
|
||||
case RDPDR_DTYP_FILESYSTEM:
|
||||
if (context->supportsDrives)
|
||||
{
|
||||
IFCALL(context->OnDriveDelete, context, DeviceId);
|
||||
}
|
||||
|
||||
if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PRINT:
|
||||
if (context->supportsPrinters)
|
||||
{
|
||||
IFCALL(context->OnPrinterDelete, context, DeviceId);
|
||||
}
|
||||
|
||||
if ((context->supported & RDPDR_DTYP_PRINT) != 0)
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SERIAL:
|
||||
case RDPDR_DTYP_PARALLEL:
|
||||
if (context->supportsPorts)
|
||||
{
|
||||
IFCALL(context->OnPortDelete, context, DeviceId);
|
||||
}
|
||||
if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_PARALLEL:
|
||||
if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
|
||||
error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
|
||||
DeviceId);
|
||||
break;
|
||||
|
||||
case RDPDR_DTYP_SMARTCARD:
|
||||
if (context->supportsSmartcards)
|
||||
{
|
||||
IFCALL(context->OnSmartcardDelete, context, DeviceId);
|
||||
}
|
||||
|
||||
if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
|
||||
error =
|
||||
IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
return error;
|
||||
|
||||
if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
@@ -1412,7 +1592,7 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
|
||||
}
|
||||
|
||||
static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context, wStream* s,
|
||||
RDPDR_HEADER* header)
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 DeviceId;
|
||||
UINT32 FileId;
|
||||
@@ -1487,7 +1667,7 @@ static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context, wStream* s,
|
||||
RDPDR_HEADER* header)
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT32 deviceId;
|
||||
UINT32 completionId;
|
||||
@@ -1536,7 +1716,6 @@ static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
|
||||
RDPDR_HEADER header = { 0 };
|
||||
|
||||
WINPR_ASSERT(context);
|
||||
WLog_DBG(TAG, "RdpdrServerSendUserLoggedOn");
|
||||
header.Component = RDPDR_CTYP_CORE;
|
||||
header.PacketId = PAKID_CORE_USER_LOGGEDON;
|
||||
s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
|
||||
@@ -1734,16 +1913,15 @@ static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* conte
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
|
||||
static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s,
|
||||
const RDPDR_HEADER* header)
|
||||
{
|
||||
UINT error = ERROR_INVALID_DATA;
|
||||
WINPR_ASSERT(context);
|
||||
WINPR_ASSERT(s);
|
||||
WINPR_ASSERT(header);
|
||||
|
||||
WLog_DBG(TAG,
|
||||
"RdpdrServerReceivePdu: Component: %s [0x%04" PRIx16 "] PacketId: %s [0x%04" PRIx16
|
||||
"]",
|
||||
WLog_DBG(TAG, "receiving message {Component %s[%04" PRIx16 "], PacketId %s[%04" PRIx16 "]",
|
||||
rdpdr_component_string(header->Component), header->Component,
|
||||
rdpdr_packetid_string(header->PacketId), header->PacketId);
|
||||
|
||||
@@ -1842,7 +2020,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RD
|
||||
rdpdr_packetid_string(header->PacketId));
|
||||
}
|
||||
|
||||
return error;
|
||||
return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
|
||||
}
|
||||
|
||||
static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
|
||||
@@ -3307,68 +3485,86 @@ static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* ca
|
||||
FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
|
||||
}
|
||||
|
||||
static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
ListDictionary_Free(ctx->IrpList);
|
||||
HashTable_Free(ctx->devicelist);
|
||||
free(ctx->ClientComputerName);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static RdpdrServerPrivate* rdpdr_server_private_new(void)
|
||||
{
|
||||
RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1, sizeof(RdpdrServerPrivate));
|
||||
|
||||
if (!priv)
|
||||
goto fail;
|
||||
|
||||
priv->VersionMajor = RDPDR_VERSION_MAJOR;
|
||||
priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
|
||||
priv->ClientId = g_ClientId++;
|
||||
priv->UserLoggedOnPdu = TRUE;
|
||||
priv->NextCompletionId = 1;
|
||||
priv->IrpList = ListDictionary_New(TRUE);
|
||||
|
||||
if (!priv->IrpList)
|
||||
goto fail;
|
||||
|
||||
priv->devicelist = HashTable_New(FALSE);
|
||||
if (!priv->devicelist)
|
||||
goto fail;
|
||||
|
||||
HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash);
|
||||
wObject* obj = HashTable_ValueObject(priv->devicelist);
|
||||
WINPR_ASSERT(obj);
|
||||
obj->fnObjectFree = rdpdr_device_free_h;
|
||||
obj->fnObjectNew = rdpdr_device_clone;
|
||||
|
||||
return priv;
|
||||
fail:
|
||||
rdpdr_server_private_free(priv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
|
||||
{
|
||||
RdpdrServerContext* context;
|
||||
context = (RdpdrServerContext*)calloc(1, sizeof(RdpdrServerContext));
|
||||
RdpdrServerContext* context = (RdpdrServerContext*)calloc(1, sizeof(RdpdrServerContext));
|
||||
|
||||
if (context)
|
||||
{
|
||||
context->vcm = vcm;
|
||||
context->Start = rdpdr_server_start;
|
||||
context->Stop = rdpdr_server_stop;
|
||||
context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
|
||||
context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
|
||||
context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
|
||||
context->DriveOpenFile = rdpdr_server_drive_open_file;
|
||||
context->DriveReadFile = rdpdr_server_drive_read_file;
|
||||
context->DriveWriteFile = rdpdr_server_drive_write_file;
|
||||
context->DriveCloseFile = rdpdr_server_drive_close_file;
|
||||
context->DriveDeleteFile = rdpdr_server_drive_delete_file;
|
||||
context->DriveRenameFile = rdpdr_server_drive_rename_file;
|
||||
context->priv = (RdpdrServerPrivate*)calloc(1, sizeof(RdpdrServerPrivate));
|
||||
if (!context)
|
||||
goto fail;
|
||||
|
||||
if (!context->priv)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
context->vcm = vcm;
|
||||
context->Start = rdpdr_server_start;
|
||||
context->Stop = rdpdr_server_stop;
|
||||
context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
|
||||
context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
|
||||
context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
|
||||
context->DriveOpenFile = rdpdr_server_drive_open_file;
|
||||
context->DriveReadFile = rdpdr_server_drive_read_file;
|
||||
context->DriveWriteFile = rdpdr_server_drive_write_file;
|
||||
context->DriveCloseFile = rdpdr_server_drive_close_file;
|
||||
context->DriveDeleteFile = rdpdr_server_drive_delete_file;
|
||||
context->DriveRenameFile = rdpdr_server_drive_rename_file;
|
||||
context->priv = rdpdr_server_private_new();
|
||||
if (!context->priv)
|
||||
goto fail;
|
||||
|
||||
context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
|
||||
context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
|
||||
context->priv->ClientId = g_ClientId++;
|
||||
context->priv->UserLoggedOnPdu = TRUE;
|
||||
context->priv->NextCompletionId = 1;
|
||||
context->priv->IrpList = ListDictionary_New(TRUE);
|
||||
|
||||
if (!context->priv->IrpList)
|
||||
{
|
||||
WLog_ERR(TAG, "ListDictionary_New failed!");
|
||||
free(context->priv);
|
||||
free(context);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
}
|
||||
/* By default announce everything, the server application can deactivate that later on */
|
||||
context->supported = UINT16_MAX;
|
||||
|
||||
return context;
|
||||
fail:
|
||||
rdpdr_server_context_free(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rdpdr_server_context_free(RdpdrServerContext* context)
|
||||
{
|
||||
if (context)
|
||||
{
|
||||
if (context->priv)
|
||||
{
|
||||
ListDictionary_Free(context->priv->IrpList);
|
||||
free(context->priv->ClientComputerName);
|
||||
free(context->priv);
|
||||
}
|
||||
if (!context)
|
||||
return;
|
||||
|
||||
free(context);
|
||||
}
|
||||
rdpdr_server_private_free(context->priv);
|
||||
free(context);
|
||||
}
|
||||
|
||||
@@ -31,40 +31,6 @@
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/server/rdpdr.h>
|
||||
|
||||
struct s_rdpdr_server_private
|
||||
{
|
||||
HANDLE Thread;
|
||||
HANDLE StopEvent;
|
||||
void* ChannelHandle;
|
||||
|
||||
UINT32 ClientId;
|
||||
UINT16 VersionMajor;
|
||||
UINT16 VersionMinor;
|
||||
char* ClientComputerName;
|
||||
|
||||
BOOL UserLoggedOnPdu;
|
||||
|
||||
wListDictionary* IrpList;
|
||||
UINT32 NextCompletionId;
|
||||
};
|
||||
|
||||
#define RDPDR_HEADER_LENGTH 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Component;
|
||||
UINT16 PacketId;
|
||||
} RDPDR_HEADER;
|
||||
|
||||
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 CapabilityType;
|
||||
UINT16 CapabilityLength;
|
||||
UINT32 Version;
|
||||
} RDPDR_CAPABILITY_HEADER;
|
||||
|
||||
typedef struct S_RDPDR_IRP
|
||||
{
|
||||
UINT32 CompletionId;
|
||||
|
||||
@@ -35,6 +35,19 @@
|
||||
typedef struct s_rdpdr_server_context RdpdrServerContext;
|
||||
typedef struct s_rdpdr_server_private RdpdrServerPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 Component;
|
||||
UINT16 PacketId;
|
||||
} RDPDR_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 CapabilityType;
|
||||
UINT16 CapabilityLength;
|
||||
UINT32 Version;
|
||||
} RDPDR_CAPABILITY_HEADER;
|
||||
|
||||
#ifndef __MINGW32__
|
||||
typedef struct
|
||||
{
|
||||
@@ -51,9 +64,33 @@ typedef struct
|
||||
} FILE_DIRECTORY_INFORMATION;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 DeviceType;
|
||||
UINT32 DeviceId;
|
||||
char PreferredDosName[9];
|
||||
UINT32 DeviceDataLength;
|
||||
BYTE* DeviceData;
|
||||
} RdpdrDevice;
|
||||
|
||||
typedef UINT (*psRdpdrStart)(RdpdrServerContext* context);
|
||||
typedef UINT (*psRdpdrStop)(RdpdrServerContext* context);
|
||||
|
||||
typedef UINT (*psRdpdrCapablityPDU)(RdpdrServerContext* context,
|
||||
const RDPDR_CAPABILITY_HEADER* header, size_t size,
|
||||
const BYTE* data);
|
||||
typedef UINT (*psRdpdrReceivePDU)(RdpdrServerContext* context, const RDPDR_HEADER* header,
|
||||
UINT error);
|
||||
typedef UINT (*psRdpdrReceiveAnnounceResponse)(RdpdrServerContext* context, UINT16 VersionMajor,
|
||||
UINT16 VersionMinor, UINT32 ClientId);
|
||||
typedef UINT (*psRdpdrSendServerAnnounce)(RdpdrServerContext* context);
|
||||
typedef UINT (*psRdpdrReceiveDeviceAnnounce)(RdpdrServerContext* context,
|
||||
const RdpdrDevice* device);
|
||||
typedef UINT (*psRdpdrReceiveDeviceRemove)(RdpdrServerContext* context, UINT32 deviceId,
|
||||
const RdpdrDevice* device);
|
||||
typedef UINT (*psRdpdrReceiveClientNameRequest)(RdpdrServerContext* context, size_t ComputerNameLen,
|
||||
const char* name);
|
||||
|
||||
typedef UINT (*psRdpdrDriveCreateDirectory)(RdpdrServerContext* context, void* callbackData,
|
||||
UINT32 deviceId, const char* path);
|
||||
typedef UINT (*psRdpdrDriveDeleteDirectory)(RdpdrServerContext* context, void* callbackData,
|
||||
@@ -75,9 +112,6 @@ typedef UINT (*psRdpdrDriveDeleteFile)(RdpdrServerContext* context, void* callba
|
||||
typedef UINT (*psRdpdrDriveRenameFile)(RdpdrServerContext* context, void* callbackData,
|
||||
UINT32 deviceId, const char* oldPath, const char* newPath);
|
||||
|
||||
typedef void (*psRdpdrOnDriveCreate)(RdpdrServerContext* context, UINT32 deviceId,
|
||||
const char* name);
|
||||
typedef void (*psRdpdrOnDriveDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
||||
typedef void (*psRdpdrOnDriveCreateDirectoryComplete)(RdpdrServerContext* context,
|
||||
void* callbackData, UINT32 ioStatus);
|
||||
typedef void (*psRdpdrOnDriveDeleteDirectoryComplete)(RdpdrServerContext* context,
|
||||
@@ -98,16 +132,8 @@ typedef void (*psRdpdrOnDriveDeleteFileComplete)(RdpdrServerContext* context, vo
|
||||
typedef void (*psRdpdrOnDriveRenameFileComplete)(RdpdrServerContext* context, void* callbackData,
|
||||
UINT32 ioStatus);
|
||||
|
||||
typedef void (*psRdpdrOnPortCreate)(RdpdrServerContext* context, UINT32 deviceId, const char* name);
|
||||
typedef void (*psRdpdrOnPortDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
||||
|
||||
typedef void (*psRdpdrOnPrinterCreate)(RdpdrServerContext* context, UINT32 deviceId,
|
||||
const char* name);
|
||||
typedef void (*psRdpdrOnPrinterDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
||||
|
||||
typedef void (*psRdpdrOnSmartcardCreate)(RdpdrServerContext* context, UINT32 deviceId,
|
||||
const char* name);
|
||||
typedef void (*psRdpdrOnSmartcardDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
||||
typedef UINT (*psRdpdrOnDeviceCreate)(RdpdrServerContext* context, const RdpdrDevice* device);
|
||||
typedef UINT (*psRdpdrOnDeviceDelete)(RdpdrServerContext* context, UINT32 deviceId);
|
||||
|
||||
struct s_rdpdr_server_context
|
||||
{
|
||||
@@ -121,11 +147,30 @@ struct s_rdpdr_server_context
|
||||
/* Server self-defined pointer. */
|
||||
void* data;
|
||||
|
||||
/* Server supported redirections. Set by server. */
|
||||
BOOL supportsDrives;
|
||||
BOOL supportsPorts;
|
||||
BOOL supportsPrinters;
|
||||
BOOL supportsSmartcards;
|
||||
/**< Server supported redirections.
|
||||
* initially used to determine which redirections are supported by the
|
||||
* server in the server capability, later on updated with what the client
|
||||
* actually wants to have supported.
|
||||
*
|
||||
* Use the \b RDPDR_DTYP_* defines as a mask to check.
|
||||
*/
|
||||
UINT16 supported;
|
||||
|
||||
/*** RDPDR message intercept callbacks */
|
||||
psRdpdrCapablityPDU ReceiveCaps; /**< Called for each received capability */
|
||||
psRdpdrCapablityPDU SendCaps; /**< Called for each capability to be sent */
|
||||
psRdpdrReceivePDU ReceivePDU; /**< Called after a RDPDR pdu was received and parsed */
|
||||
psRdpdrSendServerAnnounce
|
||||
SendServerAnnounce; /**< Called before the server sends the announce message */
|
||||
psRdpdrReceiveAnnounceResponse
|
||||
ReceiveAnnounceResponse; /**< Called after the client announce response is received */
|
||||
psRdpdrReceiveClientNameRequest
|
||||
ReceiveClientNameRequest; /**< Called after a client name request is received */
|
||||
psRdpdrReceiveDeviceAnnounce
|
||||
ReceiveDeviceAnnounce; /** < Called after a new device request was received but before the
|
||||
device is added */
|
||||
psRdpdrReceiveDeviceRemove ReceiveDeviceRemove; /**< Called after a new device request was
|
||||
received, but before it is removed */
|
||||
|
||||
/*** Drive APIs called by the server. ***/
|
||||
psRdpdrDriveCreateDirectory DriveCreateDirectory;
|
||||
@@ -139,8 +184,10 @@ struct s_rdpdr_server_context
|
||||
psRdpdrDriveRenameFile DriveRenameFile;
|
||||
|
||||
/*** Drive callbacks registered by the server. ***/
|
||||
psRdpdrOnDriveCreate OnDriveCreate;
|
||||
psRdpdrOnDriveDelete OnDriveDelete;
|
||||
psRdpdrOnDeviceCreate OnDriveCreate; /**< Called for devices of type \b RDPDR_DTYP_FILESYSTEM
|
||||
after \b ReceiveDeviceAnnounce */
|
||||
psRdpdrOnDeviceDelete OnDriveDelete; /**< Called for devices of type \b RDPDR_DTYP_FILESYSTEM
|
||||
after \b ReceiveDeviceRemove */
|
||||
psRdpdrOnDriveCreateDirectoryComplete OnDriveCreateDirectoryComplete;
|
||||
psRdpdrOnDriveDeleteDirectoryComplete OnDriveDeleteDirectoryComplete;
|
||||
psRdpdrOnDriveQueryDirectoryComplete OnDriveQueryDirectoryComplete;
|
||||
@@ -151,17 +198,29 @@ struct s_rdpdr_server_context
|
||||
psRdpdrOnDriveDeleteFileComplete OnDriveDeleteFileComplete;
|
||||
psRdpdrOnDriveRenameFileComplete OnDriveRenameFileComplete;
|
||||
|
||||
/*** Port callbacks registered by the server. ***/
|
||||
psRdpdrOnPortCreate OnPortCreate;
|
||||
psRdpdrOnPortDelete OnPortDelete;
|
||||
/*** Serial Port callbacks registered by the server. ***/
|
||||
psRdpdrOnDeviceCreate OnSerialPortCreate; /**< Called for devices of type \b RDPDR_DTYP_SERIAL
|
||||
after \b ReceiveDeviceAnnounce */
|
||||
psRdpdrOnDeviceDelete OnSerialPortDelete; /**< Called for devices of type \b RDPDR_DTYP_SERIAL
|
||||
after \b ReceiveDeviceRemove */
|
||||
|
||||
/*** Parallel Port callbacks registered by the server. ***/
|
||||
psRdpdrOnDeviceCreate OnParallelPortCreate; /**< Called for devices of type \b
|
||||
RDPDR_DTYP_PARALLEL after \b ReceiveDeviceAnnounce */
|
||||
psRdpdrOnDeviceDelete OnParallelPortDelete; /**< Called for devices of type \b
|
||||
RDPDR_DTYP_PARALLEL after \b ReceiveDeviceRemove */
|
||||
|
||||
/*** Printer callbacks registered by the server. ***/
|
||||
psRdpdrOnPrinterCreate OnPrinterCreate;
|
||||
psRdpdrOnPrinterDelete OnPrinterDelete;
|
||||
psRdpdrOnDeviceCreate OnPrinterCreate; /**< Called for devices of type RDPDR_DTYP_PRINT after \b
|
||||
ReceiveDeviceAnnounce */
|
||||
psRdpdrOnDeviceDelete OnPrinterDelete; /**< Called for devices of type RDPDR_DTYP_PRINT after \b
|
||||
ReceiveDeviceRemove */
|
||||
|
||||
/*** Smartcard callbacks registered by the server. ***/
|
||||
psRdpdrOnSmartcardCreate OnSmartcardCreate;
|
||||
psRdpdrOnSmartcardDelete OnSmartcardDelete;
|
||||
psRdpdrOnDeviceCreate OnSmartcardCreate; /**< Called for devices of type RDPDR_DTYP_SMARTCARD
|
||||
after \b ReceiveDeviceAnnounce */
|
||||
psRdpdrOnDeviceDelete OnSmartcardDelete; /**< Called for devices of type RDPDR_DTYP_SMARTCARD
|
||||
after \b ReceiveDeviceRemove */
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user