24#include <freerdp/config.h>
25#include <freerdp/freerdp.h>
26#include <freerdp/utils/rdpdr_utils.h>
29#include <winpr/interlocked.h>
30#include <winpr/assert.h>
32#include <winpr/print.h>
33#include <winpr/stream.h>
35#include <freerdp/channels/log.h>
36#include <freerdp/channels/scard.h>
37#include <freerdp/utils/smartcard_operations.h>
38#include "rdpdr_main.h"
39#include <freerdp/utils/channel_pdu_tracker.h>
41#define RDPDR_ADD_PRINTER_EVENT 0x00000001
42#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
43#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
44#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
46#define RDPDR_HEADER_LENGTH 4
47#define RDPDR_CAPABILITY_HEADER_LENGTH 8
50#define SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH 2048
52struct s_rdpdr_server_private
61 char* ClientComputerName;
65 wListDictionary* IrpList;
66 LONG NextCompletionId;
68 wHashTable* devicelist;
70 UINT32 SpecialDeviceTypeCap;
73 BOOL haveSmartcardDevice;
74 UINT32 smartcardDeviceId;
77static UINT32 g_ClientId = 0;
80static const char* fileInformation2str(uint8_t val)
85 return "FILE_DOES_NOT_EXIST";
89 return "FILE_OVERWRITTEN";
90 case FILE_OVERWRITTEN:
91 return "FILE_CREATED";
94 case FILE_DOES_NOT_EXIST:
95 return "FILE_SUPERSEDED";
97 return "FILE_UNKNOWN";
102static const char* DR_DRIVE_LOCK_REQ2str(uint32_t op)
106 case RDP_LOWIO_OP_SHAREDLOCK:
107 return "RDP_LOWIO_OP_UNLOCK_MULTIPLE";
108 case RDP_LOWIO_OP_EXCLUSIVELOCK:
109 return "RDP_LOWIO_OP_UNLOCK";
110 case RDP_LOWIO_OP_UNLOCK:
111 return "RDP_LOWIO_OP_EXCLUSIVELOCK";
112 case RDP_LOWIO_OP_UNLOCK_MULTIPLE:
113 return "RDP_LOWIO_OP_SHAREDLOCK";
115 return "RDP_LOWIO_OP_UNKNOWN";
123 free(device->DeviceData);
127static void rdpdr_device_free_h(
void* obj)
130 rdpdr_device_free(other);
134static UINT32 rdpdr_deviceid_hash(
const void*
id)
137 return *((
const UINT32*)
id);
141static BOOL rdpdr_device_equal(
const void* v1,
const void* v2)
143 const UINT32* p1 = (
const UINT32*)v1;
144 const UINT32* p2 = (
const UINT32*)v2;
152WINPR_ATTR_MALLOC(rdpdr_device_free, 1)
158WINPR_ATTR_MALLOC(rdpdr_device_free_h, 1)
159static
void* rdpdr_device_clone(const
void* val)
171 if (other->DeviceData)
173 tmp->DeviceData = malloc(other->DeviceDataLength);
174 if (!tmp->DeviceData)
176 memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
181 rdpdr_device_free(tmp);
185static void rdpdr_device_key_free(
void* obj)
190WINPR_ATTR_MALLOC(rdpdr_device_key_free, 1)
191static
void* rdpdr_device_key_clone(const
void* pvval)
193 const UINT32* val = pvval;
197 UINT32* ptr = calloc(1,
sizeof(UINT32));
205static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
208 return HashTable_GetItemValue(priv->devicelist, &DeviceId);
212static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
216 const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
219 WLog_Print(priv->log, WLOG_WARN,
"[del] Device Id: 0x%08" PRIX32
": no such device",
223 WLog_Print(priv->log, WLOG_DEBUG,
224 "[del] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
225 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
226 return HashTable_Remove(priv->devicelist, &DeviceId);
230static BOOL rdpdr_add_device(RdpdrServerPrivate* priv,
const RdpdrDevice* device)
233 WINPR_ASSERT(device);
235 WLog_Print(priv->log, WLOG_DEBUG,
236 "[add] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
237 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
239 return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
243static const WCHAR* rdpdr_read_ustring(wLog* log,
wStream* s,
size_t bytelen)
245 const size_t charlen = bytelen /
sizeof(WCHAR);
246 const WCHAR* str = Stream_ConstPointer(s);
247 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, bytelen))
249 if (_wcsnlen(str, charlen) == charlen)
251 WLog_Print(log, WLOG_WARN,
"[rdpdr] unicode string not '\\0' terminated");
254 Stream_Seek(s, bytelen);
258static void rdpdr_server_irp_free(RDPDR_IRP* irp)
264 free(irp->ExtraBuffer);
268WINPR_ATTR_MALLOC(rdpdr_server_irp_free, 1)
269static RDPDR_IRP* rdpdr_server_irp_new(
void)
271 RDPDR_IRP* irp = (RDPDR_IRP*)calloc(1,
sizeof(RDPDR_IRP));
275static void rdpdr_server_list_free(
void* ptr)
277 RDPDR_IRP* irp = ptr;
278 rdpdr_server_irp_free(irp);
282static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp)
284 WINPR_ASSERT(context);
285 WINPR_ASSERT(context->priv);
287 RdpdrServerPrivate* priv = context->priv;
288 const uintptr_t key = irp->CompletionId + 1ull;
289 return ListDictionary_Add(priv->IrpList, (
void*)key, irp);
292WINPR_ATTR_MALLOC(rdpdr_server_irp_free, 1)
293static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
295 WINPR_ASSERT(context);
296 WINPR_ASSERT(context->priv);
298 RdpdrServerPrivate* priv = context->priv;
299 const uintptr_t key = completionId + 1ull;
300 RDPDR_IRP* irp = (RDPDR_IRP*)ListDictionary_Take(priv->IrpList, (
void*)key);
305static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context,
wStream* s)
307 WINPR_ASSERT(context);
308 WINPR_ASSERT(context->priv);
311 RdpdrServerPrivate* priv = context->priv;
312 Stream_SealLength(s);
313 const size_t length = Stream_Length(s);
314 WINPR_ASSERT(length <= UINT32_MAX);
315 Stream_ResetPosition(s);
317 if (length >= RDPDR_HEADER_LENGTH)
321 .PacketId = Stream_Get_UINT16(s),
324 WLog_Print(priv->log, WLOG_DEBUG,
325 "sending message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
329 winpr_HexLogDump(priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
331 BOOL status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s,
char),
332 (ULONG)length, &written);
334 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
343static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
345 WINPR_ASSERT(context);
346 WINPR_ASSERT(context->priv);
348 UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
349 if (error != CHANNEL_RC_OK)
352 RdpdrServerPrivate* priv = context->priv;
353 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
356 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
357 return CHANNEL_RC_NO_MEMORY;
362 .PacketId = PAKID_CORE_SERVER_ANNOUNCE,
364 Stream_Write_UINT16(s, header.
Component);
365 Stream_Write_UINT16(s, header.
PacketId);
366 Stream_Write_UINT16(s, priv->VersionMajor);
367 Stream_Write_UINT16(s, priv->VersionMinor);
368 Stream_Write_UINT32(s, priv->ClientId);
369 return rdpdr_seal_send_free_request(context, s);
378static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
wStream* s,
381 WINPR_ASSERT(context);
382 WINPR_ASSERT(context->priv);
383 WINPR_ASSERT(header);
385 RdpdrServerPrivate* priv = context->priv;
387 WINPR_UNUSED(header);
389 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
390 return ERROR_INVALID_DATA;
392 const UINT16 VersionMajor = Stream_Get_UINT16(s);
393 const UINT16 VersionMinor = Stream_Get_UINT16(s);
394 const UINT32 ClientId = Stream_Get_UINT32(s);
395 WLog_Print(priv->log, WLOG_DEBUG,
396 "Client Announce Response: VersionMajor: 0x%08" PRIX16
" VersionMinor: 0x%04" PRIX16
397 " ClientId: 0x%08" PRIX32
"",
398 VersionMajor, VersionMinor, ClientId);
399 priv->ClientId = ClientId;
401 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
402 VersionMinor, ClientId);
411static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context,
wStream* s,
414 WINPR_ASSERT(context);
415 WINPR_ASSERT(context->priv);
417 WINPR_ASSERT(header);
418 WINPR_UNUSED(header);
420 RdpdrServerPrivate* priv = context->priv;
422 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
423 return ERROR_INVALID_DATA;
425 UINT32 UnicodeFlag = Stream_Get_UINT32(s);
426 const UINT32 CodePage = Stream_Get_UINT32(s);
427 const UINT32 ComputerNameLen = Stream_Get_UINT32(s);
430 UnicodeFlag = UnicodeFlag & 0x00000001;
433 WLog_Print(priv->log, WLOG_WARN,
434 "[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
435 "must be 0, but is 0x%08" PRIx32,
445 if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
447 WLog_Print(priv->log, WLOG_ERROR,
"invalid unicode computer name length: %" PRIu32
"",
449 return ERROR_INVALID_DATA;
454 if (ComputerNameLen > 256 || ComputerNameLen < 1)
456 WLog_Print(priv->log, WLOG_ERROR,
"invalid ascii computer name length: %" PRIu32
"",
458 return ERROR_INVALID_DATA;
462 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, ComputerNameLen))
463 return ERROR_INVALID_DATA;
466 const char* computerName = Stream_ConstPointer(s);
467 if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
469 WLog_Print(priv->log, WLOG_ERROR,
"computer name must be null terminated");
470 return ERROR_INVALID_DATA;
473 if (priv->ClientComputerName)
475 free(priv->ClientComputerName);
476 priv->ClientComputerName =
nullptr;
481 priv->ClientComputerName =
482 Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen /
sizeof(WCHAR),
nullptr);
483 if (!priv->ClientComputerName)
485 WLog_Print(priv->log, WLOG_ERROR,
"failed to convert client computer name");
486 return ERROR_INVALID_DATA;
491 const char* name = Stream_ConstPointer(s);
492 priv->ClientComputerName = _strdup(name);
493 Stream_Seek(s, ComputerNameLen);
495 if (!priv->ClientComputerName)
497 WLog_Print(priv->log, WLOG_ERROR,
"failed to duplicate client computer name");
498 return CHANNEL_RC_NO_MEMORY;
502 WLog_Print(priv->log, WLOG_DEBUG,
"ClientComputerName: %s", priv->ClientComputerName);
503 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
504 priv->ClientComputerName);
508static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context,
wStream* s,
511 WINPR_ASSERT(context);
512 WINPR_ASSERT(context->priv);
514 RdpdrServerPrivate* priv = context->priv;
515 UINT error = rdpdr_write_capset_header(priv->log, s, header);
516 if (error != CHANNEL_RC_OK)
519 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0,
nullptr);
528static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context,
wStream* s,
531 WINPR_ASSERT(context);
532 WINPR_ASSERT(context->priv);
533 WINPR_ASSERT(header);
535 RdpdrServerPrivate* priv = context->priv;
537 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
538 return ERROR_INVALID_DATA;
540 const UINT32 OsType = Stream_Get_UINT32(s);
542 const UINT32 OsVersion = Stream_Get_UINT32(s);
544 const UINT32 VersionMajor = Stream_Get_UINT16(s);
545 const UINT32 VersionMinor = Stream_Get_UINT16(s);
546 const UINT32 IoCode1 = Stream_Get_UINT32(s);
547 const UINT32 IoCode2 = Stream_Get_UINT32(s);
549 const UINT32 ExtendedPdu = Stream_Get_UINT32(s);
550 const UINT32 ExtraFlags1 = Stream_Get_UINT32(s);
551 const UINT32 ExtraFlags2 = Stream_Get_UINT32(s);
555 char buffer[1024] = WINPR_C_ARRAY_INIT;
556 WLog_Print(priv->log, WLOG_TRACE,
557 "OsType=%" PRIu32
", OsVersion=%" PRIu32
", VersionMajor=%" PRIu32
558 ", VersionMinor=%" PRIu32
", IoCode1=%s, IoCode2=%" PRIu32
559 ", ExtendedPdu=%" PRIu32
", ExtraFlags1=%" PRIu32
", ExtraFlags2=%" PRIu32,
560 OsType, OsVersion, VersionMajor, VersionMinor,
561 rdpdr_irp_mask2str(IoCode1, buffer,
sizeof(buffer)), IoCode2, ExtendedPdu,
562 ExtraFlags1, ExtraFlags2);
565 if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
567 WLog_Print(priv->log, WLOG_ERROR,
"unsupported RDPDR version %" PRIu16
".%" PRIu16,
568 VersionMajor, VersionMinor);
569 return ERROR_INVALID_DATA;
572 switch (VersionMinor)
574 case RDPDR_MINOR_RDP_VERSION_13:
575 case RDPDR_MINOR_RDP_VERSION_6_X:
576 case RDPDR_MINOR_RDP_VERSION_5_2:
577 case RDPDR_MINOR_RDP_VERSION_5_1:
578 case RDPDR_MINOR_RDP_VERSION_5_0:
581 WLog_Print(priv->log, WLOG_WARN,
"unsupported RDPDR minor version %" PRIu16
".%" PRIu16,
582 VersionMajor, VersionMinor);
586 UINT32 SpecialTypeDeviceCap = 0;
587 if (header->Version == GENERAL_CAPABILITY_VERSION_02)
589 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
590 return ERROR_INVALID_DATA;
592 SpecialTypeDeviceCap = Stream_Get_UINT32(s);
594 priv->SpecialDeviceTypeCap = SpecialTypeDeviceCap;
597 RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ |
598 RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN |
599 RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION |
600 RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION |
601 RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL;
603 if ((IoCode1 & mask) == 0)
605 char buffer[1024] = WINPR_C_ARRAY_INIT;
606 WLog_Print(priv->log, WLOG_ERROR,
"Missing IRP mask values %s",
607 rdpdr_irp_mask2str(IoCode1 & mask, buffer,
sizeof(buffer)));
608 return ERROR_INVALID_DATA;
610 priv->IoCode1 = IoCode1;
614 WLog_Print(priv->log, WLOG_WARN,
615 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ioCode2 is "
616 "reserved for future use, expected value 0 got %" PRIu32,
620 if ((ExtendedPdu & RDPDR_CLIENT_DISPLAY_NAME_PDU) == 0)
622 WLog_Print(priv->log, WLOG_WARN,
623 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) extendedPDU "
624 "should always set RDPDR_CLIENT_DISPLAY_NAME_PDU[0x00000002]");
627 priv->ExtendedPDU = ExtendedPdu;
628 priv->UserLoggedOnPdu = (ExtendedPdu & RDPDR_USER_LOGGEDON_PDU) != 0;
630 if (ExtraFlags2 != 0)
632 WLog_Print(priv->log, WLOG_WARN,
633 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ExtraFlags2 is "
634 "reserved for future use, expected value 0 got %" PRIu32,
638 return CHANNEL_RC_OK;
647static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context,
wStream* s)
649 WINPR_ASSERT(context);
650 WINPR_ASSERT(context->priv);
653 GENERAL_CAPABILITY_VERSION_02 };
656 ioCode1 |= RDPDR_IRP_MJ_CREATE;
657 ioCode1 |= RDPDR_IRP_MJ_CLEANUP;
658 ioCode1 |= RDPDR_IRP_MJ_CLOSE;
659 ioCode1 |= RDPDR_IRP_MJ_READ;
660 ioCode1 |= RDPDR_IRP_MJ_WRITE;
661 ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS;
662 ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN;
663 ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL;
664 ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION;
665 ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION;
666 ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION;
667 ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION;
668 ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL;
669 ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL;
670 ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY;
671 ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY;
673 UINT32 extendedPdu = 0;
674 extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU;
675 extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS;
677 RdpdrServerPrivate* priv = context->priv;
678 if (priv->UserLoggedOnPdu)
679 extendedPdu |= RDPDR_USER_LOGGEDON_PDU;
681 UINT32 extraFlags1 = 0;
682 extraFlags1 |= ENABLE_ASYNCIO;
683 UINT32 SpecialTypeDeviceCap = 0;
685 UINT error = rdpdr_write_capset_header(priv->log, s, &header);
686 if (error != CHANNEL_RC_OK)
689 const BYTE* data = Stream_ConstPointer(s);
690 const size_t start = Stream_GetPosition(s);
691 Stream_Write_UINT32(s, 0);
692 Stream_Write_UINT32(s, 0);
693 Stream_Write_UINT16(s, priv->VersionMajor);
694 Stream_Write_UINT16(s, priv->VersionMinor);
695 Stream_Write_UINT32(s, ioCode1);
696 Stream_Write_UINT32(s, 0);
697 Stream_Write_UINT32(s, extendedPdu);
698 Stream_Write_UINT32(s, extraFlags1);
701 Stream_Write_UINT32(s, SpecialTypeDeviceCap);
702 const size_t end = Stream_GetPosition(s);
703 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
712static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context,
wStream* s,
715 WINPR_ASSERT(context);
716 WINPR_ASSERT(context->priv);
718 WINPR_ASSERT(header);
719 WINPR_UNUSED(context);
720 WINPR_UNUSED(header);
723 return CHANNEL_RC_OK;
732static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context,
wStream* s)
734 WINPR_UNUSED(context);
735 WINPR_ASSERT(context);
736 WINPR_ASSERT(context->priv);
739 PRINT_CAPABILITY_VERSION_01 };
741 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
750static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context,
wStream* s,
753 WINPR_UNUSED(context);
755 WINPR_UNUSED(header);
756 WINPR_ASSERT(context);
757 WINPR_ASSERT(context->priv);
759 return CHANNEL_RC_OK;
768static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
wStream* s)
770 WINPR_UNUSED(context);
771 WINPR_ASSERT(context);
772 WINPR_ASSERT(context->priv);
775 PORT_CAPABILITY_VERSION_01 };
777 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
786static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
wStream* s,
789 WINPR_ASSERT(context);
790 WINPR_ASSERT(context->priv);
791 WINPR_UNUSED(context);
792 WINPR_UNUSED(header);
795 return CHANNEL_RC_OK;
804static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
wStream* s)
806 WINPR_ASSERT(context);
807 WINPR_ASSERT(context->priv);
808 WINPR_UNUSED(context);
811 DRIVE_CAPABILITY_VERSION_02 };
813 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
822static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context,
wStream* s,
825 WINPR_ASSERT(context);
826 WINPR_ASSERT(context->priv);
827 WINPR_UNUSED(context);
828 WINPR_UNUSED(header);
831 return CHANNEL_RC_OK;
840static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context,
wStream* s)
842 WINPR_ASSERT(context);
843 WINPR_ASSERT(context->priv);
844 WINPR_UNUSED(context);
847 SMARTCARD_CAPABILITY_VERSION_01 };
849 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
858static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
860 WINPR_ASSERT(context);
861 WINPR_ASSERT(context->priv);
863 UINT16 numCapabilities = 1;
864 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
867 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
868 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
871 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
874 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
877 RdpdrServerPrivate* priv = context->priv;
878 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 512);
881 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
882 return CHANNEL_RC_NO_MEMORY;
886 .Component = RDPDR_CTYP_CORE,
887 .PacketId = PAKID_CORE_SERVER_CAPABILITY,
889 Stream_Write_UINT16(s, header.
Component);
890 Stream_Write_UINT16(s, header.
PacketId);
891 Stream_Write_UINT16(s, numCapabilities);
892 Stream_Write_UINT16(s, 0);
895 if ((error = rdpdr_server_write_general_capability_set(context, s)))
897 WLog_Print(priv->log, WLOG_ERROR,
898 "rdpdr_server_write_general_capability_set failed with error %" PRIu32
"!",
903 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
905 if ((error = rdpdr_server_write_drive_capability_set(context, s)))
907 WLog_Print(priv->log, WLOG_ERROR,
908 "rdpdr_server_write_drive_capability_set failed with error %" PRIu32
"!",
914 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
915 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
917 if ((error = rdpdr_server_write_port_capability_set(context, s)))
919 WLog_Print(priv->log, WLOG_ERROR,
920 "rdpdr_server_write_port_capability_set failed with error %" PRIu32
"!",
926 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
928 if ((error = rdpdr_server_write_printer_capability_set(context, s)))
930 WLog_Print(priv->log, WLOG_ERROR,
931 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
937 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
939 if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
941 WLog_Print(priv->log, WLOG_ERROR,
942 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
948 return rdpdr_seal_send_free_request(context, s);
955static UINT16 rdpdr_cap_type_to_dtyp(UINT16 capabilityType)
957 switch (capabilityType)
959 case CAP_PRINTER_TYPE:
960 return RDPDR_DTYP_PRINT;
962 return RDPDR_DTYP_SERIAL | RDPDR_DTYP_PARALLEL;
964 return RDPDR_DTYP_FILESYSTEM;
965 case CAP_SMARTCARD_TYPE:
966 return RDPDR_DTYP_SMARTCARD;
967 case CAP_GENERAL_TYPE:
979static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context,
wStream* s,
982 WINPR_ASSERT(context);
983 WINPR_ASSERT(context->priv);
985 RdpdrServerPrivate* priv = context->priv;
987 WINPR_UNUSED(header);
989 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
990 return ERROR_INVALID_DATA;
992 const UINT16 numCapabilities = Stream_Get_UINT16(s);
993 Stream_Seek_UINT16(s);
996 for (UINT16 i = 0; i < numCapabilities; i++)
999 const size_t start = Stream_GetPosition(s);
1002 if ((status = rdpdr_read_capset_header(priv->log, s, &capabilityHeader)))
1004 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1008 status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
1009 Stream_GetRemainingLength(s), Stream_ConstPointer(s));
1010 if (status != CHANNEL_RC_OK)
1013 switch (capabilityHeader.CapabilityType)
1015 case CAP_GENERAL_TYPE:
1017 rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
1019 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1025 case CAP_PRINTER_TYPE:
1027 rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
1029 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1036 if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
1038 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1044 case CAP_DRIVE_TYPE:
1046 rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
1048 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1054 case CAP_SMARTCARD_TYPE:
1056 rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
1058 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1065 WLog_Print(priv->log, WLOG_WARN,
"Unknown capabilityType %" PRIu16
"",
1066 capabilityHeader.CapabilityType);
1067 Stream_Seek(s, capabilityHeader.CapabilityLength);
1068 return ERROR_INVALID_DATA;
1071 const UINT16 client_dtyp = rdpdr_cap_type_to_dtyp(capabilityHeader.CapabilityType);
1072 if ((client_dtyp != 0) && ((client_dtyp & context->supported) == 0))
1074 WLog_Print(priv->log, WLOG_WARN,
"client sent capability %s we did not announce!",
1075 rdpdr_cap_type_string(capabilityHeader.CapabilityType));
1077 caps |= client_dtyp;
1079 const size_t end = Stream_GetPosition(s);
1080 const size_t diff = end - start;
1081 if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
1083 WLog_Print(priv->log, WLOG_WARN,
1084 "{capability %s[0x%04" PRIx16
"]} processed %" PRIuz
1085 " bytes, but expected to be %" PRIu16,
1086 rdpdr_cap_type_string(capabilityHeader.CapabilityType),
1087 capabilityHeader.CapabilityType, diff, capabilityHeader.CapabilityLength);
1092 context->supported &= caps;
1094 return CHANNEL_RC_OK;
1103static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
1105 WINPR_ASSERT(context);
1106 WINPR_ASSERT(context->priv);
1108 RdpdrServerPrivate* priv = context->priv;
1109 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
1112 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1113 return CHANNEL_RC_NO_MEMORY;
1118 .PacketId = PAKID_CORE_CLIENTID_CONFIRM,
1120 Stream_Write_UINT16(s, header.
Component);
1121 Stream_Write_UINT16(s, header.
PacketId);
1122 Stream_Write_UINT16(s, priv->VersionMajor);
1123 Stream_Write_UINT16(s, priv->VersionMinor);
1124 Stream_Write_UINT32(s, priv->ClientId);
1125 return rdpdr_seal_send_free_request(context, s);
1134static UINT rdpdr_server_send_device_reply(RdpdrServerContext* context, UINT32 deviceId,
1137 WINPR_ASSERT(context);
1138 WINPR_ASSERT(context->priv);
1140 RdpdrServerPrivate* priv = context->priv;
1141 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
1144 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1145 return CHANNEL_RC_NO_MEMORY;
1150 .PacketId = PAKID_CORE_DEVICE_REPLY,
1152 Stream_Write_UINT16(s, header.
Component);
1153 Stream_Write_UINT16(s, header.
PacketId);
1154 Stream_Write_UINT32(s, deviceId);
1155 Stream_Write_UINT32(s, resultCode);
1156 return rdpdr_seal_send_free_request(context, s);
1165static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context,
1169 WINPR_ASSERT(context);
1170 WINPR_ASSERT(context->priv);
1172 RdpdrServerPrivate* priv = context->priv;
1174 WINPR_UNUSED(header);
1176 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1177 return ERROR_INVALID_DATA;
1179 const UINT32 DeviceCount = Stream_Get_UINT32(s);
1180 WLog_Print(priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1182 for (UINT32 i = 0; i < DeviceCount; i++)
1184 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
1185 return ERROR_INVALID_DATA;
1188 device.DeviceType = Stream_Get_UINT32(s);
1189 device.DeviceId = Stream_Get_UINT32(s);
1190 Stream_Read(s, device.PreferredDosName, 8);
1191 device.DeviceDataLength = Stream_Get_UINT32(s);
1192 device.DeviceData = Stream_PointerAs(s, BYTE);
1194 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, device.DeviceDataLength))
1195 return ERROR_INVALID_DATA;
1197 if (!rdpdr_add_device(context->priv, &device))
1198 return ERROR_INTERNAL_ERROR;
1200 UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
1201 if (error != CHANNEL_RC_OK)
1204 error = ERROR_NOT_SUPPORTED;
1205 switch (device.DeviceType)
1207 case RDPDR_DTYP_FILESYSTEM:
1208 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1209 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
1212 case RDPDR_DTYP_PRINT:
1213 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1214 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
1217 case RDPDR_DTYP_SERIAL:
1218 if (device.DeviceDataLength != 0)
1220 WLog_Print(priv->log, WLOG_WARN,
1221 "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32
"]",
1222 device.DeviceDataLength);
1223 error = ERROR_INVALID_DATA;
1225 else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1227 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
1230 case RDPDR_DTYP_PARALLEL:
1231 if (device.DeviceDataLength != 0)
1233 WLog_Print(priv->log, WLOG_WARN,
1234 "[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32
"]",
1235 device.DeviceDataLength);
1236 error = ERROR_INVALID_DATA;
1238 else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1239 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
1243 case RDPDR_DTYP_SMARTCARD:
1244 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1246 priv->smartcardDeviceId = device.DeviceId;
1247 priv->haveSmartcardDevice = TRUE;
1249 IFCALLRESULT(STATUS_SUCCESS, context->OnSmartcardCreate, context, &device);
1254 WLog_Print(priv->log, WLOG_WARN,
1255 "[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
1256 "(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
1257 " at position %" PRIu32,
1258 device.DeviceType, i);
1259 error = ERROR_INVALID_DATA;
1263 Stream_Seek(s, device.DeviceDataLength);
1265 error = rdpdr_server_send_device_reply(context, device.DeviceId, error);
1266 if (error != CHANNEL_RC_OK)
1270 return CHANNEL_RC_OK;
1279static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context,
wStream* s,
1282 WINPR_ASSERT(context);
1283 WINPR_ASSERT(context->priv);
1285 RdpdrServerPrivate* priv = context->priv;
1287 WINPR_UNUSED(header);
1289 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1290 return ERROR_INVALID_DATA;
1292 const UINT32 DeviceCount = Stream_Get_UINT32(s);
1293 WLog_Print(priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1295 for (UINT32 i = 0; i < DeviceCount; i++)
1300 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1301 return ERROR_INVALID_DATA;
1303 const UINT32 DeviceId = Stream_Get_UINT32(s);
1304 device = rdpdr_get_device_by_id(context->priv, DeviceId);
1305 WLog_Print(priv->log, WLOG_DEBUG,
"Device %" PRIu32
" Id: 0x%08" PRIX32
"", i, DeviceId);
1306 UINT32 DeviceType = 0;
1308 DeviceType = device->DeviceType;
1311 IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
1312 if (error != CHANNEL_RC_OK)
1317 case RDPDR_DTYP_FILESYSTEM:
1318 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1319 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
1322 case RDPDR_DTYP_PRINT:
1323 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1325 IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
1328 case RDPDR_DTYP_SERIAL:
1329 if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1331 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
1334 case RDPDR_DTYP_PARALLEL:
1335 if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1336 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
1340 case RDPDR_DTYP_SMARTCARD:
1341 if (priv->haveSmartcardDevice)
1343 priv->haveSmartcardDevice = FALSE;
1344 priv->smartcardDeviceId = 0;
1346 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1348 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
1355 if (error != CHANNEL_RC_OK)
1358 if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
1359 return ERROR_INVALID_DATA;
1362 return CHANNEL_RC_OK;
1366static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
wStream* s,
1367 WINPR_ATTR_UNUSED UINT32 DeviceId,
1368 WINPR_ATTR_UNUSED UINT32 FileId,
1369 WINPR_ATTR_UNUSED UINT32 CompletionId)
1371 WINPR_ASSERT(context);
1373 RdpdrServerPrivate* priv = context->priv;
1374 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1375 return ERROR_INVALID_DATA;
1377 WINPR_ATTR_UNUSED
const UINT32 DesiredAccess = Stream_Get_UINT32(s);
1378 WINPR_ATTR_UNUSED
const UINT32 AllocationSize = Stream_Get_UINT32(s);
1379 WINPR_ATTR_UNUSED
const UINT32 FileAttributes = Stream_Get_UINT32(s);
1380 WINPR_ATTR_UNUSED
const UINT32 SharedAccess = Stream_Get_UINT32(s);
1381 WINPR_ATTR_UNUSED
const UINT32 CreateDisposition = Stream_Get_UINT32(s);
1382 WINPR_ATTR_UNUSED
const UINT32 CreateOptions = Stream_Get_UINT32(s);
1383 const UINT32 PathLength = Stream_Get_UINT32(s);
1385 const WCHAR* path = rdpdr_read_ustring(priv->log, s, PathLength);
1386 if (!path && (PathLength > 0))
1387 return ERROR_INVALID_DATA;
1389 WLog_Print(priv->log, WLOG_WARN,
1390 "[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
1391 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1393 return CHANNEL_RC_OK;
1397static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context,
wStream* s,
1398 WINPR_ATTR_UNUSED UINT32 DeviceId,
1399 WINPR_ATTR_UNUSED UINT32 FileId,
1400 WINPR_ATTR_UNUSED UINT32 CompletionId)
1402 WINPR_ASSERT(context);
1403 WINPR_ASSERT(context->priv);
1405 RdpdrServerPrivate* priv = context->priv;
1407 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1408 return ERROR_INVALID_DATA;
1412 WLog_Print(priv->log, WLOG_WARN,
1413 "[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
1414 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1416 return CHANNEL_RC_OK;
1420static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context,
wStream* s,
1421 WINPR_ATTR_UNUSED UINT32 DeviceId,
1422 WINPR_ATTR_UNUSED UINT32 FileId,
1423 WINPR_ATTR_UNUSED UINT32 CompletionId)
1425 WINPR_ASSERT(context);
1426 WINPR_ASSERT(context->priv);
1428 RdpdrServerPrivate* priv = context->priv;
1429 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1430 return ERROR_INVALID_DATA;
1432 const UINT32 Length = Stream_Get_UINT32(s);
1433 const UINT64 Offset = Stream_Get_UINT64(s);
1436 WLog_Print(priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32, Offset,
1439 WLog_Print(priv->log, WLOG_WARN,
1440 "[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
1441 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1443 return CHANNEL_RC_OK;
1447static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context,
wStream* s,
1448 WINPR_ATTR_UNUSED UINT32 DeviceId,
1449 WINPR_ATTR_UNUSED UINT32 FileId,
1450 WINPR_ATTR_UNUSED UINT32 CompletionId)
1452 WINPR_ASSERT(context);
1453 WINPR_ASSERT(context->priv);
1455 RdpdrServerPrivate* priv = context->priv;
1457 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1458 return ERROR_INVALID_DATA;
1460 const UINT32 Length = Stream_Get_UINT32(s);
1461 const UINT64 Offset = Stream_Get_UINT64(s);
1464 WLog_Print(priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32, Offset,
1467 const BYTE* data = Stream_ConstPointer(s);
1468 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1469 return ERROR_INVALID_DATA;
1470 Stream_Seek(s, Length);
1472 WLog_Print(priv->log, WLOG_WARN,
1473 "[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
1474 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)data);
1476 return CHANNEL_RC_OK;
1480static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* context,
wStream* s,
1481 WINPR_ATTR_UNUSED UINT32 DeviceId,
1482 WINPR_ATTR_UNUSED UINT32 FileId,
1483 WINPR_ATTR_UNUSED UINT32 CompletionId)
1485 WINPR_ASSERT(context);
1486 WINPR_ASSERT(context->priv);
1488 RdpdrServerPrivate* priv = context->priv;
1490 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1491 return ERROR_INVALID_DATA;
1493 WINPR_ATTR_UNUSED
const UINT32 OutputBufferLength = Stream_Get_UINT32(s);
1494 WINPR_ATTR_UNUSED
const UINT32 InputBufferLength = Stream_Get_UINT32(s);
1495 WINPR_ATTR_UNUSED
const UINT32 IoControlCode = Stream_Get_UINT32(s);
1498 const BYTE* InputBuffer = Stream_ConstPointer(s);
1499 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, InputBufferLength))
1500 return ERROR_INVALID_DATA;
1501 Stream_Seek(s, InputBufferLength);
1503 WLog_Print(priv->log, WLOG_WARN,
1504 "[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
1505 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p [%" PRIu32
"], OutputBufferLength=%" PRIu32,
1506 (
const void*)InputBuffer, InputBufferLength, OutputBufferLength);
1508 return CHANNEL_RC_OK;
1512static UINT rdpdr_server_receive_io_query_volume_information_request(
1513 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1514 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1516 WINPR_ASSERT(context);
1518 RdpdrServerPrivate* priv = context->priv;
1519 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1520 return ERROR_INVALID_DATA;
1522 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1523 const UINT32 Length = Stream_Get_UINT32(s);
1526 WLog_Print(priv->log, WLOG_DEBUG,
1527 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1528 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1530 const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
1531 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1532 return ERROR_INVALID_DATA;
1533 Stream_Seek(s, Length);
1535 WLog_Print(priv->log, WLOG_WARN,
1536 "[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
1537 "(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
1538 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryVolumeBuffer);
1540 return CHANNEL_RC_OK;
1544static UINT rdpdr_server_receive_io_set_volume_information_request(
1545 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1546 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1548 WINPR_ASSERT(context);
1549 WINPR_ASSERT(context->priv);
1551 RdpdrServerPrivate* priv = context->priv;
1553 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1554 return ERROR_INVALID_DATA;
1556 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1557 const UINT32 Length = Stream_Get_UINT32(s);
1560 WLog_Print(priv->log, WLOG_DEBUG,
1561 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1562 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1564 const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
1565 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1566 return ERROR_INVALID_DATA;
1567 Stream_Seek(s, Length);
1569 WLog_Print(priv->log, WLOG_WARN,
1570 "[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
1571 "(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
1572 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetVolumeBuffer);
1574 return CHANNEL_RC_OK;
1578static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext* context,
1580 WINPR_ATTR_UNUSED UINT32 DeviceId,
1581 WINPR_ATTR_UNUSED UINT32 FileId,
1582 WINPR_ATTR_UNUSED UINT32 CompletionId)
1584 WINPR_ASSERT(context);
1585 WINPR_ASSERT(context->priv);
1587 RdpdrServerPrivate* priv = context->priv;
1589 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1590 return ERROR_INVALID_DATA;
1592 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1593 const UINT32 Length = Stream_Get_UINT32(s);
1596 WLog_Print(priv->log, WLOG_DEBUG,
1597 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1598 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1600 const BYTE* QueryBuffer = Stream_ConstPointer(s);
1601 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1602 return ERROR_INVALID_DATA;
1603 Stream_Seek(s, Length);
1605 WLog_Print(priv->log, WLOG_WARN,
1606 "[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
1607 "(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
1608 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryBuffer);
1610 return CHANNEL_RC_OK;
1614static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext* context,
wStream* s,
1615 WINPR_ATTR_UNUSED UINT32 DeviceId,
1616 WINPR_ATTR_UNUSED UINT32 FileId,
1617 WINPR_ATTR_UNUSED UINT32 CompletionId)
1619 WINPR_ASSERT(context);
1620 WINPR_ASSERT(context->priv);
1622 RdpdrServerPrivate* priv = context->priv;
1624 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1625 return ERROR_INVALID_DATA;
1627 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1628 const UINT32 Length = Stream_Get_UINT32(s);
1631 WLog_Print(priv->log, WLOG_DEBUG,
1632 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1633 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1635 const BYTE* SetBuffer = Stream_ConstPointer(s);
1636 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1637 return ERROR_INVALID_DATA;
1638 Stream_Seek(s, Length);
1640 WLog_Print(priv->log, WLOG_WARN,
1641 "[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
1642 "(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
1643 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetBuffer);
1645 return CHANNEL_RC_OK;
1649static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext* context,
wStream* s,
1650 WINPR_ATTR_UNUSED UINT32 DeviceId,
1651 WINPR_ATTR_UNUSED UINT32 FileId,
1652 WINPR_ATTR_UNUSED UINT32 CompletionId)
1654 WINPR_ASSERT(context);
1655 WINPR_ASSERT(context->priv);
1657 RdpdrServerPrivate* priv = context->priv;
1659 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1660 return ERROR_INVALID_DATA;
1662 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1663 const BYTE InitialQuery = Stream_Get_UINT8(s);
1664 const UINT32 PathLength = Stream_Get_UINT32(s);
1667 const WCHAR* wPath = rdpdr_read_ustring(priv->log, s, PathLength);
1668 if (!wPath && (PathLength > 0))
1669 return ERROR_INVALID_DATA;
1671 char* Path = ConvertWCharNToUtf8Alloc(wPath, PathLength /
sizeof(WCHAR),
nullptr);
1672 WLog_Print(priv->log, WLOG_DEBUG,
1673 "Got FSInformationClass %s [0x%08" PRIx32
"], InitialQuery [%" PRIu8
1674 "] Path[%" PRIu32
"] %s",
1675 FSInformationClass2Tag(FsInformationClass), FsInformationClass, InitialQuery,
1679 WLog_Print(priv->log, WLOG_WARN,
1680 "[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
1681 "(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
1682 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1684 return CHANNEL_RC_OK;
1688static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext* context,
1690 WINPR_ATTR_UNUSED UINT32 DeviceId,
1691 WINPR_ATTR_UNUSED UINT32 FileId,
1692 WINPR_ATTR_UNUSED UINT32 CompletionId)
1694 WINPR_ASSERT(context);
1695 WINPR_ASSERT(context->priv);
1697 RdpdrServerPrivate* priv = context->priv;
1699 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1700 return ERROR_INVALID_DATA;
1702 WINPR_ATTR_UNUSED
const BYTE WatchTree = Stream_Get_UINT8(s);
1703 WINPR_ATTR_UNUSED
const UINT32 CompletionFilter = Stream_Get_UINT32(s);
1706 WLog_Print(priv->log, WLOG_WARN,
1707 "[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
1708 "(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
1709 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1711 return CHANNEL_RC_OK;
1715static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext* context,
1717 UINT32 FileId, UINT32 CompletionId,
1718 UINT32 MinorFunction)
1720 WINPR_ASSERT(context);
1721 WINPR_ASSERT(context->priv);
1723 RdpdrServerPrivate* priv = context->priv;
1724 switch (MinorFunction)
1726 case IRP_MN_QUERY_DIRECTORY:
1727 return rdpdr_server_receive_io_query_directory_request(context, s, DeviceId, FileId,
1729 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
1730 return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
1733 WLog_Print(priv->log, WLOG_WARN,
1734 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
1735 "MajorFunction=%s, MinorFunction=%08" PRIx32
" is not supported",
1736 rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
1737 return ERROR_INVALID_DATA;
1742static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* context,
wStream* s,
1743 WINPR_ATTR_UNUSED UINT32 DeviceId,
1744 WINPR_ATTR_UNUSED UINT32 FileId,
1745 WINPR_ATTR_UNUSED UINT32 CompletionId)
1747 WINPR_ASSERT(context);
1748 WINPR_ASSERT(context->priv);
1750 RdpdrServerPrivate* priv = context->priv;
1752 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1753 return ERROR_INVALID_DATA;
1755 const uint32_t Operation = Stream_Get_UINT32(s);
1756 uint32_t Lock = Stream_Get_UINT32(s);
1757 const uint32_t NumLocks = Stream_Get_UINT32(s);
1760 WLog_Print(priv->log, WLOG_DEBUG,
1761 "IRP_MJ_LOCK_CONTROL, Operation=%s, Lock=0x%08" PRIx32
", NumLocks=%" PRIu32,
1762 DR_DRIVE_LOCK_REQ2str(Operation), Lock, NumLocks);
1766 for (UINT32 x = 0; x < NumLocks; x++)
1768 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 16))
1769 return ERROR_INVALID_DATA;
1771 const UINT64 Length = Stream_Get_UINT64(s);
1772 const UINT64 Offset = Stream_Get_UINT64(s);
1774 WLog_Print(priv->log, WLOG_DEBUG,
"Locking at Offset=0x%08" PRIx64
" [Length %" PRIu64
"]",
1778 WLog_Print(priv->log, WLOG_WARN,
1779 "[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
1780 "[Lock=0x%08" PRIx32
"]"
1783 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1785 return CHANNEL_RC_OK;
1789static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
wStream* s,
1792 WINPR_ASSERT(context);
1793 WINPR_ASSERT(context->priv);
1794 WINPR_ASSERT(header);
1796 RdpdrServerPrivate* priv = context->priv;
1798 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
1799 return ERROR_INVALID_DATA;
1801 const UINT32 DeviceId = Stream_Get_UINT32(s);
1802 const UINT32 FileId = Stream_Get_UINT32(s);
1803 const UINT32 CompletionId = Stream_Get_UINT32(s);
1804 const UINT32 MajorFunction = Stream_Get_UINT32(s);
1805 const UINT32 MinorFunction = Stream_Get_UINT32(s);
1806 if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
1807 WLog_Print(priv->log, WLOG_WARN,
1808 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
1809 "MinorFunction=0x%08" PRIx32
" != 0",
1810 rdpdr_irp_string(MajorFunction), MinorFunction);
1812 switch (MajorFunction)
1815 return rdpdr_server_receive_io_create_request(context, s, DeviceId, FileId,
1818 return rdpdr_server_receive_io_close_request(context, s, DeviceId, FileId,
1821 return rdpdr_server_receive_io_read_request(context, s, DeviceId, FileId, CompletionId);
1823 return rdpdr_server_receive_io_write_request(context, s, DeviceId, FileId,
1825 case IRP_MJ_DEVICE_CONTROL:
1826 return rdpdr_server_receive_io_device_control_request(context, s, DeviceId, FileId,
1828 case IRP_MJ_QUERY_VOLUME_INFORMATION:
1829 return rdpdr_server_receive_io_query_volume_information_request(context, s, DeviceId,
1830 FileId, CompletionId);
1831 case IRP_MJ_QUERY_INFORMATION:
1832 return rdpdr_server_receive_io_query_information_request(context, s, DeviceId, FileId,
1834 case IRP_MJ_SET_INFORMATION:
1835 return rdpdr_server_receive_io_set_information_request(context, s, DeviceId, FileId,
1837 case IRP_MJ_DIRECTORY_CONTROL:
1838 return rdpdr_server_receive_io_directory_control_request(context, s, DeviceId, FileId,
1839 CompletionId, MinorFunction);
1840 case IRP_MJ_LOCK_CONTROL:
1841 return rdpdr_server_receive_io_lock_control_request(context, s, DeviceId, FileId,
1843 case IRP_MJ_SET_VOLUME_INFORMATION:
1844 return rdpdr_server_receive_io_set_volume_information_request(context, s, DeviceId,
1845 FileId, CompletionId);
1849 priv->log, WLOG_WARN,
1850 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
1851 WLog_Print(priv->log, WLOG_WARN,
1852 "got DeviceId=0x%08" PRIx32
", FileId=0x%08" PRIx32
1853 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
1854 ", MinorFunction=0x%08" PRIx32,
1855 DeviceId, FileId, CompletionId, MajorFunction, MinorFunction);
1856 return ERROR_INVALID_DATA;
1866static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context,
wStream* s,
1869 WINPR_ASSERT(context);
1870 WINPR_ASSERT(context->priv);
1872 WINPR_ASSERT(header);
1874 RdpdrServerPrivate* priv = context->priv;
1876 WINPR_UNUSED(header);
1878 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
1879 return ERROR_INVALID_DATA;
1881 const UINT32 deviceId = Stream_Get_UINT32(s);
1882 const UINT32 completionId = Stream_Get_UINT32(s);
1883 const UINT32 ioStatus = Stream_Get_UINT32(s);
1884 WLog_Print(priv->log, WLOG_DEBUG,
1885 "deviceId=%" PRIu32
", completionId=0x%" PRIx32
", ioStatus=0x%" PRIx32
"", deviceId,
1886 completionId, ioStatus);
1887 RDPDR_IRP* irp = rdpdr_server_dequeue_irp(context, completionId);
1891 WLog_Print(priv->log, WLOG_ERROR,
"IRP not found for completionId=0x%" PRIx32
"",
1893 return CHANNEL_RC_OK;
1897 UINT error = CHANNEL_RC_OK;
1900 error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
1912static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
1914 WINPR_ASSERT(context);
1915 WINPR_ASSERT(context->priv);
1917 RdpdrServerPrivate* priv = context->priv;
1918 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH);
1921 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1922 return CHANNEL_RC_NO_MEMORY;
1927 .PacketId = PAKID_CORE_USER_LOGGEDON,
1929 Stream_Write_UINT16(s, header.
Component);
1930 Stream_Write_UINT16(s, header.
PacketId);
1931 return rdpdr_seal_send_free_request(context, s);
1935static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context,
wStream* s)
1937 WINPR_ASSERT(context);
1938 WINPR_ASSERT(context->priv);
1940 RdpdrServerPrivate* priv = context->priv;
1942 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 24))
1943 return ERROR_INVALID_DATA;
1945 char PortDosName[9] = WINPR_C_ARRAY_INIT;
1946 Stream_Read(s, PortDosName, 8);
1947 const UINT32 PnPNameLen = Stream_Get_UINT32(s);
1948 const UINT32 DriverNameLen = Stream_Get_UINT32(s);
1949 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
1950 const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
1952 const WCHAR* PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
1953 if (!PnPName && (PnPNameLen > 0))
1954 return ERROR_INVALID_DATA;
1955 const WCHAR* DriverName = rdpdr_read_ustring(priv->log, s, DriverNameLen);
1956 if (!DriverName && (DriverNameLen > 0))
1957 return ERROR_INVALID_DATA;
1958 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
1959 if (!PrinterName && (PrinterNameLen > 0))
1960 return ERROR_INVALID_DATA;
1962 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
1963 return ERROR_INVALID_DATA;
1964 Stream_Seek(s, CachedFieldsLen);
1966 WLog_Print(priv->log, WLOG_WARN,
1967 "[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
1968 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1969 return CHANNEL_RC_OK;
1973static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context,
wStream* s)
1975 WINPR_ASSERT(context);
1977 RdpdrServerPrivate* priv = context->priv;
1979 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
1980 return ERROR_INVALID_DATA;
1982 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
1983 const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
1985 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
1986 if (!PrinterName && (PrinterNameLen > 0))
1987 return ERROR_INVALID_DATA;
1989 const BYTE* config = Stream_ConstPointer(s);
1990 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
1991 return ERROR_INVALID_DATA;
1992 Stream_Seek(s, CachedFieldsLen);
1995 priv->log, WLOG_WARN,
1996 "[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
1997 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)config);
1998 return CHANNEL_RC_OK;
2002static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context,
wStream* s)
2004 WINPR_ASSERT(context);
2005 WINPR_ASSERT(context->priv);
2007 RdpdrServerPrivate* priv = context->priv;
2009 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
2010 return ERROR_INVALID_DATA;
2012 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
2014 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
2015 if (!PrinterName && (PrinterNameLen > 0))
2016 return ERROR_INVALID_DATA;
2019 priv->log, WLOG_WARN,
2020 "[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
2021 WLog_Print(priv->log, WLOG_WARN,
"TODO");
2022 return CHANNEL_RC_OK;
2026static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context,
wStream* s)
2028 WINPR_ASSERT(context);
2029 WINPR_ASSERT(context->priv);
2031 RdpdrServerPrivate* priv = context->priv;
2033 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
2034 return ERROR_INVALID_DATA;
2036 const UINT32 OldPrinterNameLen = Stream_Get_UINT32(s);
2037 const UINT32 NewPrinterNameLen = Stream_Get_UINT32(s);
2039 const WCHAR* OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
2040 if (!OldPrinterName && (OldPrinterNameLen > 0))
2041 return ERROR_INVALID_DATA;
2042 const WCHAR* NewPrinterName = rdpdr_read_ustring(priv->log, s, NewPrinterNameLen);
2043 if (!NewPrinterName && (NewPrinterNameLen > 0))
2044 return ERROR_INVALID_DATA;
2047 priv->log, WLOG_WARN,
2048 "[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
2049 WLog_Print(priv->log, WLOG_WARN,
"TODO");
2050 return CHANNEL_RC_OK;
2055rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context,
wStream* s,
2058 WINPR_ASSERT(context);
2059 WINPR_ASSERT(context->priv);
2060 WINPR_ASSERT(header);
2062 RdpdrServerPrivate* priv = context->priv;
2063 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
2064 return ERROR_INVALID_DATA;
2066 const UINT32 EventId = Stream_Get_UINT32(s);
2069 case RDPDR_ADD_PRINTER_EVENT:
2070 return rdpdr_server_receive_prn_cache_add_printer(context, s);
2071 case RDPDR_UPDATE_PRINTER_EVENT:
2072 return rdpdr_server_receive_prn_cache_update_printer(context, s);
2073 case RDPDR_DELETE_PRINTER_EVENT:
2074 return rdpdr_server_receive_prn_cache_delete_printer(context, s);
2075 case RDPDR_RENAME_PRINTER_EVENT:
2076 return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
2078 WLog_Print(priv->log, WLOG_WARN,
2079 "[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
2080 return ERROR_INVALID_DATA;
2085static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context,
wStream* s,
2088 WINPR_ASSERT(context);
2089 WINPR_ASSERT(context->priv);
2090 WINPR_ASSERT(header);
2092 RdpdrServerPrivate* priv = context->priv;
2094 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
2095 return ERROR_INVALID_DATA;
2097 const UINT32 PrinterId = Stream_Get_UINT32(s);
2098 const UINT32 Flags = Stream_Get_UINT32(s);
2101 priv->log, WLOG_WARN,
2102 "[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
2103 WLog_Print(priv->log, WLOG_WARN,
"PrinterId=0x%08" PRIx32
", Flags=0x%08" PRIx32, PrinterId,
2105 return CHANNEL_RC_OK;
2114static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context,
wStream* s,
2117 UINT error = ERROR_INVALID_DATA;
2118 WINPR_ASSERT(context);
2119 WINPR_ASSERT(context->priv);
2121 WINPR_ASSERT(header);
2123 RdpdrServerPrivate* priv = context->priv;
2124 WLog_Print(priv->log, WLOG_DEBUG,
2125 "receiving message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
2129 if (header->
Component == RDPDR_CTYP_CORE)
2133 case PAKID_CORE_SERVER_ANNOUNCE:
2134 WLog_Print(priv->log, WLOG_ERROR,
2135 "[MS-RDPEFS] 2.2.2.2 Server Announce Request "
2136 "(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
2139 case PAKID_CORE_CLIENTID_CONFIRM:
2140 error = rdpdr_server_receive_announce_response(context, s, header);
2143 case PAKID_CORE_CLIENT_NAME:
2144 error = rdpdr_server_receive_client_name_request(context, s, header);
2145 if (error == CHANNEL_RC_OK)
2146 error = rdpdr_server_send_core_capability_request(context);
2147 if (error == CHANNEL_RC_OK)
2148 error = rdpdr_server_send_client_id_confirm(context);
2151 case PAKID_CORE_USER_LOGGEDON:
2152 WLog_Print(priv->log, WLOG_ERROR,
2153 "[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
2154 "must not be sent by a client!");
2157 case PAKID_CORE_SERVER_CAPABILITY:
2158 WLog_Print(priv->log, WLOG_ERROR,
2159 "[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
2160 "(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
2163 case PAKID_CORE_CLIENT_CAPABILITY:
2164 error = rdpdr_server_receive_core_capability_response(context, s, header);
2165 if (error == CHANNEL_RC_OK)
2167 if (priv->UserLoggedOnPdu)
2168 error = rdpdr_server_send_user_logged_on(context);
2173 case PAKID_CORE_DEVICELIST_ANNOUNCE:
2174 error = rdpdr_server_receive_device_list_announce_request(context, s, header);
2177 case PAKID_CORE_DEVICELIST_REMOVE:
2178 error = rdpdr_server_receive_device_list_remove_request(context, s, header);
2181 case PAKID_CORE_DEVICE_REPLY:
2182 WLog_Print(priv->log, WLOG_ERROR,
2183 "[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
2184 "(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
2187 case PAKID_CORE_DEVICE_IOREQUEST:
2188 error = rdpdr_server_receive_device_io_request(context, s, header);
2191 case PAKID_CORE_DEVICE_IOCOMPLETION:
2192 error = rdpdr_server_receive_device_io_completion(context, s, header);
2196 WLog_Print(priv->log, WLOG_WARN,
2197 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2199 rdpdr_packetid_string(header->
PacketId));
2203 else if (header->
Component == RDPDR_CTYP_PRN)
2207 case PAKID_PRN_CACHE_DATA:
2208 error = rdpdr_server_receive_prn_cache_data_request(context, s, header);
2211 case PAKID_PRN_USING_XPS:
2212 error = rdpdr_server_receive_prn_using_xps_request(context, s, header);
2216 WLog_Print(priv->log, WLOG_WARN,
2217 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2219 rdpdr_packetid_string(header->
PacketId));
2225 WLog_Print(priv->log, WLOG_WARN,
2226 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2228 rdpdr_packetid_string(header->
PacketId));
2231 return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
2235static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
2237 RdpdrServerContext* context = (RdpdrServerContext*)arg;
2239 WINPR_ASSERT(context);
2240 WINPR_ASSERT(context->priv);
2244 RdpdrServerPrivate* priv = context->priv;
2245 ChannelPduTracker* tracker = ChannelPduTracker_new(priv->ChannelHandle);
2249 void* buffer =
nullptr;
2250 HANDLE ChannelEvent =
nullptr;
2251 DWORD BytesReturned = 0;
2252 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
2255 WLog_Print(priv->log, WLOG_ERROR,
"error retrieving WTSVirtualEventHandle");
2259 if (BytesReturned !=
sizeof(HANDLE))
2261 WLog_Print(priv->log, WLOG_ERROR,
"invalid size for WTSVirtualEventHandle");
2262 WTSFreeMemory(buffer);
2266 ChannelEvent = *(HANDLE*)buffer;
2267 WTSFreeMemory(buffer);
2269 if ((error = rdpdr_server_send_announce_request(context)))
2271 WLog_Print(priv->log, WLOG_ERROR,
2272 "rdpdr_server_send_announce_request failed with error %" PRIu32
"!", error);
2276 HANDLE events[2] = { priv->StopEvent, ChannelEvent };
2280 DWORD status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
2287 case WAIT_OBJECT_0 + 1:
2290 s = ChannelPduTracker_poll(tracker, &ok);
2296 if (Stream_GetRemainingLength(s) < RDPDR_HEADER_LENGTH)
2298 error = ERROR_INTERNAL_ERROR;
2304 .PacketId = Stream_Get_UINT16(s),
2307 if ((error = rdpdr_server_receive_pdu(context, s, &header)))
2309 WLog_Print(priv->log, WLOG_ERROR,
2310 "rdpdr_server_receive_pdu failed with error %" PRIu32
"!", error);
2319 error = GetLastError();
2320 WLog_Print(priv->log, WLOG_ERROR,
2321 "WaitForMultipleObjects failed with error %" PRIu32
"!", error);
2327 ChannelPduTracker_free(tracker);
2332 if (error && context->rdpcontext)
2333 setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
2345static UINT rdpdr_server_start(RdpdrServerContext* context)
2347 WINPR_ASSERT(context);
2348 WINPR_ASSERT(context->priv);
2350 PULONG pSessionId =
nullptr;
2351 DWORD BytesReturned = 0;
2353 if (!WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
2354 (LPSTR*)&pSessionId, &BytesReturned))
2355 return CHANNEL_RC_BAD_CHANNEL;
2357 DWORD SessionId = (DWORD)*pSessionId;
2358 WTSFreeMemory(pSessionId);
2360 RdpdrServerPrivate* priv = context->priv;
2361 priv->ChannelHandle =
2362 WTSVirtualChannelOpenEx(SessionId, RDPDR_SVC_CHANNEL_NAME, CHANNEL_OPTION_SHOW_PROTOCOL);
2364 if (!priv->ChannelHandle)
2366 WLog_Print(priv->log, WLOG_ERROR,
"WTSVirtualChannelOpen failed!");
2367 return CHANNEL_RC_BAD_CHANNEL;
2370 if (!(priv->StopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
2372 WLog_Print(priv->log, WLOG_ERROR,
"CreateEvent failed!");
2373 return ERROR_INTERNAL_ERROR;
2376 if (!(priv->Thread = CreateThread(
nullptr, 0, rdpdr_server_thread, (
void*)context, 0,
nullptr)))
2378 WLog_Print(priv->log, WLOG_ERROR,
"CreateThread failed!");
2379 (void)CloseHandle(priv->StopEvent);
2380 priv->StopEvent =
nullptr;
2381 return ERROR_INTERNAL_ERROR;
2384 return CHANNEL_RC_OK;
2393static UINT rdpdr_server_stop(RdpdrServerContext* context)
2395 WINPR_ASSERT(context);
2396 WINPR_ASSERT(context->priv);
2398 RdpdrServerPrivate* priv = context->priv;
2399 if (priv->StopEvent)
2401 (void)SetEvent(priv->StopEvent);
2403 if (WaitForSingleObject(priv->Thread, INFINITE) == WAIT_FAILED)
2405 UINT error = GetLastError();
2406 WLog_Print(priv->log, WLOG_ERROR,
"WaitForSingleObject failed with error %" PRIu32
"!",
2411 (void)CloseHandle(priv->Thread);
2412 priv->Thread =
nullptr;
2413 (void)CloseHandle(priv->StopEvent);
2414 priv->StopEvent =
nullptr;
2417 if (priv->ChannelHandle)
2419 (void)WTSVirtualChannelClose(priv->ChannelHandle);
2420 priv->ChannelHandle =
nullptr;
2422 return CHANNEL_RC_OK;
2425static void rdpdr_server_write_device_iorequest(
wStream* s, UINT32 deviceId, UINT32 fileId,
2426 UINT32 completionId, UINT32 majorFunction,
2427 UINT32 minorFunction)
2429 Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
2430 Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST);
2431 Stream_Write_UINT32(s, deviceId);
2432 Stream_Write_UINT32(s, fileId);
2433 Stream_Write_UINT32(s, completionId);
2434 Stream_Write_UINT32(s, majorFunction);
2435 Stream_Write_UINT32(s, minorFunction);
2444static UINT rdpdr_server_read_file_directory_information(wLog* log,
wStream* s,
2450 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
2451 return ERROR_INVALID_DATA;
2458 fdi->
ChangeTime.QuadPart = Stream_Get_INT64(s);
2459 fdi->
EndOfFile.QuadPart = Stream_Get_INT64(s);
2462 const UINT32 fileNameLength = Stream_Get_UINT32(s);
2464 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
2465 return ERROR_INVALID_DATA;
2467 if (fileNameLength /
sizeof(WCHAR) > ARRAYSIZE(fdi->
FileName))
2468 return ERROR_INVALID_DATA;
2470#if defined(__MINGW32__) || defined(WITH_WCHAR_FILE_DIRECTORY_INFORMATION)
2471 if (Stream_Read_UTF16_String(s, fdi->
FileName, fileNameLength /
sizeof(WCHAR)))
2472 return ERROR_INVALID_DATA;
2474 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, fileNameLength /
sizeof(WCHAR), fdi->
FileName,
2476 return ERROR_INVALID_DATA;
2478 return CHANNEL_RC_OK;
2485static UINT32 rdpdr_server_next_completion_id(RdpdrServerPrivate* priv)
2488 return (UINT32)(InterlockedIncrement(&priv->NextCompletionId) - 1);
2493static char* rdpdr_server_dup_path(
const char* path)
2497 char* copy = _strdup(path);
2501 for (
char* c = copy; *c !=
'\0'; c++)
2510static UINT prepare_path_irp(RdpdrServerContext* context, UINT32 deviceId,
2511 RDPDR_IRP_Callback callback,
void* callbackData,
const char* path,
2512 const char* extraPath, RDPDR_IRP** outIrp)
2514 WINPR_ASSERT(context);
2515 WINPR_ASSERT(context->priv);
2516 WINPR_ASSERT(callbackData);
2517 WINPR_ASSERT(outIrp);
2519 RdpdrServerPrivate* priv = context->priv;
2521 RDPDR_IRP* irp = rdpdr_server_irp_new();
2524 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2525 return CHANNEL_RC_NO_MEMORY;
2528 irp->CompletionId = rdpdr_server_next_completion_id(priv);
2529 irp->Callback = callback;
2530 irp->CallbackData = callbackData;
2531 irp->DeviceId = deviceId;
2534 irp->PathName = rdpdr_server_dup_path(path);
2536 irp->ExtraBuffer = rdpdr_server_dup_path(extraPath);
2537 if ((path && !irp->PathName) || (extraPath && !irp->ExtraBuffer))
2539 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_dup_path failed!");
2540 rdpdr_server_irp_free(irp);
2541 return CHANNEL_RC_NO_MEMORY;
2544 if (!rdpdr_server_enqueue_irp(context, irp))
2546 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2547 rdpdr_server_irp_free(irp);
2548 return ERROR_INTERNAL_ERROR;
2552 return CHANNEL_RC_OK;
2556static UINT prepare_irp(RdpdrServerContext* context, UINT32 deviceId, RDPDR_IRP_Callback callback,
2557 void* callbackData, RDPDR_IRP** outIrp)
2559 return prepare_path_irp(context, deviceId, callback, callbackData,
nullptr,
nullptr, outIrp);
2563static UINT prepare_smartcard_irp(RdpdrServerContext* context, UINT32 ioControlCode,
2564 RDPDR_IRP_Callback callback,
void* callbackData,
2567 WINPR_ASSERT(context);
2568 WINPR_ASSERT(context->priv);
2569 WINPR_ASSERT(callbackData);
2571 const char* cmd = scard_get_ioctl_string(ioControlCode, FALSE);
2573 RdpdrServerPrivate* priv = context->priv;
2574 if (!priv->haveSmartcardDevice)
2576 WLog_Print(priv->log, WLOG_ERROR,
"%s - no smartcard device registered", cmd);
2577 return ERROR_BAD_DEVICE;
2580 RDPDR_IRP* irp =
nullptr;
2581 UINT error = prepare_irp(context, priv->smartcardDeviceId, callback, callbackData, &irp);
2582 if (error != CHANNEL_RC_OK)
2585 irp->IoControlCode = ioControlCode;
2587 return CHANNEL_RC_OK;
2590static void dequeueAndDiscard(RdpdrServerContext* context, RDPDR_IRP* irp)
2592 WINPR_ASSERT(context);
2594 RDPDR_IRP* val = rdpdr_server_dequeue_irp(context, irp->CompletionId);
2595 rdpdr_server_irp_free(val);
2600static UINT rdpdr_seal_send_irp_request(RdpdrServerContext* context, RDPDR_IRP* irp,
wStream* s)
2602 const UINT rc = rdpdr_seal_send_free_request(context, s);
2603 if (rc != CHANNEL_RC_OK)
2604 dequeueAndDiscard(context, irp);
2614static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, RDPDR_IRP* irp,
2615 UINT32 desiredAccess, UINT32 createOptions,
2616 UINT32 createDisposition)
2618 WINPR_ASSERT(context);
2619 WINPR_ASSERT(context->priv);
2622 const UINT32 deviceId = irp->DeviceId;
2623 const UINT32 completionId = irp->CompletionId;
2624 const char* path = irp->PathName;
2626 RdpdrServerPrivate* priv = context->priv;
2628 WLog_Print(priv->log, WLOG_DEBUG,
2629 "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
2630 ", path=%s, desiredAccess=0x%" PRIx32
" createOptions=0x%" PRIx32
2631 " createDisposition=0x%" PRIx32
"",
2632 deviceId, path, desiredAccess, createOptions, createDisposition);
2634 size_t pathStrLength = 0;
2635 size_t pathLength = 0;
2638 pathStrLength = strlen(path);
2639 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2642 dequeueAndDiscard(context, irp);
2643 return ERROR_INTERNAL_ERROR;
2645 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2647 wStream* s = Stream_New(
nullptr, 256U + pathLength);
2651 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2652 dequeueAndDiscard(context, irp);
2653 return CHANNEL_RC_NO_MEMORY;
2656 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
2657 Stream_Write_UINT32(s, desiredAccess);
2658 Stream_Write_UINT32(s, 0);
2659 Stream_Write_UINT32(s, 0);
2660 Stream_Write_UINT32(s, 0);
2661 Stream_Write_UINT32(s, 3);
2662 Stream_Write_UINT32(s, createDisposition);
2663 Stream_Write_UINT32(s, createOptions);
2664 WINPR_ASSERT(pathLength <= UINT32_MAX);
2665 Stream_Write_UINT32(s, (UINT32)pathLength);
2667 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2671 dequeueAndDiscard(context, irp);
2672 return ERROR_INTERNAL_ERROR;
2674 return rdpdr_seal_send_irp_request(context, irp, s);
2683static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, RDPDR_IRP* irp)
2685 WINPR_ASSERT(context);
2686 WINPR_ASSERT(context->priv);
2689 RdpdrServerPrivate* priv = context->priv;
2691 WLog_Print(priv->log, WLOG_DEBUG,
2692 "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
"",
2693 irp->DeviceId, irp->FileId);
2694 wStream* s = Stream_New(
nullptr, 128);
2698 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2699 dequeueAndDiscard(context, irp);
2700 return CHANNEL_RC_NO_MEMORY;
2703 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2706 return rdpdr_seal_send_irp_request(context, irp, s);
2715static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, RDPDR_IRP* irp,
2716 UINT32 length, UINT64 offset)
2718 WINPR_ASSERT(context);
2719 WINPR_ASSERT(context->priv);
2722 RdpdrServerPrivate* priv = context->priv;
2724 WLog_Print(priv->log, WLOG_DEBUG,
2725 "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2726 ", length=%" PRIu32
", offset=%" PRIu64
"",
2727 irp->DeviceId, irp->FileId, length, offset);
2728 wStream* s = Stream_New(
nullptr, 128);
2732 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2733 dequeueAndDiscard(context, irp);
2734 return CHANNEL_RC_NO_MEMORY;
2737 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2739 Stream_Write_UINT32(s, length);
2740 Stream_Write_UINT64(s, offset);
2742 return rdpdr_seal_send_irp_request(context, irp, s);
2751static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, RDPDR_IRP* irp,
2752 const char* data, UINT32 length, UINT64 offset)
2754 WINPR_ASSERT(context);
2755 WINPR_ASSERT(context->priv);
2758 RdpdrServerPrivate* priv = context->priv;
2760 WLog_Print(priv->log, WLOG_DEBUG,
2761 "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2762 ", length=%" PRIu32
", offset=%" PRIu64
"",
2763 irp->DeviceId, irp->FileId, length, offset);
2764 wStream* s = Stream_New(
nullptr, 64 + length);
2768 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2769 dequeueAndDiscard(context, irp);
2770 return CHANNEL_RC_NO_MEMORY;
2773 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2775 Stream_Write_UINT32(s, length);
2776 Stream_Write_UINT64(s, offset);
2778 Stream_Write(s, data, length);
2779 return rdpdr_seal_send_irp_request(context, irp, s);
2788static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context,
2789 RDPDR_IRP* irp,
const char* path)
2791 WINPR_ASSERT(context);
2792 WINPR_ASSERT(context->priv);
2795 RdpdrServerPrivate* priv = context->priv;
2797 WLog_Print(priv->log, WLOG_DEBUG,
2798 "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2800 irp->DeviceId, irp->FileId, path);
2802 size_t pathStrLength = 0;
2803 size_t pathLength = 0;
2806 pathStrLength = strlen(path);
2807 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2810 dequeueAndDiscard(context, irp);
2811 return ERROR_INTERNAL_ERROR;
2813 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2815 wStream* s = Stream_New(
nullptr, 64 + pathLength);
2819 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2820 dequeueAndDiscard(context, irp);
2821 return CHANNEL_RC_NO_MEMORY;
2824 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2825 IRP_MJ_DIRECTORY_CONTROL, IRP_MN_QUERY_DIRECTORY);
2826 Stream_Write_UINT32(s, FileDirectoryInformation);
2827 Stream_Write_UINT8(s, path ? 1 : 0);
2828 WINPR_ASSERT(pathLength <= UINT32_MAX);
2829 Stream_Write_UINT32(s, (UINT32)pathLength);
2835 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2839 dequeueAndDiscard(context, irp);
2840 return ERROR_INTERNAL_ERROR;
2844 return rdpdr_seal_send_irp_request(context, irp, s);
2853static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context,
2854 RDPDR_IRP* irp,
const char* path,
2855 BOOL replaceIfExists)
2857 WINPR_ASSERT(context);
2858 WINPR_ASSERT(context->priv);
2861 RdpdrServerPrivate* priv = context->priv;
2863 WLog_Print(priv->log, WLOG_DEBUG,
2864 "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2866 irp->DeviceId, irp->FileId, path);
2868 size_t pathStrLength = 0;
2869 size_t pathLength = 0;
2872 pathStrLength = strlen(path);
2873 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2876 dequeueAndDiscard(context, irp);
2877 return ERROR_INTERNAL_ERROR;
2879 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2883 if (pathLength > UINT32_MAX - 64U)
2885 dequeueAndDiscard(context, irp);
2886 return ERROR_INVALID_PARAMETER;
2889 wStream* s = Stream_New(
nullptr, 64 + pathLength);
2893 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2894 dequeueAndDiscard(context, irp);
2895 return CHANNEL_RC_NO_MEMORY;
2898 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2899 IRP_MJ_SET_INFORMATION, 0);
2900 Stream_Write_UINT32(s, FileRenameInformation);
2901 Stream_Write_UINT32(s, (UINT32)pathLength + 6U);
2904 Stream_Write_UINT8(s, replaceIfExists ? 1 : 0);
2905 Stream_Write_UINT8(s, 0);
2906 Stream_Write_UINT32(s, (UINT32)pathLength);
2911 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2915 dequeueAndDiscard(context, irp);
2916 return ERROR_INTERNAL_ERROR;
2920 return rdpdr_seal_send_irp_request(context, irp, s);
2924static UINT rdpdr_server_send_device_set_information_request(RdpdrServerContext* context,
2926 UINT32 fsInformationClass,
2927 const BYTE* buffer, UINT32 length)
2929 WINPR_ASSERT(context);
2930 WINPR_ASSERT(context->priv);
2933 RdpdrServerPrivate* priv = context->priv;
2934 WLog_Print(priv->log, WLOG_DEBUG,
2935 "RdpdrServerSendDeviceSetInformationRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2936 ", class=%" PRIu32
", length=%" PRIu32
"",
2937 irp->DeviceId, irp->FileId, fsInformationClass, length);
2939 if (length > UINT32_MAX - 64U)
2941 dequeueAndDiscard(context, irp);
2942 return ERROR_INVALID_PARAMETER;
2945 wStream* s = Stream_New(
nullptr, 64U + length);
2948 dequeueAndDiscard(context, irp);
2949 return CHANNEL_RC_NO_MEMORY;
2952 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2953 IRP_MJ_SET_INFORMATION, 0);
2954 Stream_Write_UINT32(s, fsInformationClass);
2955 Stream_Write_UINT32(s, length);
2957 Stream_Write(s, buffer, length);
2958 return rdpdr_seal_send_irp_request(context, irp, s);
2962static UINT rdpdr_server_send_device_query_volume_information_request(RdpdrServerContext* context,
2964 UINT32 fsInformationClass)
2966 WINPR_ASSERT(context);
2967 WINPR_ASSERT(context->priv);
2970 RdpdrServerPrivate* priv = context->priv;
2971 WLog_Print(priv->log, WLOG_DEBUG,
2972 "RdpdrServerSendDeviceQueryVolumeInformationRequest: deviceId=%" PRIu32
2973 ", fileId=%" PRIu32
", class=%" PRIu32
"",
2974 irp->DeviceId, irp->FileId, fsInformationClass);
2976 wStream* s = Stream_New(
nullptr, 64);
2979 dequeueAndDiscard(context, irp);
2980 return CHANNEL_RC_NO_MEMORY;
2983 rdpdr_server_write_device_iorequest(s, irp->DeviceId, irp->FileId, irp->CompletionId,
2984 IRP_MJ_QUERY_VOLUME_INFORMATION, 0);
2985 Stream_Write_UINT32(s, fsInformationClass);
2986 Stream_Write_UINT32(s, 0);
2988 return rdpdr_seal_send_irp_request(context, irp, s);
2992static UINT rdpdr_server_send_device_control_request(RdpdrServerContext* context, UINT32 deviceId,
2993 UINT32 completionId, UINT32 ioControlCode,
2994 UINT32 outputBufferLength,
2995 const void* inputBuffer,
2996 size_t inputBufferLength)
2998 WINPR_ASSERT(context);
2999 WINPR_ASSERT(context->priv);
3000 WINPR_ASSERT(inputBuffer || (inputBufferLength == 0));
3002 if (inputBufferLength > UINT32_MAX)
3004 WLog_Print(context->priv->log, WLOG_ERROR,
3005 "inputBufferLength %" PRIuz
" exceeds UINT32_MAX", inputBufferLength);
3006 return ERROR_INVALID_PARAMETER;
3009 RdpdrServerPrivate* priv = context->priv;
3011 WLog_Print(priv->log, WLOG_DEBUG,
3012 "RdpdrServerSendDeviceControlRequest: deviceId=%" PRIu32
","
3013 " ioControlCode=0x%" PRIx32
", inputBufferLength=%" PRIuz,
3014 deviceId, ioControlCode, inputBufferLength);
3016 if (inputBufferLength > 0)
3017 winpr_HexLogDump(priv->log, WLOG_DEBUG, inputBuffer, inputBufferLength);
3020 Stream_New(
nullptr, RDPDR_HEADER_LENGTH + RDPDR_DEVICE_IO_REQUEST_LENGTH +
3021 RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH + inputBufferLength);
3024 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
3025 return CHANNEL_RC_NO_MEMORY;
3028 UINT32 inputLength = WINPR_ASSERTING_INT_CAST(UINT32, inputBufferLength);
3029 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_DEVICE_CONTROL, 0);
3030 Stream_Write_UINT32(s, outputBufferLength);
3031 Stream_Write_UINT32(s, inputLength);
3032 Stream_Write_UINT32(s, ioControlCode);
3035 if (inputBufferLength > 0)
3036 Stream_Write(s, inputBuffer, inputBufferLength);
3038 return rdpdr_seal_send_free_request(context, s);
3051static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context,
wStream* s,
3052 RDPDR_IRP* irp, UINT32 deviceId,
3053 UINT32 completionId, UINT32 ioStatus)
3055 WINPR_ASSERT(context);
3056 WINPR_ASSERT(context->priv);
3061 RdpdrServerPrivate* priv = context->priv;
3062 WLog_Print(priv->log, WLOG_DEBUG,
3063 "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
3064 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3065 deviceId, completionId, ioStatus);
3067 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
3069 rdpdr_server_irp_free(irp);
3070 return CHANNEL_RC_OK;
3079static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context,
wStream* s,
3080 RDPDR_IRP* irp, UINT32 deviceId,
3081 UINT32 completionId, UINT32 ioStatus)
3083 WINPR_ASSERT(context);
3084 WINPR_ASSERT(context->priv);
3088 RdpdrServerPrivate* priv = context->priv;
3089 WLog_Print(priv->log, WLOG_DEBUG,
3090 "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
3091 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3092 deviceId, completionId, ioStatus);
3094 if (ioStatus != STATUS_SUCCESS)
3097 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
3099 rdpdr_server_irp_free(irp);
3100 return CHANNEL_RC_OK;
3103 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3104 return ERROR_INVALID_DATA;
3106 const uint32_t fileId = Stream_Get_UINT32(s);
3107 const uint8_t information = Stream_Get_UINT8(s);
3108 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3109 fileInformation2str(information));
3112 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3113 irp->Callback = rdpdr_server_drive_create_directory_callback2;
3114 irp->DeviceId = deviceId;
3115 irp->FileId = fileId;
3117 if (!rdpdr_server_enqueue_irp(context, irp))
3119 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3120 rdpdr_server_irp_free(irp);
3121 return ERROR_INTERNAL_ERROR;
3125 return rdpdr_server_send_device_close_request(context, irp);
3134static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context,
void* callbackData,
3135 UINT32 deviceId,
const char* path)
3137 WINPR_ASSERT(context);
3138 WINPR_ASSERT(context->priv);
3139 WINPR_ASSERT(callbackData);
3142 RDPDR_IRP* irp =
nullptr;
3143 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_create_directory_callback1,
3144 callbackData, path,
nullptr, &irp);
3145 if (ret != CHANNEL_RC_OK)
3149 return rdpdr_server_send_device_create_request(
3150 context, irp, FILE_READ_DATA | SYNCHRONIZE,
3151 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
3164static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context,
wStream* s,
3165 RDPDR_IRP* irp, UINT32 deviceId,
3166 UINT32 completionId, UINT32 ioStatus)
3169 WINPR_ASSERT(context);
3170 WINPR_ASSERT(context->priv);
3173 RdpdrServerPrivate* priv = context->priv;
3174 WLog_Print(priv->log, WLOG_DEBUG,
3175 "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
3176 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3177 deviceId, completionId, ioStatus);
3179 context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
3181 rdpdr_server_irp_free(irp);
3182 return CHANNEL_RC_OK;
3191static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context,
wStream* s,
3192 RDPDR_IRP* irp, UINT32 deviceId,
3193 UINT32 completionId, UINT32 ioStatus)
3195 WINPR_ASSERT(context);
3196 WINPR_ASSERT(context->priv);
3199 RdpdrServerPrivate* priv = context->priv;
3200 WLog_Print(priv->log, WLOG_DEBUG,
3201 "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
3202 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3203 deviceId, completionId, ioStatus);
3205 if (ioStatus != STATUS_SUCCESS)
3208 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3210 rdpdr_server_irp_free(irp);
3211 return CHANNEL_RC_OK;
3214 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3215 return ERROR_INVALID_DATA;
3217 const uint32_t fileId = Stream_Get_UINT32(s);
3218 const uint8_t information = Stream_Get_UINT8(s);
3219 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3220 fileInformation2str(information));
3223 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3224 irp->Callback = rdpdr_server_drive_delete_directory_callback2;
3225 irp->DeviceId = deviceId;
3226 irp->FileId = fileId;
3228 if (!rdpdr_server_enqueue_irp(context, irp))
3230 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3231 rdpdr_server_irp_free(irp);
3232 return ERROR_INTERNAL_ERROR;
3236 return rdpdr_server_send_device_close_request(context, irp);
3245static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context,
void* callbackData,
3246 UINT32 deviceId,
const char* path)
3248 WINPR_ASSERT(context);
3249 WINPR_ASSERT(context->priv);
3251 RDPDR_IRP* irp =
nullptr;
3252 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_delete_directory_callback1,
3253 callbackData, path,
nullptr, &irp);
3254 if (ret != CHANNEL_RC_OK)
3258 return rdpdr_server_send_device_create_request(
3259 context, irp, DELETE | SYNCHRONIZE,
3260 FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3273static UINT rdpdr_server_drive_query_directory_callback3(RdpdrServerContext* context,
wStream* s,
3274 RDPDR_IRP* irp, UINT32 deviceId,
3275 UINT32 completionId, UINT32 ioStatus)
3277 WINPR_UNUSED(context);
3279 WINPR_UNUSED(deviceId);
3280 WINPR_UNUSED(completionId);
3281 WINPR_UNUSED(ioStatus);
3284 rdpdr_server_irp_free(irp);
3285 return CHANNEL_RC_OK;
3289static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context,
wStream* s,
3290 RDPDR_IRP* irp, UINT32 deviceId,
3291 UINT32 completionId, UINT32 ioStatus)
3293 WINPR_ASSERT(context);
3294 WINPR_ASSERT(context->priv);
3297 RdpdrServerPrivate* priv = context->priv;
3298 WLog_Print(priv->log, WLOG_DEBUG,
3299 "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
3300 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3301 deviceId, completionId, ioStatus);
3303 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3304 return ERROR_INVALID_DATA;
3306 const UINT32 length = Stream_Get_UINT32(s);
3311 UINT error = rdpdr_server_read_file_directory_information(priv->log, s, &fdi);
3314 WLog_Print(priv->log, WLOG_ERROR,
3315 "rdpdr_server_read_file_directory_information failed with error %" PRIu32
3323 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 1))
3324 return ERROR_INVALID_DATA;
3329 if (ioStatus == STATUS_SUCCESS)
3332 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
3333 length > 0 ? &fdi : nullptr);
3335 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3336 irp->Callback = rdpdr_server_drive_query_directory_callback2;
3338 if (!rdpdr_server_enqueue_irp(context, irp))
3340 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3341 rdpdr_server_irp_free(irp);
3342 return ERROR_INTERNAL_ERROR;
3346 return rdpdr_server_send_device_query_directory_request(context, irp,
nullptr);
3351 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
nullptr);
3354 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3355 irp->Callback = rdpdr_server_drive_query_directory_callback3;
3357 if (!rdpdr_server_enqueue_irp(context, irp))
3359 rdpdr_server_irp_free(irp);
3360 return ERROR_INTERNAL_ERROR;
3363 return rdpdr_server_send_device_close_request(context, irp);
3373static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context,
wStream* s,
3374 RDPDR_IRP* irp, UINT32 deviceId,
3375 UINT32 completionId, UINT32 ioStatus)
3377 WINPR_ASSERT(context);
3378 WINPR_ASSERT(context->priv);
3381 RdpdrServerPrivate* priv = context->priv;
3382 WLog_Print(priv->log, WLOG_DEBUG,
3383 "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
3384 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3385 deviceId, completionId, ioStatus);
3387 if (ioStatus != STATUS_SUCCESS)
3390 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
nullptr);
3392 rdpdr_server_irp_free(irp);
3393 return CHANNEL_RC_OK;
3396 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3397 return ERROR_INVALID_DATA;
3399 const uint32_t fileId = Stream_Get_UINT32(s);
3401 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3402 irp->Callback = rdpdr_server_drive_query_directory_callback2;
3403 irp->DeviceId = deviceId;
3404 irp->FileId = fileId;
3406 char* pattern =
nullptr;
3407 size_t patternLength = 0;
3408 if (winpr_asprintf(&pattern, &patternLength,
"%s\\*", irp->PathName) < 0)
3410 WLog_Print(priv->log, WLOG_ERROR,
"winpr_asprintf failed!");
3411 rdpdr_server_irp_free(irp);
3412 return CHANNEL_RC_NO_MEMORY;
3414 free(irp->PathName);
3415 irp->PathName = pattern;
3417 if (!rdpdr_server_enqueue_irp(context, irp))
3419 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3420 rdpdr_server_irp_free(irp);
3421 return ERROR_INTERNAL_ERROR;
3425 return rdpdr_server_send_device_query_directory_request(context, irp, irp->PathName);
3434static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context,
void* callbackData,
3435 UINT32 deviceId,
const char* path)
3437 WINPR_ASSERT(context);
3438 WINPR_ASSERT(context->priv);
3440 RDPDR_IRP* irp =
nullptr;
3441 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_query_directory_callback1,
3442 callbackData, path,
nullptr, &irp);
3443 if (ret != CHANNEL_RC_OK)
3447 return rdpdr_server_send_device_create_request(
3448 context, irp, FILE_READ_DATA | SYNCHRONIZE,
3449 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3462static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context,
wStream* s,
3463 RDPDR_IRP* irp, UINT32 deviceId,
3464 UINT32 completionId, UINT32 ioStatus)
3466 WINPR_ASSERT(context);
3467 WINPR_ASSERT(context->priv);
3470 RdpdrServerPrivate* priv = context->priv;
3471 WLog_Print(priv->log, WLOG_DEBUG,
3472 "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3473 ", ioStatus=0x%" PRIx32
"",
3474 deviceId, completionId, ioStatus);
3476 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3477 return ERROR_INVALID_DATA;
3479 const uint32_t fileId = Stream_Get_UINT32(s);
3480 const uint8_t information = Stream_Get_UINT8(s);
3481 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3482 fileInformation2str(information));
3485 context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
3487 rdpdr_server_irp_free(irp);
3488 return CHANNEL_RC_OK;
3497static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context,
void* callbackData,
3498 UINT32 deviceId,
const char* path, UINT32 desiredAccess,
3499 UINT32 createDisposition)
3501 WINPR_ASSERT(context);
3502 WINPR_ASSERT(context->priv);
3504 RDPDR_IRP* irp =
nullptr;
3505 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_open_file_callback,
3506 callbackData, path,
nullptr, &irp);
3507 if (ret != CHANNEL_RC_OK)
3511 return rdpdr_server_send_device_create_request(context, irp, desiredAccess | SYNCHRONIZE,
3512 FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
3525static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context,
wStream* s,
3526 RDPDR_IRP* irp, UINT32 deviceId,
3527 UINT32 completionId, UINT32 ioStatus)
3529 WINPR_ASSERT(context);
3530 WINPR_ASSERT(context->priv);
3533 RdpdrServerPrivate* priv = context->priv;
3534 WLog_Print(priv->log, WLOG_DEBUG,
3535 "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3536 ", ioStatus=0x%" PRIx32
"",
3537 deviceId, completionId, ioStatus);
3539 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3540 return ERROR_INVALID_DATA;
3542 const UINT32 length = Stream_Get_UINT32(s);
3543 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
3544 return ERROR_INVALID_DATA;
3546 char* buffer =
nullptr;
3549 buffer = Stream_PointerAs(s,
char);
3550 Stream_Seek(s, length);
3554 context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
3556 rdpdr_server_irp_free(irp);
3557 return CHANNEL_RC_OK;
3566static UINT rdpdr_server_drive_read_file_ex(RdpdrServerContext* context,
void* callbackData,
3567 UINT32 deviceId, UINT32 fileId, UINT32 length,
3570 WINPR_ASSERT(context);
3571 WINPR_ASSERT(context->priv);
3573 RDPDR_IRP* irp =
nullptr;
3575 prepare_irp(context, deviceId, rdpdr_server_drive_read_file_callback, callbackData, &irp);
3576 if (ret != CHANNEL_RC_OK)
3579 irp->FileId = fileId;
3582 return rdpdr_server_send_device_read_request(context, irp, length, offset);
3595static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
wStream* s,
3596 RDPDR_IRP* irp, UINT32 deviceId,
3597 UINT32 completionId, UINT32 ioStatus)
3599 WINPR_ASSERT(context);
3600 WINPR_ASSERT(context->priv);
3603 RdpdrServerPrivate* priv = context->priv;
3604 WLog_Print(priv->log, WLOG_DEBUG,
3605 "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3606 ", ioStatus=0x%" PRIx32
"",
3607 deviceId, completionId, ioStatus);
3609 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3610 return ERROR_INVALID_DATA;
3613 const UINT32 length = Stream_Get_UINT32(s);
3615 Stream_Seek(s, MIN(Stream_GetRemainingLength(s), 1));
3618 context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
3620 rdpdr_server_irp_free(irp);
3621 return CHANNEL_RC_OK;
3630static UINT rdpdr_server_drive_write_file_ex(RdpdrServerContext* context,
void* callbackData,
3631 UINT32 deviceId, UINT32 fileId,
const char* buffer,
3632 UINT32 length, UINT64 offset)
3634 WINPR_ASSERT(context);
3635 WINPR_ASSERT(context->priv);
3637 RDPDR_IRP* irp =
nullptr;
3639 prepare_irp(context, deviceId, rdpdr_server_drive_write_file_callback, callbackData, &irp);
3640 if (ret != CHANNEL_RC_OK)
3643 irp->FileId = fileId;
3647 return rdpdr_server_send_device_write_request(context, irp, buffer, length, offset);
3661static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
wStream* s,
3662 RDPDR_IRP* irp, UINT32 deviceId,
3663 UINT32 completionId, UINT32 ioStatus)
3665 WINPR_ASSERT(context);
3666 WINPR_ASSERT(context->priv);
3669 RdpdrServerPrivate* priv = context->priv;
3671 WLog_Print(priv->log, WLOG_DEBUG,
3672 "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3673 ", ioStatus=0x%" PRIx32
"",
3674 deviceId, completionId, ioStatus);
3678 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3679 return ERROR_INVALID_DATA;
3684 context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
3686 rdpdr_server_irp_free(irp);
3687 return CHANNEL_RC_OK;
3696static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context,
void* callbackData,
3697 UINT32 deviceId, UINT32 fileId)
3699 WINPR_ASSERT(context);
3700 WINPR_ASSERT(context->priv);
3702 RDPDR_IRP* irp =
nullptr;
3704 prepare_irp(context, deviceId, rdpdr_server_drive_close_file_callback, callbackData, &irp);
3705 if (ret != CHANNEL_RC_OK)
3708 irp->FileId = fileId;
3712 return rdpdr_server_send_device_close_request(context, irp);
3726static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context,
wStream* s,
3727 RDPDR_IRP* irp, UINT32 deviceId,
3728 UINT32 completionId, UINT32 ioStatus)
3731 WINPR_ASSERT(context);
3732 WINPR_ASSERT(context->priv);
3735 RdpdrServerPrivate* priv = context->priv;
3736 WLog_Print(priv->log, WLOG_DEBUG,
3737 "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3738 ", ioStatus=0x%" PRIx32
"",
3739 deviceId, completionId, ioStatus);
3741 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3743 rdpdr_server_irp_free(irp);
3744 return CHANNEL_RC_OK;
3753static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context,
wStream* s,
3754 RDPDR_IRP* irp, UINT32 deviceId,
3755 UINT32 completionId, UINT32 ioStatus)
3757 WINPR_ASSERT(context);
3758 WINPR_ASSERT(context->priv);
3761 RdpdrServerPrivate* priv = context->priv;
3762 WLog_Print(priv->log, WLOG_DEBUG,
3763 "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3764 ", ioStatus=0x%" PRIx32
"",
3765 deviceId, completionId, ioStatus);
3767 if (ioStatus != STATUS_SUCCESS)
3770 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3772 rdpdr_server_irp_free(irp);
3773 return CHANNEL_RC_OK;
3776 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3777 return ERROR_INVALID_DATA;
3779 const uint32_t fileId = Stream_Get_UINT32(s);
3780 const uint8_t information = Stream_Get_UINT8(s);
3782 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3783 fileInformation2str(information));
3785 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3786 irp->Callback = rdpdr_server_drive_delete_file_callback2;
3787 irp->DeviceId = deviceId;
3788 irp->FileId = fileId;
3790 if (!rdpdr_server_enqueue_irp(context, irp))
3792 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3793 rdpdr_server_irp_free(irp);
3794 return ERROR_INTERNAL_ERROR;
3798 return rdpdr_server_send_device_close_request(context, irp);
3807static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context,
void* callbackData,
3808 UINT32 deviceId,
const char* path)
3810 WINPR_ASSERT(context);
3811 WINPR_ASSERT(context->priv);
3813 RDPDR_IRP* irp =
nullptr;
3814 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_delete_file_callback1,
3815 callbackData, path,
nullptr, &irp);
3816 if (ret != CHANNEL_RC_OK)
3820 return rdpdr_server_send_device_create_request(
3821 context, irp, DELETE | SYNCHRONIZE, FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT,
3835static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context,
wStream* s,
3836 RDPDR_IRP* irp, UINT32 deviceId,
3837 UINT32 completionId, UINT32 ioStatus)
3839 WINPR_UNUSED(context);
3841 WINPR_ASSERT(context);
3842 WINPR_ASSERT(context->priv);
3845 RdpdrServerPrivate* priv = context->priv;
3846 WLog_Print(priv->log, WLOG_DEBUG,
3847 "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32
", completionId=%" PRIu32
3848 ", ioStatus=0x%" PRIx32
"",
3849 deviceId, completionId, ioStatus);
3851 rdpdr_server_irp_free(irp);
3852 return CHANNEL_RC_OK;
3861static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context,
wStream* s,
3862 RDPDR_IRP* irp, UINT32 deviceId,
3863 UINT32 completionId, UINT32 ioStatus)
3865 WINPR_ASSERT(context);
3866 WINPR_ASSERT(context->priv);
3869 RdpdrServerPrivate* priv = context->priv;
3870 WLog_Print(priv->log, WLOG_DEBUG,
3871 "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3872 ", ioStatus=0x%" PRIx32
"",
3873 deviceId, completionId, ioStatus);
3875 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3876 return ERROR_INVALID_DATA;
3878 WINPR_ATTR_UNUSED
const UINT32 length = Stream_Get_UINT32(s);
3880 if (Stream_GetRemainingLength(s) > 0)
3884 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3886 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3887 irp->Callback = rdpdr_server_drive_rename_file_callback3;
3888 irp->DeviceId = deviceId;
3890 if (!rdpdr_server_enqueue_irp(context, irp))
3892 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3893 rdpdr_server_irp_free(irp);
3894 return ERROR_INTERNAL_ERROR;
3898 return rdpdr_server_send_device_close_request(context, irp);
3907static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context,
wStream* s,
3908 RDPDR_IRP* irp, UINT32 deviceId,
3909 UINT32 completionId, UINT32 ioStatus)
3911 WINPR_ASSERT(context);
3912 WINPR_ASSERT(context->priv);
3915 RdpdrServerPrivate* priv = context->priv;
3916 WLog_Print(priv->log, WLOG_DEBUG,
3917 "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3918 ", ioStatus=0x%" PRIx32
"",
3919 deviceId, completionId, ioStatus);
3921 if (ioStatus != STATUS_SUCCESS)
3924 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3926 rdpdr_server_irp_free(irp);
3927 return CHANNEL_RC_OK;
3930 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3931 return ERROR_INVALID_DATA;
3933 const uint32_t fileId = Stream_Get_UINT32(s);
3934 const uint8_t information = Stream_Get_UINT8(s);
3935 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3936 fileInformation2str(information));
3939 irp->CompletionId = rdpdr_server_next_completion_id(priv);
3940 irp->Callback = rdpdr_server_drive_rename_file_callback2;
3941 irp->DeviceId = deviceId;
3942 irp->FileId = fileId;
3944 if (!rdpdr_server_enqueue_irp(context, irp))
3946 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3947 rdpdr_server_irp_free(irp);
3948 return ERROR_INTERNAL_ERROR;
3952 return rdpdr_server_send_device_file_rename_request(context, irp, irp->ExtraBuffer,
3953 irp->ReplaceIfExists);
3962static UINT rdpdr_server_drive_rename_file_ex(RdpdrServerContext* context,
void* callbackData,
3963 UINT32 deviceId,
const char* oldPath,
3964 const char* newPath, BOOL replaceIfExists)
3966 WINPR_ASSERT(context);
3967 WINPR_ASSERT(context->priv);
3969 RDPDR_IRP* irp =
nullptr;
3970 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_rename_file_callback1,
3971 callbackData, oldPath, newPath, &irp);
3972 if (ret != CHANNEL_RC_OK)
3975 irp->ReplaceIfExists = replaceIfExists;
3978 return rdpdr_server_send_device_create_request(context, irp,
3979 DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
3980 FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3984static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context,
void* callbackData,
3985 UINT32 deviceId,
const char* oldPath,
3986 const char* newPath)
3988 return rdpdr_server_drive_rename_file_ex(context, callbackData, deviceId, oldPath, newPath,
3993static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context,
void* callbackData,
3994 UINT32 deviceId, UINT32 fileId, UINT32 length,
3997 return rdpdr_server_drive_read_file_ex(context, callbackData, deviceId, fileId, length, offset);
4001static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context,
void* callbackData,
4002 UINT32 deviceId, UINT32 fileId,
const char* buffer,
4003 UINT32 length, UINT32 offset)
4005 return rdpdr_server_drive_write_file_ex(context, callbackData, deviceId, fileId, buffer, length,
4014static UINT rdpdr_server_drive_set_information_callback3(RdpdrServerContext* context,
wStream* s,
4015 RDPDR_IRP* irp, UINT32 deviceId,
4016 UINT32 completionId, UINT32 ioStatus)
4018 WINPR_UNUSED(context);
4020 WINPR_UNUSED(deviceId);
4021 WINPR_UNUSED(completionId);
4022 WINPR_UNUSED(ioStatus);
4025 rdpdr_server_irp_free(irp);
4026 return CHANNEL_RC_OK;
4030static UINT rdpdr_server_drive_set_information_callback2(RdpdrServerContext* context,
wStream* s,
4031 RDPDR_IRP* irp, UINT32 deviceId,
4032 UINT32 completionId, UINT32 ioStatus)
4034 WINPR_ASSERT(context);
4035 WINPR_ASSERT(context->priv);
4037 WINPR_UNUSED(completionId);
4039 RdpdrServerPrivate* priv = context->priv;
4042 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
4043 return ERROR_INVALID_DATA;
4046 IFCALL(context->OnDriveSetFileInformationComplete, context, irp->CallbackData, ioStatus);
4049 irp->CompletionId = rdpdr_server_next_completion_id(priv);
4050 irp->Callback = rdpdr_server_drive_set_information_callback3;
4051 irp->DeviceId = deviceId;
4053 if (!rdpdr_server_enqueue_irp(context, irp))
4055 rdpdr_server_irp_free(irp);
4056 return ERROR_INTERNAL_ERROR;
4059 return rdpdr_server_send_device_close_request(context, irp);
4063static UINT rdpdr_server_drive_set_information_callback1(RdpdrServerContext* context,
wStream* s,
4064 RDPDR_IRP* irp, UINT32 deviceId,
4065 UINT32 completionId, UINT32 ioStatus)
4067 WINPR_ASSERT(context);
4068 WINPR_ASSERT(context->priv);
4070 WINPR_UNUSED(completionId);
4072 RdpdrServerPrivate* priv = context->priv;
4074 if (ioStatus != STATUS_SUCCESS)
4076 IFCALL(context->OnDriveSetFileInformationComplete, context, irp->CallbackData, ioStatus);
4077 rdpdr_server_irp_free(irp);
4078 return CHANNEL_RC_OK;
4081 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
4082 return ERROR_INVALID_DATA;
4084 irp->FileId = Stream_Get_UINT32(s);
4085 irp->CompletionId = rdpdr_server_next_completion_id(priv);
4086 irp->Callback = rdpdr_server_drive_set_information_callback2;
4087 irp->DeviceId = deviceId;
4089 if (!rdpdr_server_enqueue_irp(context, irp))
4091 rdpdr_server_irp_free(irp);
4092 return ERROR_INTERNAL_ERROR;
4095 return rdpdr_server_send_device_set_information_request(context, irp, irp->InfoClass,
4096 irp->InfoBuffer, irp->InfoLength);
4101static UINT32 rdpdr_server_set_information_access(UINT32 fsInformationClass)
4103 switch (fsInformationClass)
4105 case FileBasicInformation:
4106 return FILE_WRITE_ATTRIBUTES;
4107 case FileEndOfFileInformation:
4108 case FileAllocationInformation:
4109 return FILE_WRITE_DATA;
4110 case FileDispositionInformation:
4111 case FileRenameInformation:
4114 return FILE_GENERIC_WRITE;
4119static UINT rdpdr_server_drive_set_information(RdpdrServerContext* context,
void* callbackData,
4120 UINT32 deviceId,
const char* path,
4121 UINT32 fsInformationClass,
const BYTE* buffer,
4124 WINPR_ASSERT(context);
4126 WINPR_ASSERT(buffer);
4128 RDPDR_IRP* irp =
nullptr;
4129 if (length >
sizeof(irp->InfoBuffer))
4130 return ERROR_INVALID_PARAMETER;
4132 UINT ret = prepare_path_irp(context, deviceId, rdpdr_server_drive_set_information_callback1,
4133 callbackData, path,
nullptr, &irp);
4134 if (ret != CHANNEL_RC_OK)
4137 irp->InfoClass = fsInformationClass;
4138 irp->InfoLength = length;
4139 memcpy(irp->InfoBuffer, buffer, length);
4142 return rdpdr_server_send_device_create_request(
4143 context, irp, rdpdr_server_set_information_access(fsInformationClass) | SYNCHRONIZE,
4144 FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
4148static UINT rdpdr_server_drive_set_file_size(RdpdrServerContext* context,
void* callbackData,
4149 UINT32 deviceId,
const char* path, UINT64 size)
4151 BYTE buffer[8] = WINPR_C_ARRAY_INIT;
4152 wStream sbuffer = WINPR_C_ARRAY_INIT;
4153 wStream* s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
4155 Stream_Write_UINT64(s, size);
4156 return rdpdr_server_drive_set_information(context, callbackData, deviceId, path,
4157 FileEndOfFileInformation, buffer,
sizeof(buffer));
4161static UINT rdpdr_server_drive_set_file_times(RdpdrServerContext* context,
void* callbackData,
4162 UINT32 deviceId,
const char* path,
4163 INT64 lastAccessTime, INT64 lastWriteTime)
4165 BYTE buffer[36] = WINPR_C_ARRAY_INIT;
4166 wStream sbuffer = WINPR_C_ARRAY_INIT;
4167 wStream* s = Stream_StaticInit(&sbuffer, buffer,
sizeof(buffer));
4170 Stream_Write_INT64(s, 0);
4171 Stream_Write_INT64(s, lastAccessTime);
4172 Stream_Write_INT64(s, lastWriteTime);
4173 Stream_Write_INT64(s, 0);
4174 Stream_Write_UINT32(s, 0);
4175 return rdpdr_server_drive_set_information(context, callbackData, deviceId, path,
4176 FileBasicInformation, buffer,
sizeof(buffer));
4184static UINT rdpdr_server_drive_query_volume_information_callback2(RdpdrServerContext* context,
4187 UINT32 completionId,
4190 WINPR_ASSERT(context);
4191 WINPR_ASSERT(context->priv);
4193 WINPR_UNUSED(completionId);
4195 RdpdrServerPrivate* priv = context->priv;
4196 UINT64 totalBytes = 0;
4197 UINT64 availableBytes = 0;
4199 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
4200 return ERROR_INVALID_DATA;
4202 const UINT32 length = Stream_Get_UINT32(s);
4203 if ((ioStatus == STATUS_SUCCESS) && (length >= 32))
4205 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
4206 return ERROR_INVALID_DATA;
4209 const UINT64 totalUnits = Stream_Get_UINT64(s);
4210 const UINT64 callerUnits = Stream_Get_UINT64(s);
4211 Stream_Seek_UINT64(s);
4212 const UINT32 sectorsPerUnit = Stream_Get_UINT32(s);
4213 const UINT32 bytesPerSector = Stream_Get_UINT32(s);
4214 const UINT64 unitSize = 1ull * sectorsPerUnit * bytesPerSector;
4216 totalBytes = totalUnits * unitSize;
4217 availableBytes = callerUnits * unitSize;
4219 else if (ioStatus == STATUS_SUCCESS)
4220 ioStatus = ERROR_INVALID_PARAMETER;
4222 IFCALL(context->OnDriveQueryVolumeInformationComplete, context, irp->CallbackData, ioStatus,
4223 totalBytes, availableBytes);
4226 irp->CompletionId = rdpdr_server_next_completion_id(priv);
4227 irp->Callback = rdpdr_server_drive_set_information_callback3;
4228 irp->DeviceId = deviceId;
4230 if (!rdpdr_server_enqueue_irp(context, irp))
4232 rdpdr_server_irp_free(irp);
4233 return ERROR_INTERNAL_ERROR;
4236 return rdpdr_server_send_device_close_request(context, irp);
4240static UINT rdpdr_server_drive_query_volume_information_callback1(RdpdrServerContext* context,
4243 UINT32 completionId,
4246 WINPR_ASSERT(context);
4247 WINPR_ASSERT(context->priv);
4249 WINPR_UNUSED(completionId);
4251 RdpdrServerPrivate* priv = context->priv;
4253 if (ioStatus != STATUS_SUCCESS)
4255 IFCALL(context->OnDriveQueryVolumeInformationComplete, context, irp->CallbackData, ioStatus,
4257 rdpdr_server_irp_free(irp);
4258 return CHANNEL_RC_OK;
4261 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
4262 return ERROR_INVALID_DATA;
4264 irp->FileId = Stream_Get_UINT32(s);
4265 irp->CompletionId = rdpdr_server_next_completion_id(priv);
4266 irp->Callback = rdpdr_server_drive_query_volume_information_callback2;
4267 irp->DeviceId = deviceId;
4269 if (!rdpdr_server_enqueue_irp(context, irp))
4271 rdpdr_server_irp_free(irp);
4272 return ERROR_INTERNAL_ERROR;
4275 return rdpdr_server_send_device_query_volume_information_request(context, irp,
4276 FileFsFullSizeInformation);
4280static UINT rdpdr_server_drive_query_volume_information(RdpdrServerContext* context,
4281 void* callbackData, UINT32 deviceId)
4283 RDPDR_IRP* irp =
nullptr;
4286 prepare_path_irp(context, deviceId, rdpdr_server_drive_query_volume_information_callback1,
4287 callbackData,
"\\",
nullptr, &irp);
4288 if (ret != CHANNEL_RC_OK)
4291 return rdpdr_server_send_device_create_request(
4292 context, irp, FILE_READ_DATA | SYNCHRONIZE,
4293 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
4296static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
4300 ListDictionary_Free(ctx->IrpList);
4301 HashTable_Free(ctx->devicelist);
4302 free(ctx->ClientComputerName);
4306#define TAG CHANNELS_TAG("rdpdr.server")
4307WINPR_ATTR_MALLOC(rdpdr_server_private_free, 1)
4308static RdpdrServerPrivate* rdpdr_server_private_new(
void)
4310 RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1,
sizeof(RdpdrServerPrivate));
4315 priv->log = WLog_Get(TAG);
4316 priv->VersionMajor = RDPDR_VERSION_MAJOR;
4317 priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
4318 priv->ClientId = g_ClientId++;
4319 priv->UserLoggedOnPdu = TRUE;
4320 priv->NextCompletionId = 1;
4321 priv->haveSmartcardDevice = FALSE;
4322 priv->smartcardDeviceId = 0;
4323 priv->IrpList = ListDictionary_New(TRUE);
4328 ListDictionary_ValueObject(priv->IrpList)->
fnObjectFree = rdpdr_server_list_free;
4330 priv->devicelist = HashTable_New(FALSE);
4331 if (!priv->devicelist)
4334 if (!HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash))
4338 wObject* obj = HashTable_ValueObject(priv->devicelist);
4345 wObject* obj = HashTable_KeyObject(priv->devicelist);
4353 rdpdr_server_private_free(priv);
4358static UINT rdpdr_server_smartcard_establish_context_callback(RdpdrServerContext* context,
4360 UINT32 deviceId, UINT32 completionId,
4363 WINPR_ASSERT(context);
4364 WINPR_ASSERT(context->priv);
4368 UINT result = CHANNEL_RC_OK;
4369 RdpdrServerPrivate* priv = context->priv;
4372 WLog_Print(priv->log, WLOG_DEBUG,
4373 "RdpdrServerSmartcardEstablishContextCallback: deviceId=%" PRIu32
4374 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
4375 deviceId, completionId, ioStatus);
4377 if (ioStatus != STATUS_SUCCESS)
4379 if (context->OnSmartcardEstablishContextComplete)
4380 context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
4381 SCARD_F_INTERNAL_ERROR,
nullptr);
4385 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4386 if (rc != SCARD_S_SUCCESS)
4388 result = ERROR_INVALID_DATA;
4392 if (context->OnSmartcardEstablishContextComplete)
4393 context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
4397 smartcard_operation_free(&op, FALSE);
4398 rdpdr_server_irp_free(irp);
4403static UINT rdpdr_server_smartcard_establish_context(RdpdrServerContext* context,
4404 void* callbackData, UINT32 dwScope,
4405 UINT32* completionId)
4407 WINPR_ASSERT(context);
4408 WINPR_ASSERT(context->priv);
4409 WINPR_ASSERT(completionId);
4411 RdpdrServerPrivate* priv = context->priv;
4412 RDPDR_IRP* irp =
nullptr;
4416 case SCARD_SCOPE_USER:
4417 case SCARD_SCOPE_TERMINAL:
4418 case SCARD_SCOPE_SYSTEM:
4421 WLog_Print(priv->log, WLOG_ERROR,
"invalid dwScope=0x%08" PRIx32, dwScope);
4422 return ERROR_INVALID_PARAMETER;
4425 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_ESTABLISHCONTEXT,
4426 rdpdr_server_smartcard_establish_context_callback,
4427 callbackData, &irp);
4428 if (result != CHANNEL_RC_OK)
4432 *completionId = irp->CompletionId;
4435 .ioControlCode = SCARD_IOCTL_ESTABLISHCONTEXT,
4436 .call.establishContext.dwScope = dwScope,
4439 wStream* s = Stream_New(
nullptr, 64);
4442 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4443 result = CHANNEL_RC_NO_MEMORY;
4447 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4448 if (rc != SCARD_S_SUCCESS)
4450 result = ERROR_INTERNAL_ERROR;
4454 result = rdpdr_server_send_device_control_request(
4455 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4456 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4460 if (result != CHANNEL_RC_OK)
4461 rdpdr_server_discard_request(context, irp->CompletionId);
4470static UINT rdpdr_server_smartcard_release_context_callback(RdpdrServerContext* context,
wStream* s,
4471 RDPDR_IRP* irp, UINT32 deviceId,
4472 UINT32 completionId, UINT32 ioStatus)
4474 WINPR_ASSERT(context);
4475 WINPR_ASSERT(context->priv);
4479 UINT result = CHANNEL_RC_OK;
4480 RdpdrServerPrivate* priv = context->priv;
4483 WLog_Print(priv->log, WLOG_DEBUG,
4484 "SmartcardReleaseContextCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4485 ", ioStatus=0x%" PRIx32,
4486 deviceId, completionId, ioStatus);
4488 if (ioStatus != STATUS_SUCCESS)
4490 if (context->OnSmartcardReleaseContextComplete)
4491 context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
4492 SCARD_F_INTERNAL_ERROR);
4496 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4497 if (rc != SCARD_S_SUCCESS)
4499 result = ERROR_INVALID_DATA;
4503 if (context->OnSmartcardReleaseContextComplete)
4504 context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
4508 smartcard_operation_free(&op, FALSE);
4509 rdpdr_server_irp_free(irp);
4514static UINT rdpdr_server_smartcard_release_context(RdpdrServerContext* context,
void* callbackData,
4516 UINT32* completionId)
4518 WINPR_ASSERT(context);
4519 WINPR_ASSERT(context->priv);
4520 WINPR_ASSERT(hContext);
4521 WINPR_ASSERT(completionId);
4523 RdpdrServerPrivate* priv = context->priv;
4524 RDPDR_IRP* irp =
nullptr;
4527 prepare_smartcard_irp(context, SCARD_IOCTL_RELEASECONTEXT,
4528 rdpdr_server_smartcard_release_context_callback, callbackData, &irp);
4529 if (result != CHANNEL_RC_OK)
4532 *completionId = irp->CompletionId;
4535 .ioControlCode = SCARD_IOCTL_RELEASECONTEXT,
4536 .call.context.handles.hContext = *hContext,
4539 wStream* s = Stream_New(
nullptr, 64);
4542 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4543 result = CHANNEL_RC_NO_MEMORY;
4547 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4548 if (rc != SCARD_S_SUCCESS)
4550 result = ERROR_INTERNAL_ERROR;
4554 result = rdpdr_server_send_device_control_request(
4555 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4556 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4560 if (result != CHANNEL_RC_OK)
4561 rdpdr_server_discard_request(context, irp->CompletionId);
4570static UINT rdpdr_server_smartcard_is_valid_context_callback(RdpdrServerContext* context,
4572 UINT32 deviceId, UINT32 completionId,
4575 WINPR_ASSERT(context);
4576 WINPR_ASSERT(context->priv);
4580 UINT result = CHANNEL_RC_OK;
4581 RdpdrServerPrivate* priv = context->priv;
4584 WLog_Print(priv->log, WLOG_DEBUG,
4585 "SmartcardIsValidContextCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4586 ", ioStatus=0x%" PRIx32,
4587 deviceId, completionId, ioStatus);
4589 if (ioStatus != STATUS_SUCCESS)
4591 if (context->OnSmartcardIsValidContextComplete)
4592 context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
4593 SCARD_F_INTERNAL_ERROR);
4597 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4598 if (rc != SCARD_S_SUCCESS)
4600 result = ERROR_INVALID_DATA;
4604 if (context->OnSmartcardIsValidContextComplete)
4605 context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
4609 smartcard_operation_free(&op, FALSE);
4610 rdpdr_server_irp_free(irp);
4615static UINT rdpdr_server_smartcard_is_valid_context(RdpdrServerContext* context,
void* callbackData,
4617 UINT32* completionId)
4619 WINPR_ASSERT(context);
4620 WINPR_ASSERT(context->priv);
4621 WINPR_ASSERT(hContext);
4622 WINPR_ASSERT(completionId);
4624 RdpdrServerPrivate* priv = context->priv;
4625 RDPDR_IRP* irp =
nullptr;
4628 prepare_smartcard_irp(context, SCARD_IOCTL_ISVALIDCONTEXT,
4629 rdpdr_server_smartcard_is_valid_context_callback, callbackData, &irp);
4630 if (result != CHANNEL_RC_OK)
4634 *completionId = irp->CompletionId;
4637 .ioControlCode = SCARD_IOCTL_ISVALIDCONTEXT,
4638 .call.context.handles.hContext = *hContext,
4641 wStream* s = Stream_New(
nullptr, 64);
4644 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4645 result = CHANNEL_RC_NO_MEMORY;
4649 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4650 if (rc != SCARD_S_SUCCESS)
4652 result = ERROR_INTERNAL_ERROR;
4656 result = rdpdr_server_send_device_control_request(
4657 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4658 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4662 if (result != CHANNEL_RC_OK)
4663 rdpdr_server_discard_request(context, irp->CompletionId);
4672static UINT rdpdr_server_smartcard_list_reader_groups_callback(RdpdrServerContext* context,
4674 UINT32 deviceId, UINT32 completionId,
4677 WINPR_ASSERT(context);
4678 WINPR_ASSERT(context->priv);
4682 UINT result = CHANNEL_RC_OK;
4683 RdpdrServerPrivate* priv = context->priv;
4686 WLog_Print(priv->log, WLOG_DEBUG,
4687 "SmartcardListReaderGroupsCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4688 ", ioStatus=0x%" PRIx32,
4689 deviceId, completionId, ioStatus);
4691 if (ioStatus != STATUS_SUCCESS)
4693 if (context->OnSmartcardListReaderGroupsComplete)
4694 context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
4695 SCARD_F_INTERNAL_ERROR,
nullptr);
4699 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4700 if (rc != SCARD_S_SUCCESS)
4702 result = ERROR_INVALID_DATA;
4706 if (context->OnSmartcardListReaderGroupsComplete)
4707 context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
4711 smartcard_operation_free(&op, FALSE);
4712 rdpdr_server_irp_free(irp);
4717static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* context,
4718 void* callbackData, UINT32 ioControlCode,
4720 UINT32* completionId)
4722 WINPR_ASSERT(context);
4723 WINPR_ASSERT(context->priv);
4725 WINPR_ASSERT(completionId);
4727 RdpdrServerPrivate* priv = context->priv;
4728 RDPDR_IRP* irp =
nullptr;
4730 UINT result = prepare_smartcard_irp(context, ioControlCode,
4731 rdpdr_server_smartcard_list_reader_groups_callback,
4732 callbackData, &irp);
4733 if (result != CHANNEL_RC_OK)
4737 *completionId = irp->CompletionId;
4740 .call.listReaderGroups = {
4741 .handles.hContext = call->handles.hContext,
4742 .fmszGroupsIsNULL = call->fmszGroupsIsNULL,
4743 .cchGroups = call->cchGroups,
4746 wStream* s = Stream_New(
nullptr, 32);
4749 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4750 result = CHANNEL_RC_NO_MEMORY;
4754 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4755 if (rc != SCARD_S_SUCCESS)
4757 result = ERROR_INTERNAL_ERROR;
4761 result = rdpdr_server_send_device_control_request(
4762 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4763 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4767 if (result != CHANNEL_RC_OK)
4768 rdpdr_server_discard_request(context, irp->CompletionId);
4776static UINT rdpdr_server_smartcard_list_reader_groupsA(RdpdrServerContext* context,
4779 UINT32* completionId)
4781 return rdpdr_server_smartcard_list_reader_groups(
4782 context, callbackData, SCARD_IOCTL_LISTREADERGROUPSA, call, completionId);
4786static UINT rdpdr_server_smartcard_list_reader_groupsW(RdpdrServerContext* context,
4789 UINT32* completionId)
4791 return rdpdr_server_smartcard_list_reader_groups(
4792 context, callbackData, SCARD_IOCTL_LISTREADERGROUPSW, call, completionId);
4797static UINT rdpdr_server_smartcard_list_readers_callback(RdpdrServerContext* context,
wStream* s,
4798 RDPDR_IRP* irp, UINT32 deviceId,
4799 UINT32 completionId, UINT32 ioStatus)
4801 WINPR_ASSERT(context);
4802 WINPR_ASSERT(context->priv);
4806 UINT result = CHANNEL_RC_OK;
4807 RdpdrServerPrivate* priv = context->priv;
4810 WLog_Print(priv->log, WLOG_DEBUG,
4811 "SmartcardListReadersCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4812 ", ioStatus=0x%" PRIx32,
4813 deviceId, completionId, ioStatus);
4815 if (ioStatus != STATUS_SUCCESS)
4817 if (context->OnSmartcardListReadersComplete)
4818 context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus,
4819 SCARD_F_INTERNAL_ERROR,
nullptr);
4823 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4824 if (rc != SCARD_S_SUCCESS)
4826 result = ERROR_INVALID_DATA;
4830 if (context->OnSmartcardListReadersComplete)
4831 context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
4832 &op.
ret.listReaders);
4835 smartcard_operation_free(&op, FALSE);
4836 rdpdr_server_irp_free(irp);
4841static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context,
void* callbackData,
4843 UINT32* completionId)
4845 WINPR_ASSERT(context);
4846 WINPR_ASSERT(context->priv);
4848 WINPR_ASSERT(completionId);
4850 RdpdrServerPrivate* priv = context->priv;
4851 RDPDR_IRP* irp =
nullptr;
4853 UINT result = prepare_smartcard_irp(
4854 context, ioControlCode, rdpdr_server_smartcard_list_readers_callback, callbackData, &irp);
4855 if (result != CHANNEL_RC_OK)
4859 *completionId = irp->CompletionId;
4862 .call.listReaders = {
4863 .handles.hContext = call->handles.hContext,
4864 .cBytes = call->cBytes,
4865 .mszGroups = call->mszGroups,
4866 .fmszReadersIsNULL = call->fmszReadersIsNULL,
4867 .cchReaders = call->cchReaders,
4870 wStream* s = Stream_New(
nullptr, 256);
4873 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4874 result = CHANNEL_RC_NO_MEMORY;
4878 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4879 if (rc != SCARD_S_SUCCESS)
4881 result = ERROR_INTERNAL_ERROR;
4885 result = rdpdr_server_send_device_control_request(
4886 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4887 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4891 if (result != CHANNEL_RC_OK)
4892 rdpdr_server_discard_request(context, irp->CompletionId);
4900static UINT rdpdr_server_smartcard_list_readersA(RdpdrServerContext* context,
void* callbackData,
4903 return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSA,
4904 call, completionId);
4908static UINT rdpdr_server_smartcard_list_readersW(RdpdrServerContext* context,
void* callbackData,
4911 return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSW,
4912 call, completionId);
4917static UINT rdpdr_server_smartcard_get_status_change_callback(RdpdrServerContext* context,
4919 UINT32 deviceId, UINT32 completionId,
4922 WINPR_ASSERT(context);
4923 WINPR_ASSERT(context->priv);
4927 UINT result = CHANNEL_RC_OK;
4928 RdpdrServerPrivate* priv = context->priv;
4931 WLog_Print(priv->log, WLOG_DEBUG,
4932 "SmartcardGetStatusChangeCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4933 ", ioStatus=0x%" PRIx32,
4934 deviceId, completionId, ioStatus);
4936 if (ioStatus != STATUS_SUCCESS)
4938 if (context->OnSmartcardGetStatusChangeComplete)
4939 context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
4940 SCARD_F_INTERNAL_ERROR,
nullptr);
4944 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4945 if (rc != SCARD_S_SUCCESS)
4947 result = ERROR_INVALID_DATA;
4951 if (context->OnSmartcardGetStatusChangeComplete)
4952 context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
4956 smartcard_operation_free(&op, FALSE);
4957 rdpdr_server_irp_free(irp);
4962static UINT rdpdr_server_smartcard_get_status_change(RdpdrServerContext* context,
4963 void* callbackData, UINT32 ioControlCode,
4964 const void* call, DWORD cReaders,
4965 UINT32* completionId)
4967 WINPR_ASSERT(context);
4968 WINPR_ASSERT(context->priv);
4970 WINPR_ASSERT(completionId);
4972 RdpdrServerPrivate* priv = context->priv;
4973 RDPDR_IRP* irp =
nullptr;
4975 UINT result = prepare_smartcard_irp(context, ioControlCode,
4976 rdpdr_server_smartcard_get_status_change_callback,
4977 callbackData, &irp);
4978 if (result != CHANNEL_RC_OK)
4982 *completionId = irp->CompletionId;
4985 op.ioControlCode = ioControlCode;
4987 switch (ioControlCode)
4989 case SCARD_IOCTL_GETSTATUSCHANGEA:
4992 case SCARD_IOCTL_GETSTATUSCHANGEW:
4996 WINPR_ASSERT(FALSE);
4997 return ERROR_INVALID_PARAMETER;
5000 wStream* s = Stream_New(
nullptr, 256 + cReaders * 256);
5003 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5004 result = CHANNEL_RC_NO_MEMORY;
5008 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5009 if (rc != SCARD_S_SUCCESS)
5011 result = ERROR_INTERNAL_ERROR;
5015 result = rdpdr_server_send_device_control_request(
5016 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5017 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5021 if (result != CHANNEL_RC_OK)
5022 rdpdr_server_discard_request(context, irp->CompletionId);
5030static UINT rdpdr_server_smartcard_get_status_changeA(RdpdrServerContext* context,
5033 UINT32* completionId)
5035 return rdpdr_server_smartcard_get_status_change(
5036 context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEA, call, call->cReaders, completionId);
5040static UINT rdpdr_server_smartcard_get_status_changeW(RdpdrServerContext* context,
5043 UINT32* completionId)
5045 return rdpdr_server_smartcard_get_status_change(
5046 context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEW, call, call->cReaders, completionId);
5051static UINT rdpdr_server_smartcard_cancel_callback(RdpdrServerContext* context,
wStream* s,
5052 RDPDR_IRP* irp, UINT32 deviceId,
5053 UINT32 completionId, UINT32 ioStatus)
5055 WINPR_ASSERT(context);
5056 WINPR_ASSERT(context->priv);
5060 UINT result = CHANNEL_RC_OK;
5061 RdpdrServerPrivate* priv = context->priv;
5064 WLog_Print(priv->log, WLOG_DEBUG,
5065 "SmartcardCancelCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5066 ", ioStatus=0x%" PRIx32,
5067 deviceId, completionId, ioStatus);
5069 if (ioStatus != STATUS_SUCCESS)
5071 if (context->OnSmartcardCancelComplete)
5072 context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus,
5073 SCARD_F_INTERNAL_ERROR);
5077 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5078 if (rc != SCARD_S_SUCCESS)
5080 result = ERROR_INVALID_DATA;
5084 if (context->OnSmartcardCancelComplete)
5085 context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
5088 smartcard_operation_free(&op, FALSE);
5089 rdpdr_server_irp_free(irp);
5094static UINT rdpdr_server_smartcard_cancel(RdpdrServerContext* context,
void* callbackData,
5097 WINPR_ASSERT(context);
5098 WINPR_ASSERT(context->priv);
5099 WINPR_ASSERT(hContext);
5100 WINPR_ASSERT(completionId);
5102 RdpdrServerPrivate* priv = context->priv;
5103 RDPDR_IRP* irp =
nullptr;
5105 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_CANCEL,
5106 rdpdr_server_smartcard_cancel_callback, callbackData, &irp);
5107 if (result != CHANNEL_RC_OK)
5111 *completionId = irp->CompletionId;
5114 .ioControlCode = SCARD_IOCTL_CANCEL,
5115 .call.context.handles.hContext = *hContext,
5118 wStream* s = Stream_New(
nullptr, 64);
5121 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5122 result = CHANNEL_RC_NO_MEMORY;
5126 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5127 if (rc != SCARD_S_SUCCESS)
5129 result = ERROR_INTERNAL_ERROR;
5133 result = rdpdr_server_send_device_control_request(
5134 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5135 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5139 if (result != CHANNEL_RC_OK)
5140 rdpdr_server_discard_request(context, irp->CompletionId);
5149static UINT rdpdr_server_smartcard_connect_callback(RdpdrServerContext* context,
wStream* s,
5150 RDPDR_IRP* irp, UINT32 deviceId,
5151 UINT32 completionId, UINT32 ioStatus)
5153 WINPR_ASSERT(context);
5154 WINPR_ASSERT(context->priv);
5158 UINT result = CHANNEL_RC_OK;
5159 RdpdrServerPrivate* priv = context->priv;
5162 WLog_Print(priv->log, WLOG_DEBUG,
5163 "SmartcardConnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5164 ", ioStatus=0x%" PRIx32,
5165 deviceId, completionId, ioStatus);
5167 if (ioStatus != STATUS_SUCCESS)
5169 if (context->OnSmartcardConnectComplete)
5170 context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus,
5171 SCARD_F_INTERNAL_ERROR,
nullptr);
5175 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5176 if (rc != SCARD_S_SUCCESS)
5178 result = ERROR_INVALID_DATA;
5182 if (context->OnSmartcardConnectComplete)
5183 context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5187 smartcard_operation_free(&op, FALSE);
5188 rdpdr_server_irp_free(irp);
5193static UINT rdpdr_server_smartcard_connect(RdpdrServerContext* context,
void* callbackData,
5194 UINT32 ioControlCode,
const void* call,
5195 UINT32* completionId)
5197 WINPR_ASSERT(context);
5198 WINPR_ASSERT(context->priv);
5200 WINPR_ASSERT(completionId);
5202 RdpdrServerPrivate* priv = context->priv;
5203 RDPDR_IRP* irp =
nullptr;
5205 UINT result = prepare_smartcard_irp(
5206 context, ioControlCode, rdpdr_server_smartcard_connect_callback, callbackData, &irp);
5207 if (result != CHANNEL_RC_OK)
5211 *completionId = irp->CompletionId;
5214 op.ioControlCode = ioControlCode;
5216 switch (ioControlCode)
5218 case SCARD_IOCTL_CONNECTA:
5221 case SCARD_IOCTL_CONNECTW:
5225 WINPR_ASSERT(FALSE);
5226 return ERROR_INVALID_PARAMETER;
5229 wStream* s = Stream_New(
nullptr, 512);
5232 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5233 result = CHANNEL_RC_NO_MEMORY;
5237 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5238 if (rc != SCARD_S_SUCCESS)
5240 result = ERROR_INTERNAL_ERROR;
5244 result = rdpdr_server_send_device_control_request(
5245 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5246 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5250 if (result != CHANNEL_RC_OK)
5251 rdpdr_server_discard_request(context, irp->CompletionId);
5259static UINT rdpdr_server_smartcard_connectA(RdpdrServerContext* context,
void* callbackData,
5262 return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTA, call,
5267static UINT rdpdr_server_smartcard_connectW(RdpdrServerContext* context,
void* callbackData,
5270 return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTW, call,
5276static UINT rdpdr_server_smartcard_reconnect_callback(RdpdrServerContext* context,
wStream* s,
5277 RDPDR_IRP* irp, UINT32 deviceId,
5278 UINT32 completionId, UINT32 ioStatus)
5280 WINPR_ASSERT(context);
5281 WINPR_ASSERT(context->priv);
5285 UINT result = CHANNEL_RC_OK;
5286 RdpdrServerPrivate* priv = context->priv;
5289 WLog_Print(priv->log, WLOG_DEBUG,
5290 "SmartcardReconnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5291 ", ioStatus=0x%" PRIx32,
5292 deviceId, completionId, ioStatus);
5294 if (ioStatus != STATUS_SUCCESS)
5296 if (context->OnSmartcardReconnectComplete)
5297 context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus,
5298 SCARD_F_INTERNAL_ERROR,
nullptr);
5302 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5303 if (rc != SCARD_S_SUCCESS)
5305 result = ERROR_INVALID_DATA;
5309 if (context->OnSmartcardReconnectComplete)
5310 context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5314 smartcard_operation_free(&op, FALSE);
5315 rdpdr_server_irp_free(irp);
5320static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context,
void* callbackData,
5323 WINPR_ASSERT(context);
5324 WINPR_ASSERT(context->priv);
5326 WINPR_ASSERT(completionId);
5328 RdpdrServerPrivate* priv = context->priv;
5329 RDPDR_IRP* irp =
nullptr;
5332 prepare_smartcard_irp(context, SCARD_IOCTL_RECONNECT,
5333 rdpdr_server_smartcard_reconnect_callback, callbackData, &irp);
5334 if (result != CHANNEL_RC_OK)
5338 *completionId = irp->CompletionId;
5342 .handles.hContext = call->handles.hContext,
5343 .handles.hCard = call->handles.hCard,
5344 .dwShareMode = call->dwShareMode,
5345 .dwPreferredProtocols = call->dwPreferredProtocols,
5346 .dwInitialization = call->dwInitialization,
5349 wStream* s = Stream_New(
nullptr, 128);
5352 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5353 result = CHANNEL_RC_NO_MEMORY;
5357 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5358 if (rc != SCARD_S_SUCCESS)
5360 result = ERROR_INTERNAL_ERROR;
5364 result = rdpdr_server_send_device_control_request(
5365 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5366 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5370 if (result != CHANNEL_RC_OK)
5371 rdpdr_server_discard_request(context, irp->CompletionId);
5380static UINT rdpdr_server_smartcard_disconnect_callback(RdpdrServerContext* context,
wStream* s,
5381 RDPDR_IRP* irp, UINT32 deviceId,
5382 UINT32 completionId, UINT32 ioStatus)
5384 WINPR_ASSERT(context);
5385 WINPR_ASSERT(context->priv);
5389 UINT result = CHANNEL_RC_OK;
5390 RdpdrServerPrivate* priv = context->priv;
5393 WLog_Print(priv->log, WLOG_DEBUG,
5394 "SmartcardDisconnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5395 ", ioStatus=0x%" PRIx32,
5396 deviceId, completionId, ioStatus);
5398 if (ioStatus != STATUS_SUCCESS)
5400 if (context->OnSmartcardDisconnectComplete)
5401 context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus,
5402 SCARD_F_INTERNAL_ERROR);
5406 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5407 if (rc != SCARD_S_SUCCESS)
5409 result = ERROR_INVALID_DATA;
5413 if (context->OnSmartcardDisconnectComplete)
5414 context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
5417 smartcard_operation_free(&op, FALSE);
5418 rdpdr_server_irp_free(irp);
5423static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context,
void* callbackData,
5425 UINT32* completionId)
5427 WINPR_ASSERT(context);
5428 WINPR_ASSERT(context->priv);
5430 WINPR_ASSERT(completionId);
5432 RdpdrServerPrivate* priv = context->priv;
5433 RDPDR_IRP* irp =
nullptr;
5436 prepare_smartcard_irp(context, SCARD_IOCTL_DISCONNECT,
5437 rdpdr_server_smartcard_disconnect_callback, callbackData, &irp);
5438 if (result != CHANNEL_RC_OK)
5442 *completionId = irp->CompletionId;
5445 .call.hCardAndDisposition = {
5446 .handles.hContext = call->handles.hContext,
5447 .handles.hCard = call->handles.hCard,
5448 .dwDisposition = call->dwDisposition,
5451 wStream* s = Stream_New(
nullptr, 128);
5454 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5455 result = CHANNEL_RC_NO_MEMORY;
5459 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5460 if (rc != SCARD_S_SUCCESS)
5462 result = ERROR_INTERNAL_ERROR;
5466 result = rdpdr_server_send_device_control_request(
5467 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5468 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5472 if (result != CHANNEL_RC_OK)
5473 rdpdr_server_discard_request(context, irp->CompletionId);
5482static UINT rdpdr_server_smartcard_begin_transaction_callback(RdpdrServerContext* context,
5484 UINT32 deviceId, UINT32 completionId,
5487 WINPR_ASSERT(context);
5488 WINPR_ASSERT(context->priv);
5492 UINT result = CHANNEL_RC_OK;
5493 RdpdrServerPrivate* priv = context->priv;
5496 WLog_Print(priv->log, WLOG_DEBUG,
5497 "SmartcardBeginTransactionCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5498 ", ioStatus=0x%" PRIx32,
5499 deviceId, completionId, ioStatus);
5501 if (ioStatus != STATUS_SUCCESS)
5503 if (context->OnSmartcardBeginTransactionComplete)
5504 context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
5505 SCARD_F_INTERNAL_ERROR);
5509 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5510 if (rc != SCARD_S_SUCCESS)
5512 result = ERROR_INVALID_DATA;
5516 if (context->OnSmartcardBeginTransactionComplete)
5517 context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
5521 smartcard_operation_free(&op, FALSE);
5522 rdpdr_server_irp_free(irp);
5527static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context,
5530 UINT32* completionId)
5532 WINPR_ASSERT(context);
5533 WINPR_ASSERT(context->priv);
5535 WINPR_ASSERT(completionId);
5537 RdpdrServerPrivate* priv = context->priv;
5538 RDPDR_IRP* irp =
nullptr;
5540 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_BEGINTRANSACTION,
5541 rdpdr_server_smartcard_begin_transaction_callback,
5542 callbackData, &irp);
5543 if (result != CHANNEL_RC_OK)
5547 *completionId = irp->CompletionId;
5550 .call.hCardAndDisposition = {
5551 .handles.hContext = call->handles.hContext,
5552 .handles.hCard = call->handles.hCard,
5553 .dwDisposition = SCARD_LEAVE_CARD,
5556 wStream* s = Stream_New(
nullptr, 128);
5559 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5560 result = CHANNEL_RC_NO_MEMORY;
5564 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5565 if (rc != SCARD_S_SUCCESS)
5567 result = ERROR_INTERNAL_ERROR;
5571 result = rdpdr_server_send_device_control_request(
5572 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5573 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5577 if (result != CHANNEL_RC_OK)
5578 rdpdr_server_discard_request(context, irp->CompletionId);
5587static UINT rdpdr_server_smartcard_end_transaction_callback(RdpdrServerContext* context,
wStream* s,
5588 RDPDR_IRP* irp, UINT32 deviceId,
5589 UINT32 completionId, UINT32 ioStatus)
5591 WINPR_ASSERT(context);
5592 WINPR_ASSERT(context->priv);
5596 UINT result = CHANNEL_RC_OK;
5597 RdpdrServerPrivate* priv = context->priv;
5600 WLog_Print(priv->log, WLOG_DEBUG,
5601 "SmartcardEndTransactionCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5602 ", ioStatus=0x%" PRIx32,
5603 deviceId, completionId, ioStatus);
5605 if (ioStatus != STATUS_SUCCESS)
5607 if (context->OnSmartcardEndTransactionComplete)
5608 context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
5609 SCARD_F_INTERNAL_ERROR);
5613 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5614 if (rc != SCARD_S_SUCCESS)
5616 result = ERROR_INVALID_DATA;
5620 if (context->OnSmartcardEndTransactionComplete)
5621 context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
5625 smartcard_operation_free(&op, FALSE);
5626 rdpdr_server_irp_free(irp);
5631static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context,
void* callbackData,
5633 UINT32* completionId)
5635 WINPR_ASSERT(context);
5636 WINPR_ASSERT(context->priv);
5638 WINPR_ASSERT(completionId);
5640 RdpdrServerPrivate* priv = context->priv;
5641 RDPDR_IRP* irp =
nullptr;
5644 prepare_smartcard_irp(context, SCARD_IOCTL_ENDTRANSACTION,
5645 rdpdr_server_smartcard_end_transaction_callback, callbackData, &irp);
5646 if (result != CHANNEL_RC_OK)
5650 *completionId = irp->CompletionId;
5653 .call.hCardAndDisposition = {
5654 .handles.hContext = call->handles.hContext,
5655 .handles.hCard = call->handles.hCard,
5656 .dwDisposition = call->dwDisposition,
5659 wStream* s = Stream_New(
nullptr, 128);
5662 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5663 result = CHANNEL_RC_NO_MEMORY;
5667 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5668 if (rc != SCARD_S_SUCCESS)
5670 result = ERROR_INTERNAL_ERROR;
5674 result = rdpdr_server_send_device_control_request(
5675 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5676 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5680 if (result != CHANNEL_RC_OK)
5681 rdpdr_server_discard_request(context, irp->CompletionId);
5690static UINT rdpdr_server_smartcard_status_callback(RdpdrServerContext* context,
wStream* s,
5691 RDPDR_IRP* irp, UINT32 deviceId,
5692 UINT32 completionId, UINT32 ioStatus)
5694 WINPR_ASSERT(context);
5695 WINPR_ASSERT(context->priv);
5699 UINT result = CHANNEL_RC_OK;
5700 RdpdrServerPrivate* priv = context->priv;
5703 WLog_Print(priv->log, WLOG_DEBUG,
5704 "SmartcardStatusCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5705 ", ioStatus=0x%" PRIx32,
5706 deviceId, completionId, ioStatus);
5708 if (ioStatus != STATUS_SUCCESS)
5710 if (context->OnSmartcardStatusComplete)
5711 context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus,
5712 SCARD_F_INTERNAL_ERROR,
nullptr);
5716 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5717 if (rc != SCARD_S_SUCCESS)
5719 result = ERROR_INVALID_DATA;
5723 if (context->OnSmartcardStatusComplete)
5724 context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5728 smartcard_operation_free(&op, FALSE);
5729 rdpdr_server_irp_free(irp);
5734static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context,
void* callbackData,
5736 UINT32* completionId)
5738 WINPR_ASSERT(context);
5739 WINPR_ASSERT(context->priv);
5741 WINPR_ASSERT(completionId);
5743 RdpdrServerPrivate* priv = context->priv;
5744 RDPDR_IRP* irp =
nullptr;
5746 UINT result = prepare_smartcard_irp(context, ioControlCode,
5747 rdpdr_server_smartcard_status_callback, callbackData, &irp);
5748 if (result != CHANNEL_RC_OK)
5752 *completionId = irp->CompletionId;
5756 .handles.hContext = call->handles.hContext,
5757 .handles.hCard = call->handles.hCard,
5758 .fmszReaderNamesIsNULL = call->fmszReaderNamesIsNULL,
5759 .cchReaderLen = call->cchReaderLen,
5760 .cbAtrLen = call->cbAtrLen,
5763 wStream* s = Stream_New(
nullptr, 128);
5766 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5767 result = CHANNEL_RC_NO_MEMORY;
5771 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5772 if (rc != SCARD_S_SUCCESS)
5774 result = ERROR_INTERNAL_ERROR;
5778 result = rdpdr_server_send_device_control_request(
5779 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5780 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5784 if (result != CHANNEL_RC_OK)
5785 rdpdr_server_discard_request(context, irp->CompletionId);
5793static UINT rdpdr_server_smartcard_statusA(RdpdrServerContext* context,
void* callbackData,
5796 return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSA, call,
5801static UINT rdpdr_server_smartcard_statusW(RdpdrServerContext* context,
void* callbackData,
5804 return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSW, call,
5810static UINT rdpdr_server_smartcard_transmit_callback(RdpdrServerContext* context,
wStream* s,
5811 RDPDR_IRP* irp, UINT32 deviceId,
5812 UINT32 completionId, UINT32 ioStatus)
5814 WINPR_ASSERT(context);
5815 WINPR_ASSERT(context->priv);
5819 UINT result = CHANNEL_RC_OK;
5820 RdpdrServerPrivate* priv = context->priv;
5823 WLog_Print(priv->log, WLOG_DEBUG,
5824 "SmartcardTransmitCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5825 ", ioStatus=0x%" PRIx32,
5826 deviceId, completionId, ioStatus);
5828 if (ioStatus != STATUS_SUCCESS)
5830 if (context->OnSmartcardTransmitComplete)
5831 context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus,
5832 SCARD_F_INTERNAL_ERROR,
nullptr);
5836 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5837 if (rc != SCARD_S_SUCCESS)
5839 result = ERROR_INVALID_DATA;
5843 if (context->OnSmartcardTransmitComplete)
5844 context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5848 smartcard_operation_free(&op, FALSE);
5849 rdpdr_server_irp_free(irp);
5854static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context,
void* callbackData,
5857 WINPR_ASSERT(context);
5858 WINPR_ASSERT(context->priv);
5860 WINPR_ASSERT(completionId);
5862 RdpdrServerPrivate* priv = context->priv;
5863 RDPDR_IRP* irp =
nullptr;
5866 prepare_smartcard_irp(context, SCARD_IOCTL_TRANSMIT,
5867 rdpdr_server_smartcard_transmit_callback, callbackData, &irp);
5868 if (result != CHANNEL_RC_OK)
5872 *completionId = irp->CompletionId;
5875 .call.transmit = *call };
5877 wStream* s = Stream_New(
nullptr, 512 + call->cbSendLength);
5880 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5881 result = CHANNEL_RC_NO_MEMORY;
5885 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5886 if (rc != SCARD_S_SUCCESS)
5888 result = ERROR_INTERNAL_ERROR;
5892 result = rdpdr_server_send_device_control_request(
5893 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5894 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5898 if (result != CHANNEL_RC_OK)
5899 rdpdr_server_discard_request(context, irp->CompletionId);
5908static UINT rdpdr_server_smartcard_control_callback(RdpdrServerContext* context,
wStream* s,
5909 RDPDR_IRP* irp, UINT32 deviceId,
5910 UINT32 completionId, UINT32 ioStatus)
5912 WINPR_ASSERT(context);
5913 WINPR_ASSERT(context->priv);
5917 UINT result = CHANNEL_RC_OK;
5918 RdpdrServerPrivate* priv = context->priv;
5921 WLog_Print(priv->log, WLOG_DEBUG,
5922 "SmartcardControlCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5923 ", ioStatus=0x%" PRIx32,
5924 deviceId, completionId, ioStatus);
5926 if (ioStatus != STATUS_SUCCESS)
5928 if (context->OnSmartcardControlComplete)
5929 context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus,
5930 SCARD_F_INTERNAL_ERROR,
nullptr);
5934 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5935 if (rc != SCARD_S_SUCCESS)
5937 result = ERROR_INVALID_DATA;
5941 if (context->OnSmartcardControlComplete)
5942 context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5946 smartcard_operation_free(&op, FALSE);
5947 rdpdr_server_irp_free(irp);
5952static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context,
void* callbackData,
5955 WINPR_ASSERT(context);
5956 WINPR_ASSERT(context->priv);
5958 WINPR_ASSERT(completionId);
5960 RdpdrServerPrivate* priv = context->priv;
5961 RDPDR_IRP* irp =
nullptr;
5963 UINT result = prepare_smartcard_irp(
5964 context, SCARD_IOCTL_CONTROL, rdpdr_server_smartcard_control_callback, callbackData, &irp);
5965 if (result != CHANNEL_RC_OK)
5969 *completionId = irp->CompletionId;
5973 .handles.hContext = call->handles.hContext,
5974 .handles.hCard = call->handles.hCard,
5975 .dwControlCode = call->dwControlCode,
5976 .cbInBufferSize = call->cbInBufferSize,
5977 .pvInBuffer = call->pvInBuffer,
5978 .fpvOutBufferIsNULL = call->fpvOutBufferIsNULL,
5979 .cbOutBufferSize = call->cbOutBufferSize,
5982 wStream* s = Stream_New(
nullptr, 512 + call->cbOutBufferSize);
5985 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5986 result = CHANNEL_RC_NO_MEMORY;
5990 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5991 if (rc != SCARD_S_SUCCESS)
5993 result = ERROR_INTERNAL_ERROR;
5997 result = rdpdr_server_send_device_control_request(
5998 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5999 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
6003 if (result != CHANNEL_RC_OK)
6004 rdpdr_server_discard_request(context, irp->CompletionId);
6013static UINT rdpdr_server_smartcard_get_attrib_callback(RdpdrServerContext* context,
wStream* s,
6014 RDPDR_IRP* irp, UINT32 deviceId,
6015 UINT32 completionId, UINT32 ioStatus)
6017 WINPR_ASSERT(context);
6018 WINPR_ASSERT(context->priv);
6022 UINT result = CHANNEL_RC_OK;
6023 RdpdrServerPrivate* priv = context->priv;
6026 WLog_Print(priv->log, WLOG_DEBUG,
6027 "SmartcardGetAttribCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
6028 ", ioStatus=0x%" PRIx32,
6029 deviceId, completionId, ioStatus);
6031 if (ioStatus != STATUS_SUCCESS)
6033 if (context->OnSmartcardGetAttribComplete)
6034 context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus,
6035 SCARD_F_INTERNAL_ERROR,
nullptr);
6039 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
6040 if (rc != SCARD_S_SUCCESS)
6042 result = ERROR_INVALID_DATA;
6046 if (context->OnSmartcardGetAttribComplete)
6047 context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
6051 smartcard_operation_free(&op, FALSE);
6052 rdpdr_server_irp_free(irp);
6057static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context,
void* callbackData,
6060 WINPR_ASSERT(context);
6061 WINPR_ASSERT(context->priv);
6063 WINPR_ASSERT(completionId);
6065 RdpdrServerPrivate* priv = context->priv;
6067 RDPDR_IRP* irp =
nullptr;
6069 prepare_smartcard_irp(context, SCARD_IOCTL_GETATTRIB,
6070 rdpdr_server_smartcard_get_attrib_callback, callbackData, &irp);
6071 if (ret != CHANNEL_RC_OK)
6075 *completionId = irp->CompletionId;
6078 .call.getAttrib = *call };
6080 UINT error = CHANNEL_RC_NO_MEMORY;
6081 wStream* s = Stream_New(
nullptr, 64);
6084 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
6088 LONG status = smartcard_irp_device_control_encode_request(s, &op);
6089 if (status != SCARD_S_SUCCESS)
6091 error = ERROR_INTERNAL_ERROR;
6095 error = rdpdr_server_send_device_control_request(
6096 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
6097 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
6101 if (error != CHANNEL_RC_OK && irp)
6102 rdpdr_server_discard_request(context, irp->CompletionId);
6111static UINT rdpdr_server_smartcard_set_attrib_callback(RdpdrServerContext* context,
wStream* s,
6112 RDPDR_IRP* irp, UINT32 deviceId,
6113 UINT32 completionId, UINT32 ioStatus)
6115 WINPR_ASSERT(context);
6116 WINPR_ASSERT(context->priv);
6120 UINT result = CHANNEL_RC_OK;
6121 RdpdrServerPrivate* priv = context->priv;
6124 WLog_Print(priv->log, WLOG_DEBUG,
6125 "SmartcardSetAttribCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
6126 ", ioStatus=0x%" PRIx32,
6127 deviceId, completionId, ioStatus);
6129 if (ioStatus != STATUS_SUCCESS)
6131 if (context->OnSmartcardSetAttribComplete)
6132 context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus,
6133 SCARD_F_INTERNAL_ERROR);
6137 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
6138 if (rc != SCARD_S_SUCCESS)
6140 result = ERROR_INVALID_DATA;
6144 if (context->OnSmartcardSetAttribComplete)
6145 context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
6148 smartcard_operation_free(&op, FALSE);
6149 rdpdr_server_irp_free(irp);
6154static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context,
void* callbackData,
6157 WINPR_ASSERT(context);
6158 WINPR_ASSERT(context->priv);
6160 WINPR_ASSERT(completionId);
6162 RdpdrServerPrivate* priv = context->priv;
6163 RDPDR_IRP* irp =
nullptr;
6166 prepare_smartcard_irp(context, SCARD_IOCTL_SETATTRIB,
6167 rdpdr_server_smartcard_set_attrib_callback, callbackData, &irp);
6168 if (result != CHANNEL_RC_OK)
6172 *completionId = irp->CompletionId;
6176 .handles.hContext = call->handles.hContext,
6177 .handles.hCard = call->handles.hCard,
6178 .dwAttrId = call->dwAttrId,
6179 .cbAttrLen = call->cbAttrLen,
6180 .pbAttr = call->pbAttr,
6183 wStream* s = Stream_New(
nullptr, 64 + call->cbAttrLen);
6186 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
6187 result = CHANNEL_RC_NO_MEMORY;
6191 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
6192 if (rc != SCARD_S_SUCCESS)
6194 result = ERROR_INTERNAL_ERROR;
6198 result = rdpdr_server_send_device_control_request(
6199 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
6200 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
6204 if (result != CHANNEL_RC_OK)
6205 rdpdr_server_discard_request(context, irp->CompletionId);
6212RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
6214 RdpdrServerContext* context = (RdpdrServerContext*)calloc(1,
sizeof(RdpdrServerContext));
6220 context->Start = rdpdr_server_start;
6221 context->Stop = rdpdr_server_stop;
6222 context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
6223 context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
6224 context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
6225 context->DriveOpenFile = rdpdr_server_drive_open_file;
6226 context->DriveReadFile = rdpdr_server_drive_read_file;
6227 context->DriveWriteFile = rdpdr_server_drive_write_file;
6228 context->DriveCloseFile = rdpdr_server_drive_close_file;
6229 context->DriveDeleteFile = rdpdr_server_drive_delete_file;
6230 context->DriveRenameFile = rdpdr_server_drive_rename_file;
6231 context->DriveReadFileEx = rdpdr_server_drive_read_file_ex;
6232 context->DriveWriteFileEx = rdpdr_server_drive_write_file_ex;
6233 context->DriveRenameFileEx = rdpdr_server_drive_rename_file_ex;
6234 context->DriveSetFileSize = rdpdr_server_drive_set_file_size;
6235 context->DriveSetFileTimes = rdpdr_server_drive_set_file_times;
6236 context->DriveQueryVolumeInformation = rdpdr_server_drive_query_volume_information;
6237 context->SmartcardEstablishContext = rdpdr_server_smartcard_establish_context;
6238 context->SmartcardReleaseContext = rdpdr_server_smartcard_release_context;
6239 context->SmartcardIsValidContext = rdpdr_server_smartcard_is_valid_context;
6240 context->SmartcardListReaderGroupsA = rdpdr_server_smartcard_list_reader_groupsA;
6241 context->SmartcardListReaderGroupsW = rdpdr_server_smartcard_list_reader_groupsW;
6242 context->SmartcardListReadersA = rdpdr_server_smartcard_list_readersA;
6243 context->SmartcardListReadersW = rdpdr_server_smartcard_list_readersW;
6244 context->SmartcardGetStatusChangeA = rdpdr_server_smartcard_get_status_changeA;
6245 context->SmartcardGetStatusChangeW = rdpdr_server_smartcard_get_status_changeW;
6246 context->SmartcardCancel = rdpdr_server_smartcard_cancel;
6247 context->SmartcardConnectA = rdpdr_server_smartcard_connectA;
6248 context->SmartcardConnectW = rdpdr_server_smartcard_connectW;
6249 context->SmartcardReconnect = rdpdr_server_smartcard_reconnect;
6250 context->SmartcardDisconnect = rdpdr_server_smartcard_disconnect;
6251 context->SmartcardBeginTransaction = rdpdr_server_smartcard_begin_transaction;
6252 context->SmartcardEndTransaction = rdpdr_server_smartcard_end_transaction;
6253 context->SmartcardStatusA = rdpdr_server_smartcard_statusA;
6254 context->SmartcardStatusW = rdpdr_server_smartcard_statusW;
6255 context->SmartcardTransmit = rdpdr_server_smartcard_transmit;
6256 context->SmartcardControl = rdpdr_server_smartcard_control;
6257 context->SmartcardGetAttrib = rdpdr_server_smartcard_get_attrib;
6258 context->SmartcardSetAttrib = rdpdr_server_smartcard_set_attrib;
6259 context->priv = rdpdr_server_private_new();
6264 context->supported = UINT16_MAX;
6268 WINPR_PRAGMA_DIAG_PUSH
6269 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
6270 rdpdr_server_context_free(context);
6271 WINPR_PRAGMA_DIAG_POP
6275void rdpdr_server_context_free(RdpdrServerContext* context)
6280 rdpdr_server_private_free(context->priv);
6284void rdpdr_server_discard_request(RdpdrServerContext* context, UINT32 completionId)
6286 WINPR_ASSERT(context);
6288 RdpdrServerPrivate* priv = context->priv;
6289 const uintptr_t key = completionId + 1ull;
6290 ListDictionary_Remove(priv->IrpList, (
void*)key);
union SMARTCARD_OPERATION::@41 ret
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
WINPR_ATTR_NODISCARD OBJECT_EQUALS_FN fnObjectEquals
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew