24#include <freerdp/config.h>
25#include <freerdp/freerdp.h>
26#include <freerdp/utils/rdpdr_utils.h>
29#include <winpr/assert.h>
31#include <winpr/print.h>
32#include <winpr/stream.h>
34#include <freerdp/channels/log.h>
35#include <freerdp/channels/scard.h>
36#include <freerdp/utils/smartcard_operations.h>
37#include "rdpdr_main.h"
38#include <freerdp/utils/channel_pdu_tracker.h>
40#define RDPDR_ADD_PRINTER_EVENT 0x00000001
41#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
42#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
43#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
45#define RDPDR_HEADER_LENGTH 4
46#define RDPDR_CAPABILITY_HEADER_LENGTH 8
49#define SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH 2048
51struct s_rdpdr_server_private
60 char* ClientComputerName;
64 wListDictionary* IrpList;
65 UINT32 NextCompletionId;
67 wHashTable* devicelist;
69 UINT32 SpecialDeviceTypeCap;
72 BOOL haveSmartcardDevice;
73 UINT32 smartcardDeviceId;
76static const char* fileInformation2str(uint8_t val)
81 return "FILE_DOES_NOT_EXIST";
85 return "FILE_OVERWRITTEN";
86 case FILE_OVERWRITTEN:
87 return "FILE_CREATED";
90 case FILE_DOES_NOT_EXIST:
91 return "FILE_SUPERSEDED";
93 return "FILE_UNKNOWN";
97static const char* DR_DRIVE_LOCK_REQ2str(uint32_t op)
101 case RDP_LOWIO_OP_SHAREDLOCK:
102 return "RDP_LOWIO_OP_UNLOCK_MULTIPLE";
103 case RDP_LOWIO_OP_EXCLUSIVELOCK:
104 return "RDP_LOWIO_OP_UNLOCK";
105 case RDP_LOWIO_OP_UNLOCK:
106 return "RDP_LOWIO_OP_EXCLUSIVELOCK";
107 case RDP_LOWIO_OP_UNLOCK_MULTIPLE:
108 return "RDP_LOWIO_OP_SHAREDLOCK";
110 return "RDP_LOWIO_OP_UNKNOWN";
118 free(device->DeviceData);
122static void rdpdr_device_free_h(
void* obj)
125 rdpdr_device_free(other);
128static UINT32 rdpdr_deviceid_hash(
const void*
id)
131 return *((
const UINT32*)
id);
134static BOOL rdpdr_device_equal(
const void* v1,
const void* v2)
136 const UINT32* p1 = (
const UINT32*)v1;
137 const UINT32* p2 = (
const UINT32*)v2;
150static void* rdpdr_device_clone(
const void* val)
162 if (other->DeviceData)
164 tmp->DeviceData = malloc(other->DeviceDataLength);
165 if (!tmp->DeviceData)
167 memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
172 rdpdr_device_free(tmp);
176static void* rdpdr_device_key_clone(
const void* pvval)
178 const UINT32* val = pvval;
182 UINT32* ptr = calloc(1,
sizeof(UINT32));
189static void rdpdr_device_key_free(
void* obj)
194static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
197 return HashTable_GetItemValue(priv->devicelist, &DeviceId);
200static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
204 const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
207 WLog_Print(priv->log, WLOG_WARN,
"[del] Device Id: 0x%08" PRIX32
": no such device",
211 WLog_Print(priv->log, WLOG_DEBUG,
212 "[del] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
213 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
214 return HashTable_Remove(priv->devicelist, &DeviceId);
217static BOOL rdpdr_add_device(RdpdrServerPrivate* priv,
const RdpdrDevice* device)
220 WINPR_ASSERT(device);
222 WLog_Print(priv->log, WLOG_DEBUG,
223 "[add] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
224 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
226 return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
229static UINT32 g_ClientId = 0;
231static const WCHAR* rdpdr_read_ustring(wLog* log,
wStream* s,
size_t bytelen)
233 const size_t charlen = bytelen /
sizeof(WCHAR);
234 const WCHAR* str = Stream_ConstPointer(s);
235 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, bytelen))
237 if (_wcsnlen(str, charlen) == charlen)
239 WLog_Print(log, WLOG_WARN,
"[rdpdr] unicode string not '\\0' terminated");
242 Stream_Seek(s, bytelen);
246static RDPDR_IRP* rdpdr_server_irp_new(
void)
248 RDPDR_IRP* irp = (RDPDR_IRP*)calloc(1,
sizeof(RDPDR_IRP));
252static void rdpdr_server_irp_free(RDPDR_IRP* irp)
257static void rdpdr_server_list_free(
void* ptr)
259 RDPDR_IRP* irp = ptr;
260 rdpdr_server_irp_free(irp);
262static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp)
264 WINPR_ASSERT(context);
265 WINPR_ASSERT(context->priv);
267 RdpdrServerPrivate* priv = context->priv;
268 const uintptr_t key = irp->CompletionId + 1ull;
269 return ListDictionary_Add(priv->IrpList, (
void*)key, irp);
272static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
274 WINPR_ASSERT(context);
275 WINPR_ASSERT(context->priv);
277 RdpdrServerPrivate* priv = context->priv;
278 const uintptr_t key = completionId + 1ull;
279 RDPDR_IRP* irp = (RDPDR_IRP*)ListDictionary_Take(priv->IrpList, (
void*)key);
283static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context,
wStream* s)
285 WINPR_ASSERT(context);
286 WINPR_ASSERT(context->priv);
289 RdpdrServerPrivate* priv = context->priv;
290 Stream_SealLength(s);
291 const size_t length = Stream_Length(s);
292 WINPR_ASSERT(length <= UINT32_MAX);
293 Stream_ResetPosition(s);
295 if (length >= RDPDR_HEADER_LENGTH)
299 .PacketId = Stream_Get_UINT16(s),
302 WLog_Print(priv->log, WLOG_DEBUG,
303 "sending message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
307 winpr_HexLogDump(priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
309 BOOL status = WTSVirtualChannelWrite(priv->ChannelHandle, Stream_BufferAs(s,
char),
310 (ULONG)length, &written);
312 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
320static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
322 WINPR_ASSERT(context);
323 WINPR_ASSERT(context->priv);
325 UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
326 if (error != CHANNEL_RC_OK)
329 RdpdrServerPrivate* priv = context->priv;
330 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
333 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
334 return CHANNEL_RC_NO_MEMORY;
339 .PacketId = PAKID_CORE_SERVER_ANNOUNCE,
341 Stream_Write_UINT16(s, header.
Component);
342 Stream_Write_UINT16(s, header.
PacketId);
343 Stream_Write_UINT16(s, priv->VersionMajor);
344 Stream_Write_UINT16(s, priv->VersionMinor);
345 Stream_Write_UINT32(s, priv->ClientId);
346 return rdpdr_seal_send_free_request(context, s);
354static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
wStream* s,
357 WINPR_ASSERT(context);
358 WINPR_ASSERT(context->priv);
359 WINPR_ASSERT(header);
361 RdpdrServerPrivate* priv = context->priv;
363 WINPR_UNUSED(header);
365 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
366 return ERROR_INVALID_DATA;
368 const UINT16 VersionMajor = Stream_Get_UINT16(s);
369 const UINT16 VersionMinor = Stream_Get_UINT16(s);
370 const UINT32 ClientId = Stream_Get_UINT32(s);
371 WLog_Print(priv->log, WLOG_DEBUG,
372 "Client Announce Response: VersionMajor: 0x%08" PRIX16
" VersionMinor: 0x%04" PRIX16
373 " ClientId: 0x%08" PRIX32
"",
374 VersionMajor, VersionMinor, ClientId);
375 priv->ClientId = ClientId;
377 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
378 VersionMinor, ClientId);
386static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context,
wStream* s,
389 WINPR_ASSERT(context);
390 WINPR_ASSERT(context->priv);
392 WINPR_ASSERT(header);
393 WINPR_UNUSED(header);
395 RdpdrServerPrivate* priv = context->priv;
397 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
398 return ERROR_INVALID_DATA;
400 UINT32 UnicodeFlag = Stream_Get_UINT32(s);
401 const UINT32 CodePage = Stream_Get_UINT32(s);
402 const UINT32 ComputerNameLen = Stream_Get_UINT32(s);
405 UnicodeFlag = UnicodeFlag & 0x00000001;
408 WLog_Print(priv->log, WLOG_WARN,
409 "[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
410 "must be 0, but is 0x%08" PRIx32,
420 if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
422 WLog_Print(priv->log, WLOG_ERROR,
"invalid unicode computer name length: %" PRIu32
"",
424 return ERROR_INVALID_DATA;
429 if (ComputerNameLen > 256 || ComputerNameLen < 1)
431 WLog_Print(priv->log, WLOG_ERROR,
"invalid ascii computer name length: %" PRIu32
"",
433 return ERROR_INVALID_DATA;
437 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, ComputerNameLen))
438 return ERROR_INVALID_DATA;
441 const char* computerName = Stream_ConstPointer(s);
442 if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
444 WLog_Print(priv->log, WLOG_ERROR,
"computer name must be null terminated");
445 return ERROR_INVALID_DATA;
448 if (priv->ClientComputerName)
450 free(priv->ClientComputerName);
451 priv->ClientComputerName =
nullptr;
456 priv->ClientComputerName =
457 Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen /
sizeof(WCHAR),
nullptr);
458 if (!priv->ClientComputerName)
460 WLog_Print(priv->log, WLOG_ERROR,
"failed to convert client computer name");
461 return ERROR_INVALID_DATA;
466 const char* name = Stream_ConstPointer(s);
467 priv->ClientComputerName = _strdup(name);
468 Stream_Seek(s, ComputerNameLen);
470 if (!priv->ClientComputerName)
472 WLog_Print(priv->log, WLOG_ERROR,
"failed to duplicate client computer name");
473 return CHANNEL_RC_NO_MEMORY;
477 WLog_Print(priv->log, WLOG_DEBUG,
"ClientComputerName: %s", priv->ClientComputerName);
478 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
479 priv->ClientComputerName);
482static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context,
wStream* s,
485 WINPR_ASSERT(context);
486 WINPR_ASSERT(context->priv);
488 RdpdrServerPrivate* priv = context->priv;
489 UINT error = rdpdr_write_capset_header(priv->log, s, header);
490 if (error != CHANNEL_RC_OK)
493 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0,
nullptr);
501static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context,
wStream* s,
504 WINPR_ASSERT(context);
505 WINPR_ASSERT(context->priv);
506 WINPR_ASSERT(header);
508 RdpdrServerPrivate* priv = context->priv;
510 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
511 return ERROR_INVALID_DATA;
513 const UINT32 OsType = Stream_Get_UINT32(s);
515 const UINT32 OsVersion = Stream_Get_UINT32(s);
517 const UINT32 VersionMajor = Stream_Get_UINT16(s);
518 const UINT32 VersionMinor = Stream_Get_UINT16(s);
519 const UINT32 IoCode1 = Stream_Get_UINT32(s);
520 const UINT32 IoCode2 = Stream_Get_UINT32(s);
522 const UINT32 ExtendedPdu = Stream_Get_UINT32(s);
523 const UINT32 ExtraFlags1 = Stream_Get_UINT32(s);
524 const UINT32 ExtraFlags2 = Stream_Get_UINT32(s);
528 char buffer[1024] = WINPR_C_ARRAY_INIT;
529 WLog_Print(priv->log, WLOG_TRACE,
530 "OsType=%" PRIu32
", OsVersion=%" PRIu32
", VersionMajor=%" PRIu32
531 ", VersionMinor=%" PRIu32
", IoCode1=%s, IoCode2=%" PRIu32
532 ", ExtendedPdu=%" PRIu32
", ExtraFlags1=%" PRIu32
", ExtraFlags2=%" PRIu32,
533 OsType, OsVersion, VersionMajor, VersionMinor,
534 rdpdr_irp_mask2str(IoCode1, buffer,
sizeof(buffer)), IoCode2, ExtendedPdu,
535 ExtraFlags1, ExtraFlags2);
538 if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
540 WLog_Print(priv->log, WLOG_ERROR,
"unsupported RDPDR version %" PRIu16
".%" PRIu16,
541 VersionMajor, VersionMinor);
542 return ERROR_INVALID_DATA;
545 switch (VersionMinor)
547 case RDPDR_MINOR_RDP_VERSION_13:
548 case RDPDR_MINOR_RDP_VERSION_6_X:
549 case RDPDR_MINOR_RDP_VERSION_5_2:
550 case RDPDR_MINOR_RDP_VERSION_5_1:
551 case RDPDR_MINOR_RDP_VERSION_5_0:
554 WLog_Print(priv->log, WLOG_WARN,
"unsupported RDPDR minor version %" PRIu16
".%" PRIu16,
555 VersionMajor, VersionMinor);
559 UINT32 SpecialTypeDeviceCap = 0;
560 if (header->Version == GENERAL_CAPABILITY_VERSION_02)
562 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
563 return ERROR_INVALID_DATA;
565 SpecialTypeDeviceCap = Stream_Get_UINT32(s);
567 priv->SpecialDeviceTypeCap = SpecialTypeDeviceCap;
570 RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ |
571 RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN |
572 RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION |
573 RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION |
574 RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL;
576 if ((IoCode1 & mask) == 0)
578 char buffer[1024] = WINPR_C_ARRAY_INIT;
579 WLog_Print(priv->log, WLOG_ERROR,
"Missing IRP mask values %s",
580 rdpdr_irp_mask2str(IoCode1 & mask, buffer,
sizeof(buffer)));
581 return ERROR_INVALID_DATA;
583 priv->IoCode1 = IoCode1;
587 WLog_Print(priv->log, WLOG_WARN,
588 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ioCode2 is "
589 "reserved for future use, expected value 0 got %" PRIu32,
593 if ((ExtendedPdu & RDPDR_CLIENT_DISPLAY_NAME_PDU) == 0)
595 WLog_Print(priv->log, WLOG_WARN,
596 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) extendedPDU "
597 "should always set RDPDR_CLIENT_DISPLAY_NAME_PDU[0x00000002]");
600 priv->ExtendedPDU = ExtendedPdu;
601 priv->UserLoggedOnPdu = (ExtendedPdu & RDPDR_USER_LOGGEDON_PDU) != 0;
603 if (ExtraFlags2 != 0)
605 WLog_Print(priv->log, WLOG_WARN,
606 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ExtraFlags2 is "
607 "reserved for future use, expected value 0 got %" PRIu32,
611 return CHANNEL_RC_OK;
619static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context,
wStream* s)
621 WINPR_ASSERT(context);
622 WINPR_ASSERT(context->priv);
625 GENERAL_CAPABILITY_VERSION_02 };
628 ioCode1 |= RDPDR_IRP_MJ_CREATE;
629 ioCode1 |= RDPDR_IRP_MJ_CLEANUP;
630 ioCode1 |= RDPDR_IRP_MJ_CLOSE;
631 ioCode1 |= RDPDR_IRP_MJ_READ;
632 ioCode1 |= RDPDR_IRP_MJ_WRITE;
633 ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS;
634 ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN;
635 ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL;
636 ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION;
637 ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION;
638 ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION;
639 ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION;
640 ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL;
641 ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL;
642 ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY;
643 ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY;
645 UINT32 extendedPdu = 0;
646 extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU;
647 extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS;
649 RdpdrServerPrivate* priv = context->priv;
650 if (priv->UserLoggedOnPdu)
651 extendedPdu |= RDPDR_USER_LOGGEDON_PDU;
653 UINT32 extraFlags1 = 0;
654 extraFlags1 |= ENABLE_ASYNCIO;
655 UINT32 SpecialTypeDeviceCap = 0;
657 UINT error = rdpdr_write_capset_header(priv->log, s, &header);
658 if (error != CHANNEL_RC_OK)
661 const BYTE* data = Stream_ConstPointer(s);
662 const size_t start = Stream_GetPosition(s);
663 Stream_Write_UINT32(s, 0);
664 Stream_Write_UINT32(s, 0);
665 Stream_Write_UINT16(s, priv->VersionMajor);
666 Stream_Write_UINT16(s, priv->VersionMinor);
667 Stream_Write_UINT32(s, ioCode1);
668 Stream_Write_UINT32(s, 0);
669 Stream_Write_UINT32(s, extendedPdu);
670 Stream_Write_UINT32(s, extraFlags1);
673 Stream_Write_UINT32(s, SpecialTypeDeviceCap);
674 const size_t end = Stream_GetPosition(s);
675 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
683static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context,
wStream* s,
686 WINPR_ASSERT(context);
687 WINPR_ASSERT(context->priv);
689 WINPR_ASSERT(header);
690 WINPR_UNUSED(context);
691 WINPR_UNUSED(header);
694 return CHANNEL_RC_OK;
702static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context,
wStream* s)
704 WINPR_UNUSED(context);
705 WINPR_ASSERT(context);
706 WINPR_ASSERT(context->priv);
709 PRINT_CAPABILITY_VERSION_01 };
711 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
719static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context,
wStream* s,
722 WINPR_UNUSED(context);
724 WINPR_UNUSED(header);
725 WINPR_ASSERT(context);
726 WINPR_ASSERT(context->priv);
728 return CHANNEL_RC_OK;
736static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
wStream* s)
738 WINPR_UNUSED(context);
739 WINPR_ASSERT(context);
740 WINPR_ASSERT(context->priv);
743 PORT_CAPABILITY_VERSION_01 };
745 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
753static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
wStream* s,
756 WINPR_ASSERT(context);
757 WINPR_ASSERT(context->priv);
758 WINPR_UNUSED(context);
759 WINPR_UNUSED(header);
762 return CHANNEL_RC_OK;
770static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
wStream* s)
772 WINPR_ASSERT(context);
773 WINPR_ASSERT(context->priv);
774 WINPR_UNUSED(context);
777 DRIVE_CAPABILITY_VERSION_02 };
779 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
787static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context,
wStream* s,
790 WINPR_ASSERT(context);
791 WINPR_ASSERT(context->priv);
792 WINPR_UNUSED(context);
793 WINPR_UNUSED(header);
796 return CHANNEL_RC_OK;
804static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context,
wStream* s)
806 WINPR_ASSERT(context);
807 WINPR_ASSERT(context->priv);
808 WINPR_UNUSED(context);
811 SMARTCARD_CAPABILITY_VERSION_01 };
813 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
821static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
823 WINPR_ASSERT(context);
824 WINPR_ASSERT(context->priv);
826 UINT16 numCapabilities = 1;
827 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
830 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
831 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
834 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
837 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
840 RdpdrServerPrivate* priv = context->priv;
841 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 512);
844 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
845 return CHANNEL_RC_NO_MEMORY;
849 .Component = RDPDR_CTYP_CORE,
850 .PacketId = PAKID_CORE_SERVER_CAPABILITY,
852 Stream_Write_UINT16(s, header.
Component);
853 Stream_Write_UINT16(s, header.
PacketId);
854 Stream_Write_UINT16(s, numCapabilities);
855 Stream_Write_UINT16(s, 0);
858 if ((error = rdpdr_server_write_general_capability_set(context, s)))
860 WLog_Print(priv->log, WLOG_ERROR,
861 "rdpdr_server_write_general_capability_set failed with error %" PRIu32
"!",
866 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
868 if ((error = rdpdr_server_write_drive_capability_set(context, s)))
870 WLog_Print(priv->log, WLOG_ERROR,
871 "rdpdr_server_write_drive_capability_set failed with error %" PRIu32
"!",
877 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
878 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
880 if ((error = rdpdr_server_write_port_capability_set(context, s)))
882 WLog_Print(priv->log, WLOG_ERROR,
883 "rdpdr_server_write_port_capability_set failed with error %" PRIu32
"!",
889 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
891 if ((error = rdpdr_server_write_printer_capability_set(context, s)))
893 WLog_Print(priv->log, WLOG_ERROR,
894 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
900 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
902 if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
904 WLog_Print(priv->log, WLOG_ERROR,
905 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
911 return rdpdr_seal_send_free_request(context, s);
917static UINT16 rdpdr_cap_type_to_dtyp(UINT16 capabilityType)
919 switch (capabilityType)
921 case CAP_PRINTER_TYPE:
922 return RDPDR_DTYP_PRINT;
924 return RDPDR_DTYP_SERIAL | RDPDR_DTYP_PARALLEL;
926 return RDPDR_DTYP_FILESYSTEM;
927 case CAP_SMARTCARD_TYPE:
928 return RDPDR_DTYP_SMARTCARD;
929 case CAP_GENERAL_TYPE:
940static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context,
wStream* s,
943 WINPR_ASSERT(context);
944 WINPR_ASSERT(context->priv);
946 RdpdrServerPrivate* priv = context->priv;
948 WINPR_UNUSED(header);
950 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
951 return ERROR_INVALID_DATA;
953 const UINT16 numCapabilities = Stream_Get_UINT16(s);
954 Stream_Seek_UINT16(s);
957 for (UINT16 i = 0; i < numCapabilities; i++)
960 const size_t start = Stream_GetPosition(s);
963 if ((status = rdpdr_read_capset_header(priv->log, s, &capabilityHeader)))
965 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
969 status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
970 Stream_GetRemainingLength(s), Stream_ConstPointer(s));
971 if (status != CHANNEL_RC_OK)
974 switch (capabilityHeader.CapabilityType)
976 case CAP_GENERAL_TYPE:
978 rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
980 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
986 case CAP_PRINTER_TYPE:
988 rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
990 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
997 if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
999 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1005 case CAP_DRIVE_TYPE:
1007 rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
1009 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1015 case CAP_SMARTCARD_TYPE:
1017 rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
1019 WLog_Print(priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
1026 WLog_Print(priv->log, WLOG_WARN,
"Unknown capabilityType %" PRIu16
"",
1027 capabilityHeader.CapabilityType);
1028 Stream_Seek(s, capabilityHeader.CapabilityLength);
1029 return ERROR_INVALID_DATA;
1032 const UINT16 client_dtyp = rdpdr_cap_type_to_dtyp(capabilityHeader.CapabilityType);
1033 if ((client_dtyp != 0) && ((client_dtyp & context->supported) == 0))
1035 WLog_Print(priv->log, WLOG_WARN,
"client sent capability %s we did not announce!",
1036 rdpdr_cap_type_string(capabilityHeader.CapabilityType));
1038 caps |= client_dtyp;
1040 const size_t end = Stream_GetPosition(s);
1041 const size_t diff = end - start;
1042 if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
1044 WLog_Print(priv->log, WLOG_WARN,
1045 "{capability %s[0x%04" PRIx16
"]} processed %" PRIuz
1046 " bytes, but expected to be %" PRIu16,
1047 rdpdr_cap_type_string(capabilityHeader.CapabilityType),
1048 capabilityHeader.CapabilityType, diff, capabilityHeader.CapabilityLength);
1053 context->supported &= caps;
1055 return CHANNEL_RC_OK;
1063static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
1065 WINPR_ASSERT(context);
1066 WINPR_ASSERT(context->priv);
1068 RdpdrServerPrivate* priv = context->priv;
1069 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
1072 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1073 return CHANNEL_RC_NO_MEMORY;
1078 .PacketId = PAKID_CORE_CLIENTID_CONFIRM,
1080 Stream_Write_UINT16(s, header.
Component);
1081 Stream_Write_UINT16(s, header.
PacketId);
1082 Stream_Write_UINT16(s, priv->VersionMajor);
1083 Stream_Write_UINT16(s, priv->VersionMinor);
1084 Stream_Write_UINT32(s, priv->ClientId);
1085 return rdpdr_seal_send_free_request(context, s);
1093static UINT rdpdr_server_send_device_reply(RdpdrServerContext* context, UINT32 deviceId,
1096 WINPR_ASSERT(context);
1097 WINPR_ASSERT(context->priv);
1099 RdpdrServerPrivate* priv = context->priv;
1100 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH + 8);
1103 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1104 return CHANNEL_RC_NO_MEMORY;
1109 .PacketId = PAKID_CORE_DEVICE_REPLY,
1111 Stream_Write_UINT16(s, header.
Component);
1112 Stream_Write_UINT16(s, header.
PacketId);
1113 Stream_Write_UINT32(s, deviceId);
1114 Stream_Write_UINT32(s, resultCode);
1115 return rdpdr_seal_send_free_request(context, s);
1123static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context,
1127 WINPR_ASSERT(context);
1128 WINPR_ASSERT(context->priv);
1130 RdpdrServerPrivate* priv = context->priv;
1132 WINPR_UNUSED(header);
1134 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1135 return ERROR_INVALID_DATA;
1137 const UINT32 DeviceCount = Stream_Get_UINT32(s);
1138 WLog_Print(priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1140 for (UINT32 i = 0; i < DeviceCount; i++)
1142 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
1143 return ERROR_INVALID_DATA;
1146 device.DeviceType = Stream_Get_UINT32(s);
1147 device.DeviceId = Stream_Get_UINT32(s);
1148 Stream_Read(s, device.PreferredDosName, 8);
1149 device.DeviceDataLength = Stream_Get_UINT32(s);
1150 device.DeviceData = Stream_PointerAs(s, BYTE);
1152 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, device.DeviceDataLength))
1153 return ERROR_INVALID_DATA;
1155 if (!rdpdr_add_device(context->priv, &device))
1156 return ERROR_INTERNAL_ERROR;
1158 UINT error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
1159 if (error != CHANNEL_RC_OK)
1162 error = ERROR_NOT_SUPPORTED;
1163 switch (device.DeviceType)
1165 case RDPDR_DTYP_FILESYSTEM:
1166 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1167 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
1170 case RDPDR_DTYP_PRINT:
1171 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1172 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
1175 case RDPDR_DTYP_SERIAL:
1176 if (device.DeviceDataLength != 0)
1178 WLog_Print(priv->log, WLOG_WARN,
1179 "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32
"]",
1180 device.DeviceDataLength);
1181 error = ERROR_INVALID_DATA;
1183 else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1185 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
1188 case RDPDR_DTYP_PARALLEL:
1189 if (device.DeviceDataLength != 0)
1191 WLog_Print(priv->log, WLOG_WARN,
1192 "[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32
"]",
1193 device.DeviceDataLength);
1194 error = ERROR_INVALID_DATA;
1196 else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1197 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
1201 case RDPDR_DTYP_SMARTCARD:
1202 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1204 priv->smartcardDeviceId = device.DeviceId;
1205 priv->haveSmartcardDevice = TRUE;
1207 IFCALLRESULT(STATUS_SUCCESS, context->OnSmartcardCreate, context, &device);
1212 WLog_Print(priv->log, WLOG_WARN,
1213 "[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
1214 "(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
1215 " at position %" PRIu32,
1216 device.DeviceType, i);
1217 error = ERROR_INVALID_DATA;
1221 Stream_Seek(s, device.DeviceDataLength);
1223 error = rdpdr_server_send_device_reply(context, device.DeviceId, error);
1224 if (error != CHANNEL_RC_OK)
1228 return CHANNEL_RC_OK;
1236static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context,
wStream* s,
1239 WINPR_ASSERT(context);
1240 WINPR_ASSERT(context->priv);
1242 RdpdrServerPrivate* priv = context->priv;
1244 WINPR_UNUSED(header);
1246 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1247 return ERROR_INVALID_DATA;
1249 const UINT32 DeviceCount = Stream_Get_UINT32(s);
1250 WLog_Print(priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1252 for (UINT32 i = 0; i < DeviceCount; i++)
1257 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1258 return ERROR_INVALID_DATA;
1260 const UINT32 DeviceId = Stream_Get_UINT32(s);
1261 device = rdpdr_get_device_by_id(context->priv, DeviceId);
1262 WLog_Print(priv->log, WLOG_DEBUG,
"Device %" PRIu32
" Id: 0x%08" PRIX32
"", i, DeviceId);
1263 UINT32 DeviceType = 0;
1265 DeviceType = device->DeviceType;
1268 IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
1269 if (error != CHANNEL_RC_OK)
1274 case RDPDR_DTYP_FILESYSTEM:
1275 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1276 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
1279 case RDPDR_DTYP_PRINT:
1280 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1282 IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
1285 case RDPDR_DTYP_SERIAL:
1286 if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1288 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
1291 case RDPDR_DTYP_PARALLEL:
1292 if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1293 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
1297 case RDPDR_DTYP_SMARTCARD:
1298 if (priv->haveSmartcardDevice)
1300 priv->haveSmartcardDevice = FALSE;
1301 priv->smartcardDeviceId = 0;
1303 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1305 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
1312 if (error != CHANNEL_RC_OK)
1315 if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
1316 return ERROR_INVALID_DATA;
1319 return CHANNEL_RC_OK;
1322static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
wStream* s,
1323 WINPR_ATTR_UNUSED UINT32 DeviceId,
1324 WINPR_ATTR_UNUSED UINT32 FileId,
1325 WINPR_ATTR_UNUSED UINT32 CompletionId)
1327 WINPR_ASSERT(context);
1329 RdpdrServerPrivate* priv = context->priv;
1330 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1331 return ERROR_INVALID_DATA;
1333 WINPR_ATTR_UNUSED
const UINT32 DesiredAccess = Stream_Get_UINT32(s);
1334 WINPR_ATTR_UNUSED
const UINT32 AllocationSize = Stream_Get_UINT32(s);
1335 WINPR_ATTR_UNUSED
const UINT32 FileAttributes = Stream_Get_UINT32(s);
1336 WINPR_ATTR_UNUSED
const UINT32 SharedAccess = Stream_Get_UINT32(s);
1337 WINPR_ATTR_UNUSED
const UINT32 CreateDisposition = Stream_Get_UINT32(s);
1338 WINPR_ATTR_UNUSED
const UINT32 CreateOptions = Stream_Get_UINT32(s);
1339 const UINT32 PathLength = Stream_Get_UINT32(s);
1341 const WCHAR* path = rdpdr_read_ustring(priv->log, s, PathLength);
1342 if (!path && (PathLength > 0))
1343 return ERROR_INVALID_DATA;
1345 WLog_Print(priv->log, WLOG_WARN,
1346 "[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
1347 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1349 return CHANNEL_RC_OK;
1352static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context,
wStream* s,
1353 WINPR_ATTR_UNUSED UINT32 DeviceId,
1354 WINPR_ATTR_UNUSED UINT32 FileId,
1355 WINPR_ATTR_UNUSED UINT32 CompletionId)
1357 WINPR_ASSERT(context);
1358 WINPR_ASSERT(context->priv);
1360 RdpdrServerPrivate* priv = context->priv;
1362 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1363 return ERROR_INVALID_DATA;
1367 WLog_Print(priv->log, WLOG_WARN,
1368 "[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
1369 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1371 return CHANNEL_RC_OK;
1374static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context,
wStream* s,
1375 WINPR_ATTR_UNUSED UINT32 DeviceId,
1376 WINPR_ATTR_UNUSED UINT32 FileId,
1377 WINPR_ATTR_UNUSED UINT32 CompletionId)
1379 WINPR_ASSERT(context);
1380 WINPR_ASSERT(context->priv);
1382 RdpdrServerPrivate* priv = context->priv;
1383 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1384 return ERROR_INVALID_DATA;
1386 const UINT32 Length = Stream_Get_UINT32(s);
1387 const UINT64 Offset = Stream_Get_UINT64(s);
1390 WLog_Print(priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32, Offset,
1393 WLog_Print(priv->log, WLOG_WARN,
1394 "[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
1395 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1397 return CHANNEL_RC_OK;
1400static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context,
wStream* s,
1401 WINPR_ATTR_UNUSED UINT32 DeviceId,
1402 WINPR_ATTR_UNUSED UINT32 FileId,
1403 WINPR_ATTR_UNUSED UINT32 CompletionId)
1405 WINPR_ASSERT(context);
1406 WINPR_ASSERT(context->priv);
1408 RdpdrServerPrivate* priv = context->priv;
1410 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1411 return ERROR_INVALID_DATA;
1413 const UINT32 Length = Stream_Get_UINT32(s);
1414 const UINT64 Offset = Stream_Get_UINT64(s);
1417 WLog_Print(priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32, Offset,
1420 const BYTE* data = Stream_ConstPointer(s);
1421 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1422 return ERROR_INVALID_DATA;
1423 Stream_Seek(s, Length);
1425 WLog_Print(priv->log, WLOG_WARN,
1426 "[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
1427 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)data);
1429 return CHANNEL_RC_OK;
1432static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* context,
wStream* s,
1433 WINPR_ATTR_UNUSED UINT32 DeviceId,
1434 WINPR_ATTR_UNUSED UINT32 FileId,
1435 WINPR_ATTR_UNUSED UINT32 CompletionId)
1437 WINPR_ASSERT(context);
1438 WINPR_ASSERT(context->priv);
1440 RdpdrServerPrivate* priv = context->priv;
1442 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1443 return ERROR_INVALID_DATA;
1445 WINPR_ATTR_UNUSED
const UINT32 OutputBufferLength = Stream_Get_UINT32(s);
1446 WINPR_ATTR_UNUSED
const UINT32 InputBufferLength = Stream_Get_UINT32(s);
1447 WINPR_ATTR_UNUSED
const UINT32 IoControlCode = Stream_Get_UINT32(s);
1450 const BYTE* InputBuffer = Stream_ConstPointer(s);
1451 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, InputBufferLength))
1452 return ERROR_INVALID_DATA;
1453 Stream_Seek(s, InputBufferLength);
1455 WLog_Print(priv->log, WLOG_WARN,
1456 "[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
1457 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p [%" PRIu32
"], OutputBufferLength=%" PRIu32,
1458 (
const void*)InputBuffer, InputBufferLength, OutputBufferLength);
1460 return CHANNEL_RC_OK;
1463static UINT rdpdr_server_receive_io_query_volume_information_request(
1464 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1465 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1467 WINPR_ASSERT(context);
1469 RdpdrServerPrivate* priv = context->priv;
1470 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1471 return ERROR_INVALID_DATA;
1473 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1474 const UINT32 Length = Stream_Get_UINT32(s);
1477 WLog_Print(priv->log, WLOG_DEBUG,
1478 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1479 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1481 const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
1482 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1483 return ERROR_INVALID_DATA;
1484 Stream_Seek(s, Length);
1486 WLog_Print(priv->log, WLOG_WARN,
1487 "[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
1488 "(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
1489 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryVolumeBuffer);
1491 return CHANNEL_RC_OK;
1494static UINT rdpdr_server_receive_io_set_volume_information_request(
1495 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1496 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1498 WINPR_ASSERT(context);
1499 WINPR_ASSERT(context->priv);
1501 RdpdrServerPrivate* priv = context->priv;
1503 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1504 return ERROR_INVALID_DATA;
1506 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1507 const UINT32 Length = Stream_Get_UINT32(s);
1510 WLog_Print(priv->log, WLOG_DEBUG,
1511 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1512 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1514 const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
1515 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1516 return ERROR_INVALID_DATA;
1517 Stream_Seek(s, Length);
1519 WLog_Print(priv->log, WLOG_WARN,
1520 "[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
1521 "(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
1522 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetVolumeBuffer);
1524 return CHANNEL_RC_OK;
1527static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext* context,
1529 WINPR_ATTR_UNUSED UINT32 DeviceId,
1530 WINPR_ATTR_UNUSED UINT32 FileId,
1531 WINPR_ATTR_UNUSED UINT32 CompletionId)
1533 WINPR_ASSERT(context);
1534 WINPR_ASSERT(context->priv);
1536 RdpdrServerPrivate* priv = context->priv;
1538 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1539 return ERROR_INVALID_DATA;
1541 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1542 const UINT32 Length = Stream_Get_UINT32(s);
1545 WLog_Print(priv->log, WLOG_DEBUG,
1546 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1547 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1549 const BYTE* QueryBuffer = Stream_ConstPointer(s);
1550 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1551 return ERROR_INVALID_DATA;
1552 Stream_Seek(s, Length);
1554 WLog_Print(priv->log, WLOG_WARN,
1555 "[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
1556 "(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
1557 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryBuffer);
1559 return CHANNEL_RC_OK;
1562static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext* context,
wStream* s,
1563 WINPR_ATTR_UNUSED UINT32 DeviceId,
1564 WINPR_ATTR_UNUSED UINT32 FileId,
1565 WINPR_ATTR_UNUSED UINT32 CompletionId)
1567 WINPR_ASSERT(context);
1568 WINPR_ASSERT(context->priv);
1570 RdpdrServerPrivate* priv = context->priv;
1572 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1573 return ERROR_INVALID_DATA;
1575 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1576 const UINT32 Length = Stream_Get_UINT32(s);
1579 WLog_Print(priv->log, WLOG_DEBUG,
1580 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1581 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1583 const BYTE* SetBuffer = Stream_ConstPointer(s);
1584 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, Length))
1585 return ERROR_INVALID_DATA;
1586 Stream_Seek(s, Length);
1588 WLog_Print(priv->log, WLOG_WARN,
1589 "[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
1590 "(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
1591 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetBuffer);
1593 return CHANNEL_RC_OK;
1596static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext* context,
wStream* s,
1597 WINPR_ATTR_UNUSED UINT32 DeviceId,
1598 WINPR_ATTR_UNUSED UINT32 FileId,
1599 WINPR_ATTR_UNUSED UINT32 CompletionId)
1601 WINPR_ASSERT(context);
1602 WINPR_ASSERT(context->priv);
1604 RdpdrServerPrivate* priv = context->priv;
1606 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1607 return ERROR_INVALID_DATA;
1609 const UINT32 FsInformationClass = Stream_Get_UINT32(s);
1610 const BYTE InitialQuery = Stream_Get_UINT8(s);
1611 const UINT32 PathLength = Stream_Get_UINT32(s);
1614 const WCHAR* wPath = rdpdr_read_ustring(priv->log, s, PathLength);
1615 if (!wPath && (PathLength > 0))
1616 return ERROR_INVALID_DATA;
1618 char* Path = ConvertWCharNToUtf8Alloc(wPath, PathLength /
sizeof(WCHAR),
nullptr);
1619 WLog_Print(priv->log, WLOG_DEBUG,
1620 "Got FSInformationClass %s [0x%08" PRIx32
"], InitialQuery [%" PRIu8
1621 "] Path[%" PRIu32
"] %s",
1622 FSInformationClass2Tag(FsInformationClass), FsInformationClass, InitialQuery,
1626 WLog_Print(priv->log, WLOG_WARN,
1627 "[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
1628 "(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
1629 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1631 return CHANNEL_RC_OK;
1634static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext* context,
1636 WINPR_ATTR_UNUSED UINT32 DeviceId,
1637 WINPR_ATTR_UNUSED UINT32 FileId,
1638 WINPR_ATTR_UNUSED UINT32 CompletionId)
1640 WINPR_ASSERT(context);
1641 WINPR_ASSERT(context->priv);
1643 RdpdrServerPrivate* priv = context->priv;
1645 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1646 return ERROR_INVALID_DATA;
1648 WINPR_ATTR_UNUSED
const BYTE WatchTree = Stream_Get_UINT8(s);
1649 WINPR_ATTR_UNUSED
const UINT32 CompletionFilter = Stream_Get_UINT32(s);
1652 WLog_Print(priv->log, WLOG_WARN,
1653 "[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
1654 "(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
1655 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1657 return CHANNEL_RC_OK;
1660static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext* context,
1662 UINT32 FileId, UINT32 CompletionId,
1663 UINT32 MinorFunction)
1665 WINPR_ASSERT(context);
1666 WINPR_ASSERT(context->priv);
1668 RdpdrServerPrivate* priv = context->priv;
1669 switch (MinorFunction)
1671 case IRP_MN_QUERY_DIRECTORY:
1672 return rdpdr_server_receive_io_query_directory_request(context, s, DeviceId, FileId,
1674 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
1675 return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
1678 WLog_Print(priv->log, WLOG_WARN,
1679 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
1680 "MajorFunction=%s, MinorFunction=%08" PRIx32
" is not supported",
1681 rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
1682 return ERROR_INVALID_DATA;
1686static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* context,
wStream* s,
1687 WINPR_ATTR_UNUSED UINT32 DeviceId,
1688 WINPR_ATTR_UNUSED UINT32 FileId,
1689 WINPR_ATTR_UNUSED UINT32 CompletionId)
1691 WINPR_ASSERT(context);
1692 WINPR_ASSERT(context->priv);
1694 RdpdrServerPrivate* priv = context->priv;
1696 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 32))
1697 return ERROR_INVALID_DATA;
1699 const uint32_t Operation = Stream_Get_UINT32(s);
1700 uint32_t Lock = Stream_Get_UINT32(s);
1701 const uint32_t NumLocks = Stream_Get_UINT32(s);
1704 WLog_Print(priv->log, WLOG_DEBUG,
1705 "IRP_MJ_LOCK_CONTROL, Operation=%s, Lock=0x%08" PRIx32
", NumLocks=%" PRIu32,
1706 DR_DRIVE_LOCK_REQ2str(Operation), Lock, NumLocks);
1710 for (UINT32 x = 0; x < NumLocks; x++)
1712 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 16))
1713 return ERROR_INVALID_DATA;
1715 const UINT64 Length = Stream_Get_UINT64(s);
1716 const UINT64 Offset = Stream_Get_UINT64(s);
1718 WLog_Print(priv->log, WLOG_DEBUG,
"Locking at Offset=0x%08" PRIx64
" [Length %" PRIu64
"]",
1722 WLog_Print(priv->log, WLOG_WARN,
1723 "[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
1724 "[Lock=0x%08" PRIx32
"]"
1727 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1729 return CHANNEL_RC_OK;
1732static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
wStream* s,
1735 WINPR_ASSERT(context);
1736 WINPR_ASSERT(context->priv);
1737 WINPR_ASSERT(header);
1739 RdpdrServerPrivate* priv = context->priv;
1741 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 20))
1742 return ERROR_INVALID_DATA;
1744 const UINT32 DeviceId = Stream_Get_UINT32(s);
1745 const UINT32 FileId = Stream_Get_UINT32(s);
1746 const UINT32 CompletionId = Stream_Get_UINT32(s);
1747 const UINT32 MajorFunction = Stream_Get_UINT32(s);
1748 const UINT32 MinorFunction = Stream_Get_UINT32(s);
1749 if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
1750 WLog_Print(priv->log, WLOG_WARN,
1751 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
1752 "MinorFunction=0x%08" PRIx32
" != 0",
1753 rdpdr_irp_string(MajorFunction), MinorFunction);
1755 switch (MajorFunction)
1758 return rdpdr_server_receive_io_create_request(context, s, DeviceId, FileId,
1761 return rdpdr_server_receive_io_close_request(context, s, DeviceId, FileId,
1764 return rdpdr_server_receive_io_read_request(context, s, DeviceId, FileId, CompletionId);
1766 return rdpdr_server_receive_io_write_request(context, s, DeviceId, FileId,
1768 case IRP_MJ_DEVICE_CONTROL:
1769 return rdpdr_server_receive_io_device_control_request(context, s, DeviceId, FileId,
1771 case IRP_MJ_QUERY_VOLUME_INFORMATION:
1772 return rdpdr_server_receive_io_query_volume_information_request(context, s, DeviceId,
1773 FileId, CompletionId);
1774 case IRP_MJ_QUERY_INFORMATION:
1775 return rdpdr_server_receive_io_query_information_request(context, s, DeviceId, FileId,
1777 case IRP_MJ_SET_INFORMATION:
1778 return rdpdr_server_receive_io_set_information_request(context, s, DeviceId, FileId,
1780 case IRP_MJ_DIRECTORY_CONTROL:
1781 return rdpdr_server_receive_io_directory_control_request(context, s, DeviceId, FileId,
1782 CompletionId, MinorFunction);
1783 case IRP_MJ_LOCK_CONTROL:
1784 return rdpdr_server_receive_io_lock_control_request(context, s, DeviceId, FileId,
1786 case IRP_MJ_SET_VOLUME_INFORMATION:
1787 return rdpdr_server_receive_io_set_volume_information_request(context, s, DeviceId,
1788 FileId, CompletionId);
1792 priv->log, WLOG_WARN,
1793 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
1794 WLog_Print(priv->log, WLOG_WARN,
1795 "got DeviceId=0x%08" PRIx32
", FileId=0x%08" PRIx32
1796 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
1797 ", MinorFunction=0x%08" PRIx32,
1798 DeviceId, FileId, CompletionId, MajorFunction, MinorFunction);
1799 return ERROR_INVALID_DATA;
1808static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context,
wStream* s,
1811 WINPR_ASSERT(context);
1812 WINPR_ASSERT(context->priv);
1814 WINPR_ASSERT(header);
1816 RdpdrServerPrivate* priv = context->priv;
1818 WINPR_UNUSED(header);
1820 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 12))
1821 return ERROR_INVALID_DATA;
1823 const UINT32 deviceId = Stream_Get_UINT32(s);
1824 const UINT32 completionId = Stream_Get_UINT32(s);
1825 const UINT32 ioStatus = Stream_Get_UINT32(s);
1826 WLog_Print(priv->log, WLOG_DEBUG,
1827 "deviceId=%" PRIu32
", completionId=0x%" PRIx32
", ioStatus=0x%" PRIx32
"", deviceId,
1828 completionId, ioStatus);
1829 RDPDR_IRP* irp = rdpdr_server_dequeue_irp(context, completionId);
1833 WLog_Print(priv->log, WLOG_ERROR,
"IRP not found for completionId=0x%" PRIx32
"",
1835 return CHANNEL_RC_OK;
1839 UINT error = CHANNEL_RC_OK;
1842 error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
1853static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
1855 WINPR_ASSERT(context);
1856 WINPR_ASSERT(context->priv);
1858 RdpdrServerPrivate* priv = context->priv;
1859 wStream* s = Stream_New(
nullptr, RDPDR_HEADER_LENGTH);
1862 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
1863 return CHANNEL_RC_NO_MEMORY;
1868 .PacketId = PAKID_CORE_USER_LOGGEDON,
1870 Stream_Write_UINT16(s, header.
Component);
1871 Stream_Write_UINT16(s, header.
PacketId);
1872 return rdpdr_seal_send_free_request(context, s);
1875static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context,
wStream* s)
1877 WINPR_ASSERT(context);
1878 WINPR_ASSERT(context->priv);
1880 RdpdrServerPrivate* priv = context->priv;
1882 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 24))
1883 return ERROR_INVALID_DATA;
1885 char PortDosName[9] = WINPR_C_ARRAY_INIT;
1886 Stream_Read(s, PortDosName, 8);
1887 const UINT32 PnPNameLen = Stream_Get_UINT32(s);
1888 const UINT32 DriverNameLen = Stream_Get_UINT32(s);
1889 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
1890 const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
1892 const WCHAR* PnPName = rdpdr_read_ustring(priv->log, s, PnPNameLen);
1893 if (!PnPName && (PnPNameLen > 0))
1894 return ERROR_INVALID_DATA;
1895 const WCHAR* DriverName = rdpdr_read_ustring(priv->log, s, DriverNameLen);
1896 if (!DriverName && (DriverNameLen > 0))
1897 return ERROR_INVALID_DATA;
1898 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
1899 if (!PrinterName && (PrinterNameLen > 0))
1900 return ERROR_INVALID_DATA;
1902 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
1903 return ERROR_INVALID_DATA;
1904 Stream_Seek(s, CachedFieldsLen);
1906 WLog_Print(priv->log, WLOG_WARN,
1907 "[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
1908 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1909 return CHANNEL_RC_OK;
1912static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context,
wStream* s)
1914 WINPR_ASSERT(context);
1916 RdpdrServerPrivate* priv = context->priv;
1918 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
1919 return ERROR_INVALID_DATA;
1921 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
1922 const UINT32 CachedFieldsLen = Stream_Get_UINT32(s);
1924 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
1925 if (!PrinterName && (PrinterNameLen > 0))
1926 return ERROR_INVALID_DATA;
1928 const BYTE* config = Stream_ConstPointer(s);
1929 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, CachedFieldsLen))
1930 return ERROR_INVALID_DATA;
1931 Stream_Seek(s, CachedFieldsLen);
1934 priv->log, WLOG_WARN,
1935 "[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
1936 WLog_Print(priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)config);
1937 return CHANNEL_RC_OK;
1940static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context,
wStream* s)
1942 WINPR_ASSERT(context);
1943 WINPR_ASSERT(context->priv);
1945 RdpdrServerPrivate* priv = context->priv;
1947 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
1948 return ERROR_INVALID_DATA;
1950 const UINT32 PrinterNameLen = Stream_Get_UINT32(s);
1952 const WCHAR* PrinterName = rdpdr_read_ustring(priv->log, s, PrinterNameLen);
1953 if (!PrinterName && (PrinterNameLen > 0))
1954 return ERROR_INVALID_DATA;
1957 priv->log, WLOG_WARN,
1958 "[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
1959 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1960 return CHANNEL_RC_OK;
1963static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context,
wStream* s)
1965 WINPR_ASSERT(context);
1966 WINPR_ASSERT(context->priv);
1968 RdpdrServerPrivate* priv = context->priv;
1970 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
1971 return ERROR_INVALID_DATA;
1973 const UINT32 OldPrinterNameLen = Stream_Get_UINT32(s);
1974 const UINT32 NewPrinterNameLen = Stream_Get_UINT32(s);
1976 const WCHAR* OldPrinterName = rdpdr_read_ustring(priv->log, s, OldPrinterNameLen);
1977 if (!OldPrinterName && (OldPrinterNameLen > 0))
1978 return ERROR_INVALID_DATA;
1979 const WCHAR* NewPrinterName = rdpdr_read_ustring(priv->log, s, NewPrinterNameLen);
1980 if (!NewPrinterName && (NewPrinterNameLen > 0))
1981 return ERROR_INVALID_DATA;
1984 priv->log, WLOG_WARN,
1985 "[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
1986 WLog_Print(priv->log, WLOG_WARN,
"TODO");
1987 return CHANNEL_RC_OK;
1991rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context,
wStream* s,
1994 WINPR_ASSERT(context);
1995 WINPR_ASSERT(context->priv);
1996 WINPR_ASSERT(header);
1998 RdpdrServerPrivate* priv = context->priv;
1999 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
2000 return ERROR_INVALID_DATA;
2002 const UINT32 EventId = Stream_Get_UINT32(s);
2005 case RDPDR_ADD_PRINTER_EVENT:
2006 return rdpdr_server_receive_prn_cache_add_printer(context, s);
2007 case RDPDR_UPDATE_PRINTER_EVENT:
2008 return rdpdr_server_receive_prn_cache_update_printer(context, s);
2009 case RDPDR_DELETE_PRINTER_EVENT:
2010 return rdpdr_server_receive_prn_cache_delete_printer(context, s);
2011 case RDPDR_RENAME_PRINTER_EVENT:
2012 return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
2014 WLog_Print(priv->log, WLOG_WARN,
2015 "[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
2016 return ERROR_INVALID_DATA;
2020static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context,
wStream* s,
2023 WINPR_ASSERT(context);
2024 WINPR_ASSERT(context->priv);
2025 WINPR_ASSERT(header);
2027 RdpdrServerPrivate* priv = context->priv;
2029 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 8))
2030 return ERROR_INVALID_DATA;
2032 const UINT32 PrinterId = Stream_Get_UINT32(s);
2033 const UINT32 Flags = Stream_Get_UINT32(s);
2036 priv->log, WLOG_WARN,
2037 "[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
2038 WLog_Print(priv->log, WLOG_WARN,
"PrinterId=0x%08" PRIx32
", Flags=0x%08" PRIx32, PrinterId,
2040 return CHANNEL_RC_OK;
2048static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context,
wStream* s,
2051 UINT error = ERROR_INVALID_DATA;
2052 WINPR_ASSERT(context);
2053 WINPR_ASSERT(context->priv);
2055 WINPR_ASSERT(header);
2057 RdpdrServerPrivate* priv = context->priv;
2058 WLog_Print(priv->log, WLOG_DEBUG,
2059 "receiving message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
2063 if (header->
Component == RDPDR_CTYP_CORE)
2067 case PAKID_CORE_SERVER_ANNOUNCE:
2068 WLog_Print(priv->log, WLOG_ERROR,
2069 "[MS-RDPEFS] 2.2.2.2 Server Announce Request "
2070 "(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
2073 case PAKID_CORE_CLIENTID_CONFIRM:
2074 error = rdpdr_server_receive_announce_response(context, s, header);
2077 case PAKID_CORE_CLIENT_NAME:
2078 error = rdpdr_server_receive_client_name_request(context, s, header);
2079 if (error == CHANNEL_RC_OK)
2080 error = rdpdr_server_send_core_capability_request(context);
2081 if (error == CHANNEL_RC_OK)
2082 error = rdpdr_server_send_client_id_confirm(context);
2085 case PAKID_CORE_USER_LOGGEDON:
2086 WLog_Print(priv->log, WLOG_ERROR,
2087 "[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
2088 "must not be sent by a client!");
2091 case PAKID_CORE_SERVER_CAPABILITY:
2092 WLog_Print(priv->log, WLOG_ERROR,
2093 "[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
2094 "(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
2097 case PAKID_CORE_CLIENT_CAPABILITY:
2098 error = rdpdr_server_receive_core_capability_response(context, s, header);
2099 if (error == CHANNEL_RC_OK)
2101 if (priv->UserLoggedOnPdu)
2102 error = rdpdr_server_send_user_logged_on(context);
2107 case PAKID_CORE_DEVICELIST_ANNOUNCE:
2108 error = rdpdr_server_receive_device_list_announce_request(context, s, header);
2111 case PAKID_CORE_DEVICELIST_REMOVE:
2112 error = rdpdr_server_receive_device_list_remove_request(context, s, header);
2115 case PAKID_CORE_DEVICE_REPLY:
2116 WLog_Print(priv->log, WLOG_ERROR,
2117 "[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
2118 "(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
2121 case PAKID_CORE_DEVICE_IOREQUEST:
2122 error = rdpdr_server_receive_device_io_request(context, s, header);
2125 case PAKID_CORE_DEVICE_IOCOMPLETION:
2126 error = rdpdr_server_receive_device_io_completion(context, s, header);
2130 WLog_Print(priv->log, WLOG_WARN,
2131 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2133 rdpdr_packetid_string(header->
PacketId));
2137 else if (header->
Component == RDPDR_CTYP_PRN)
2141 case PAKID_PRN_CACHE_DATA:
2142 error = rdpdr_server_receive_prn_cache_data_request(context, s, header);
2145 case PAKID_PRN_USING_XPS:
2146 error = rdpdr_server_receive_prn_using_xps_request(context, s, header);
2150 WLog_Print(priv->log, WLOG_WARN,
2151 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2153 rdpdr_packetid_string(header->
PacketId));
2159 WLog_Print(priv->log, WLOG_WARN,
2160 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2162 rdpdr_packetid_string(header->
PacketId));
2165 return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
2168static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
2170 RdpdrServerContext* context = (RdpdrServerContext*)arg;
2172 WINPR_ASSERT(context);
2173 WINPR_ASSERT(context->priv);
2177 RdpdrServerPrivate* priv = context->priv;
2178 ChannelPduTracker* tracker = ChannelPduTracker_new(priv->ChannelHandle);
2182 void* buffer =
nullptr;
2183 HANDLE ChannelEvent =
nullptr;
2184 DWORD BytesReturned = 0;
2185 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
2188 WLog_Print(priv->log, WLOG_ERROR,
"error retrieving WTSVirtualEventHandle");
2192 if (BytesReturned !=
sizeof(HANDLE))
2194 WLog_Print(priv->log, WLOG_ERROR,
"invalid size for WTSVirtualEventHandle");
2195 WTSFreeMemory(buffer);
2199 ChannelEvent = *(HANDLE*)buffer;
2200 WTSFreeMemory(buffer);
2202 if ((error = rdpdr_server_send_announce_request(context)))
2204 WLog_Print(priv->log, WLOG_ERROR,
2205 "rdpdr_server_send_announce_request failed with error %" PRIu32
"!", error);
2209 HANDLE events[2] = { priv->StopEvent, ChannelEvent };
2213 DWORD status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
2220 case WAIT_OBJECT_0 + 1:
2223 s = ChannelPduTracker_poll(tracker, &ok);
2229 if (Stream_GetRemainingLength(s) < RDPDR_HEADER_LENGTH)
2231 error = ERROR_INTERNAL_ERROR;
2237 .PacketId = Stream_Get_UINT16(s),
2240 if ((error = rdpdr_server_receive_pdu(context, s, &header)))
2242 WLog_Print(priv->log, WLOG_ERROR,
2243 "rdpdr_server_receive_pdu failed with error %" PRIu32
"!", error);
2252 error = GetLastError();
2253 WLog_Print(priv->log, WLOG_ERROR,
2254 "WaitForMultipleObjects failed with error %" PRIu32
"!", error);
2260 ChannelPduTracker_free(tracker);
2265 if (error && context->rdpcontext)
2266 setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
2277static UINT rdpdr_server_start(RdpdrServerContext* context)
2279 WINPR_ASSERT(context);
2280 WINPR_ASSERT(context->priv);
2282 PULONG pSessionId =
nullptr;
2283 DWORD BytesReturned = 0;
2285 if (!WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
2286 (LPSTR*)&pSessionId, &BytesReturned))
2287 return CHANNEL_RC_BAD_CHANNEL;
2289 DWORD SessionId = (DWORD)*pSessionId;
2290 WTSFreeMemory(pSessionId);
2292 RdpdrServerPrivate* priv = context->priv;
2293 priv->ChannelHandle =
2294 WTSVirtualChannelOpenEx(SessionId, RDPDR_SVC_CHANNEL_NAME, CHANNEL_OPTION_SHOW_PROTOCOL);
2296 if (!priv->ChannelHandle)
2298 WLog_Print(priv->log, WLOG_ERROR,
"WTSVirtualChannelOpen failed!");
2299 return CHANNEL_RC_BAD_CHANNEL;
2302 if (!(priv->StopEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
2304 WLog_Print(priv->log, WLOG_ERROR,
"CreateEvent failed!");
2305 return ERROR_INTERNAL_ERROR;
2308 if (!(priv->Thread = CreateThread(
nullptr, 0, rdpdr_server_thread, (
void*)context, 0,
nullptr)))
2310 WLog_Print(priv->log, WLOG_ERROR,
"CreateThread failed!");
2311 (void)CloseHandle(priv->StopEvent);
2312 priv->StopEvent =
nullptr;
2313 return ERROR_INTERNAL_ERROR;
2316 return CHANNEL_RC_OK;
2324static UINT rdpdr_server_stop(RdpdrServerContext* context)
2326 WINPR_ASSERT(context);
2327 WINPR_ASSERT(context->priv);
2329 RdpdrServerPrivate* priv = context->priv;
2330 if (priv->StopEvent)
2332 (void)SetEvent(priv->StopEvent);
2334 if (WaitForSingleObject(priv->Thread, INFINITE) == WAIT_FAILED)
2336 UINT error = GetLastError();
2337 WLog_Print(priv->log, WLOG_ERROR,
"WaitForSingleObject failed with error %" PRIu32
"!",
2342 (void)CloseHandle(priv->Thread);
2343 priv->Thread =
nullptr;
2344 (void)CloseHandle(priv->StopEvent);
2345 priv->StopEvent =
nullptr;
2348 if (priv->ChannelHandle)
2350 (void)WTSVirtualChannelClose(priv->ChannelHandle);
2351 priv->ChannelHandle =
nullptr;
2353 return CHANNEL_RC_OK;
2356static void rdpdr_server_write_device_iorequest(
wStream* s, UINT32 deviceId, UINT32 fileId,
2357 UINT32 completionId, UINT32 majorFunction,
2358 UINT32 minorFunction)
2360 Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
2361 Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST);
2362 Stream_Write_UINT32(s, deviceId);
2363 Stream_Write_UINT32(s, fileId);
2364 Stream_Write_UINT32(s, completionId);
2365 Stream_Write_UINT32(s, majorFunction);
2366 Stream_Write_UINT32(s, minorFunction);
2374static UINT rdpdr_server_read_file_directory_information(wLog* log,
wStream* s,
2380 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
2381 return ERROR_INVALID_DATA;
2388 fdi->
ChangeTime.QuadPart = Stream_Get_INT64(s);
2389 fdi->
EndOfFile.QuadPart = Stream_Get_INT64(s);
2392 const UINT32 fileNameLength = Stream_Get_UINT32(s);
2394 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
2395 return ERROR_INVALID_DATA;
2397 if (fileNameLength /
sizeof(WCHAR) > ARRAYSIZE(fdi->
FileName))
2398 return ERROR_INVALID_DATA;
2400#if defined(__MINGW32__) || defined(WITH_WCHAR_FILE_DIRECTORY_INFORMATION)
2401 if (Stream_Read_UTF16_String(s, fdi->
FileName, fileNameLength /
sizeof(WCHAR)))
2402 return ERROR_INVALID_DATA;
2404 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, fileNameLength /
sizeof(WCHAR), fdi->
FileName,
2406 return ERROR_INVALID_DATA;
2408 return CHANNEL_RC_OK;
2411static UINT prepare_irp(RdpdrServerContext* context, UINT32 deviceId, RDPDR_IRP_Callback callback,
2412 void* callbackData, RDPDR_IRP** outIrp)
2414 WINPR_ASSERT(context);
2415 WINPR_ASSERT(context->priv);
2416 WINPR_ASSERT(callbackData);
2417 WINPR_ASSERT(outIrp);
2419 RdpdrServerPrivate* priv = context->priv;
2421 RDPDR_IRP* irp = rdpdr_server_irp_new();
2424 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2425 return CHANNEL_RC_NO_MEMORY;
2428 irp->CompletionId = priv->NextCompletionId++;
2429 irp->Callback = callback;
2430 irp->CallbackData = callbackData;
2431 irp->DeviceId = deviceId;
2433 if (!rdpdr_server_enqueue_irp(context, irp))
2435 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2436 rdpdr_server_irp_free(irp);
2437 return ERROR_INTERNAL_ERROR;
2441 return CHANNEL_RC_OK;
2444static UINT prepare_smartcard_irp(RdpdrServerContext* context, UINT32 ioControlCode,
2445 RDPDR_IRP_Callback callback,
void* callbackData,
2448 WINPR_ASSERT(context);
2449 WINPR_ASSERT(context->priv);
2450 WINPR_ASSERT(callbackData);
2452 const char* cmd = scard_get_ioctl_string(ioControlCode, FALSE);
2454 RdpdrServerPrivate* priv = context->priv;
2455 if (!priv->haveSmartcardDevice)
2457 WLog_Print(priv->log, WLOG_ERROR,
"%s - no smartcard device registered", cmd);
2458 return ERROR_BAD_DEVICE;
2461 RDPDR_IRP* irp =
nullptr;
2462 UINT error = prepare_irp(context, priv->smartcardDeviceId, callback, callbackData, &irp);
2463 if (error != CHANNEL_RC_OK)
2466 irp->IoControlCode = ioControlCode;
2468 return CHANNEL_RC_OK;
2476static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, UINT32 deviceId,
2477 UINT32 completionId,
const char* path,
2478 UINT32 desiredAccess, UINT32 createOptions,
2479 UINT32 createDisposition)
2481 WINPR_ASSERT(context);
2482 WINPR_ASSERT(context->priv);
2484 RdpdrServerPrivate* priv = context->priv;
2486 WLog_Print(priv->log, WLOG_DEBUG,
2487 "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
2488 ", path=%s, desiredAccess=0x%" PRIx32
" createOptions=0x%" PRIx32
2489 " createDisposition=0x%" PRIx32
"",
2490 deviceId, path, desiredAccess, createOptions, createDisposition);
2492 size_t pathStrLength = 0;
2493 size_t pathLength = 0;
2496 pathStrLength = strlen(path);
2497 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2499 return ERROR_INTERNAL_ERROR;
2500 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2502 wStream* s = Stream_New(
nullptr, 256U + pathLength);
2506 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2507 return CHANNEL_RC_NO_MEMORY;
2510 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
2511 Stream_Write_UINT32(s, desiredAccess);
2512 Stream_Write_UINT32(s, 0);
2513 Stream_Write_UINT32(s, 0);
2514 Stream_Write_UINT32(s, 0);
2515 Stream_Write_UINT32(s, 3);
2516 Stream_Write_UINT32(s, createDisposition);
2517 Stream_Write_UINT32(s, createOptions);
2518 WINPR_ASSERT(pathLength <= UINT32_MAX);
2519 Stream_Write_UINT32(s, (UINT32)pathLength);
2521 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2525 return ERROR_INTERNAL_ERROR;
2527 return rdpdr_seal_send_free_request(context, s);
2535static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId,
2536 UINT32 fileId, UINT32 completionId)
2538 WINPR_ASSERT(context);
2539 WINPR_ASSERT(context->priv);
2541 RdpdrServerPrivate* priv = context->priv;
2543 WLog_Print(priv->log, WLOG_DEBUG,
2544 "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
"",
2546 wStream* s = Stream_New(
nullptr, 128);
2550 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2551 return CHANNEL_RC_NO_MEMORY;
2554 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0);
2556 return rdpdr_seal_send_free_request(context, s);
2564static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, UINT32 deviceId,
2565 UINT32 fileId, UINT32 completionId, UINT32 length,
2568 WINPR_ASSERT(context);
2569 WINPR_ASSERT(context->priv);
2571 RdpdrServerPrivate* priv = context->priv;
2573 WLog_Print(priv->log, WLOG_DEBUG,
2574 "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2575 ", length=%" PRIu32
", offset=%" PRIu32
"",
2576 deviceId, fileId, length, offset);
2577 wStream* s = Stream_New(
nullptr, 128);
2581 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2582 return CHANNEL_RC_NO_MEMORY;
2585 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0);
2586 Stream_Write_UINT32(s, length);
2587 Stream_Write_UINT32(s, offset);
2588 Stream_Write_UINT32(s, 0);
2590 return rdpdr_seal_send_free_request(context, s);
2598static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, UINT32 deviceId,
2599 UINT32 fileId, UINT32 completionId,
2600 const char* data, UINT32 length, UINT32 offset)
2602 WINPR_ASSERT(context);
2603 WINPR_ASSERT(context->priv);
2605 RdpdrServerPrivate* priv = context->priv;
2607 WLog_Print(priv->log, WLOG_DEBUG,
2608 "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2609 ", length=%" PRIu32
", offset=%" PRIu32
"",
2610 deviceId, fileId, length, offset);
2611 wStream* s = Stream_New(
nullptr, 64 + length);
2615 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2616 return CHANNEL_RC_NO_MEMORY;
2619 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0);
2620 Stream_Write_UINT32(s, length);
2621 Stream_Write_UINT32(s, offset);
2622 Stream_Write_UINT32(s, 0);
2624 Stream_Write(s, data, length);
2625 return rdpdr_seal_send_free_request(context, s);
2633static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context,
2634 UINT32 deviceId, UINT32 fileId,
2635 UINT32 completionId,
const char* path)
2637 WINPR_ASSERT(context);
2638 WINPR_ASSERT(context->priv);
2640 RdpdrServerPrivate* priv = context->priv;
2642 WLog_Print(priv->log, WLOG_DEBUG,
2643 "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2645 deviceId, fileId, path);
2647 size_t pathStrLength = 0;
2648 size_t pathLength = 0;
2651 pathStrLength = strlen(path);
2652 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2654 return ERROR_INTERNAL_ERROR;
2655 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2657 wStream* s = Stream_New(
nullptr, 64 + pathLength);
2661 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2662 return CHANNEL_RC_NO_MEMORY;
2665 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_DIRECTORY_CONTROL,
2666 IRP_MN_QUERY_DIRECTORY);
2667 Stream_Write_UINT32(s, FileDirectoryInformation);
2668 Stream_Write_UINT8(s, path ? 1 : 0);
2669 WINPR_ASSERT(pathLength <= UINT32_MAX);
2670 Stream_Write_UINT32(s, (UINT32)pathLength);
2676 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2680 return ERROR_INTERNAL_ERROR;
2684 return rdpdr_seal_send_free_request(context, s);
2692static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context,
2693 UINT32 deviceId, UINT32 fileId,
2694 UINT32 completionId,
const char* path)
2696 WINPR_ASSERT(context);
2697 WINPR_ASSERT(context->priv);
2699 RdpdrServerPrivate* priv = context->priv;
2701 WLog_Print(priv->log, WLOG_DEBUG,
2702 "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2704 deviceId, fileId, path);
2706 size_t pathStrLength = 0;
2707 size_t pathLength = 0;
2710 pathStrLength = strlen(path);
2711 const SSIZE_T wlen = ConvertUtf8ToWChar(path,
nullptr, 0);
2713 return ERROR_INTERNAL_ERROR;
2714 pathLength = (WINPR_ASSERTING_INT_CAST(
size_t, wlen) + 1) *
sizeof(WCHAR);
2717 wStream* s = Stream_New(
nullptr, 64 + pathLength);
2721 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2722 return CHANNEL_RC_NO_MEMORY;
2725 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION,
2727 Stream_Write_UINT32(s, FileRenameInformation);
2728 WINPR_ASSERT(pathLength <= UINT32_MAX - 6U);
2729 Stream_Write_UINT32(s, (UINT32)pathLength + 6U);
2732 Stream_Write_UINT8(s, 0);
2733 Stream_Write_UINT8(s, 0);
2734 Stream_Write_UINT32(s, (UINT32)pathLength);
2739 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path, pathStrLength,
2743 return ERROR_INTERNAL_ERROR;
2747 return rdpdr_seal_send_free_request(context, s);
2750static UINT rdpdr_server_send_device_control_request(RdpdrServerContext* context, UINT32 deviceId,
2751 UINT32 completionId, UINT32 ioControlCode,
2752 UINT32 outputBufferLength,
2753 const void* inputBuffer,
2754 size_t inputBufferLength)
2756 WINPR_ASSERT(context);
2757 WINPR_ASSERT(context->priv);
2758 WINPR_ASSERT(inputBuffer || (inputBufferLength == 0));
2760 if (inputBufferLength > UINT32_MAX)
2762 WLog_Print(context->priv->log, WLOG_ERROR,
2763 "inputBufferLength %" PRIuz
" exceeds UINT32_MAX", inputBufferLength);
2764 return ERROR_INVALID_PARAMETER;
2767 RdpdrServerPrivate* priv = context->priv;
2769 WLog_Print(priv->log, WLOG_DEBUG,
2770 "RdpdrServerSendDeviceControlRequest: deviceId=%" PRIu32
","
2771 " ioControlCode=0x%" PRIx32
", inputBufferLength=%" PRIuz,
2772 deviceId, ioControlCode, inputBufferLength);
2774 if (inputBufferLength > 0)
2775 winpr_HexLogDump(priv->log, WLOG_DEBUG, inputBuffer, inputBufferLength);
2778 Stream_New(
nullptr, RDPDR_HEADER_LENGTH + RDPDR_DEVICE_IO_REQUEST_LENGTH +
2779 RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH + inputBufferLength);
2782 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
2783 return CHANNEL_RC_NO_MEMORY;
2786 UINT32 inputLength = WINPR_ASSERTING_INT_CAST(UINT32, inputBufferLength);
2787 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_DEVICE_CONTROL, 0);
2788 Stream_Write_UINT32(s, outputBufferLength);
2789 Stream_Write_UINT32(s, inputLength);
2790 Stream_Write_UINT32(s, ioControlCode);
2793 if (inputBufferLength > 0)
2794 Stream_Write(s, inputBuffer, inputBufferLength);
2796 return rdpdr_seal_send_free_request(context, s);
2799static void rdpdr_server_convert_slashes(
char* path,
int size)
2801 WINPR_ASSERT(path || (size <= 0));
2803 for (
int i = 0; (i < size) && (path[i] !=
'\0'); i++)
2819static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context,
wStream* s,
2820 RDPDR_IRP* irp, UINT32 deviceId,
2821 UINT32 completionId, UINT32 ioStatus)
2823 WINPR_ASSERT(context);
2824 WINPR_ASSERT(context->priv);
2829 RdpdrServerPrivate* priv = context->priv;
2830 WLog_Print(priv->log, WLOG_DEBUG,
2831 "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
2832 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2833 deviceId, completionId, ioStatus);
2835 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2837 rdpdr_server_irp_free(irp);
2838 return CHANNEL_RC_OK;
2846static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context,
wStream* s,
2847 RDPDR_IRP* irp, UINT32 deviceId,
2848 UINT32 completionId, UINT32 ioStatus)
2850 WINPR_ASSERT(context);
2851 WINPR_ASSERT(context->priv);
2855 RdpdrServerPrivate* priv = context->priv;
2856 WLog_Print(priv->log, WLOG_DEBUG,
2857 "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
2858 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2859 deviceId, completionId, ioStatus);
2861 if (ioStatus != STATUS_SUCCESS)
2864 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2866 rdpdr_server_irp_free(irp);
2867 return CHANNEL_RC_OK;
2870 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
2871 return ERROR_INVALID_DATA;
2873 const uint32_t fileId = Stream_Get_UINT32(s);
2874 const uint8_t information = Stream_Get_UINT8(s);
2875 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2876 fileInformation2str(information));
2879 irp->CompletionId = priv->NextCompletionId++;
2880 irp->Callback = rdpdr_server_drive_create_directory_callback2;
2881 irp->DeviceId = deviceId;
2882 irp->FileId = fileId;
2884 if (!rdpdr_server_enqueue_irp(context, irp))
2886 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2887 rdpdr_server_irp_free(irp);
2888 return ERROR_INTERNAL_ERROR;
2892 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2900static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context,
void* callbackData,
2901 UINT32 deviceId,
const char* path)
2903 WINPR_ASSERT(context);
2904 WINPR_ASSERT(context->priv);
2905 WINPR_ASSERT(callbackData);
2908 RDPDR_IRP* irp =
nullptr;
2909 UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_create_directory_callback1,
2910 callbackData, &irp);
2911 if (ret != CHANNEL_RC_OK)
2914 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2915 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2918 return rdpdr_server_send_device_create_request(
2919 context, irp->DeviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
2920 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
2932static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context,
wStream* s,
2933 RDPDR_IRP* irp, UINT32 deviceId,
2934 UINT32 completionId, UINT32 ioStatus)
2937 WINPR_ASSERT(context);
2938 WINPR_ASSERT(context->priv);
2941 RdpdrServerPrivate* priv = context->priv;
2942 WLog_Print(priv->log, WLOG_DEBUG,
2943 "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
2944 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2945 deviceId, completionId, ioStatus);
2947 context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
2949 rdpdr_server_irp_free(irp);
2950 return CHANNEL_RC_OK;
2958static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context,
wStream* s,
2959 RDPDR_IRP* irp, UINT32 deviceId,
2960 UINT32 completionId, UINT32 ioStatus)
2962 WINPR_ASSERT(context);
2963 WINPR_ASSERT(context->priv);
2966 RdpdrServerPrivate* priv = context->priv;
2967 WLog_Print(priv->log, WLOG_DEBUG,
2968 "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
2969 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2970 deviceId, completionId, ioStatus);
2972 if (ioStatus != STATUS_SUCCESS)
2975 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
2977 rdpdr_server_irp_free(irp);
2978 return CHANNEL_RC_OK;
2981 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
2982 return ERROR_INVALID_DATA;
2984 const uint32_t fileId = Stream_Get_UINT32(s);
2985 const uint8_t information = Stream_Get_UINT8(s);
2986 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2987 fileInformation2str(information));
2990 irp->CompletionId = priv->NextCompletionId++;
2991 irp->Callback = rdpdr_server_drive_delete_directory_callback2;
2992 irp->DeviceId = deviceId;
2993 irp->FileId = fileId;
2995 if (!rdpdr_server_enqueue_irp(context, irp))
2997 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2998 rdpdr_server_irp_free(irp);
2999 return ERROR_INTERNAL_ERROR;
3003 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3011static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context,
void* callbackData,
3012 UINT32 deviceId,
const char* path)
3014 WINPR_ASSERT(context);
3015 WINPR_ASSERT(context->priv);
3017 RDPDR_IRP* irp =
nullptr;
3018 UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_delete_directory_callback1,
3019 callbackData, &irp);
3020 if (ret != CHANNEL_RC_OK)
3023 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3024 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3027 return rdpdr_server_send_device_create_request(
3028 context, irp->DeviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
3029 FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3041static UINT rdpdr_server_drive_query_directory_callback3(RdpdrServerContext* context,
wStream* s,
3042 RDPDR_IRP* irp, UINT32 deviceId,
3043 UINT32 completionId, UINT32 ioStatus)
3045 WINPR_UNUSED(context);
3047 WINPR_UNUSED(deviceId);
3048 WINPR_UNUSED(completionId);
3049 WINPR_UNUSED(ioStatus);
3052 rdpdr_server_irp_free(irp);
3053 return CHANNEL_RC_OK;
3056static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context,
wStream* s,
3057 RDPDR_IRP* irp, UINT32 deviceId,
3058 UINT32 completionId, UINT32 ioStatus)
3060 WINPR_ASSERT(context);
3061 WINPR_ASSERT(context->priv);
3064 RdpdrServerPrivate* priv = context->priv;
3065 WLog_Print(priv->log, WLOG_DEBUG,
3066 "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
3067 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3068 deviceId, completionId, ioStatus);
3070 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3071 return ERROR_INVALID_DATA;
3073 const UINT32 length = Stream_Get_UINT32(s);
3078 UINT error = rdpdr_server_read_file_directory_information(priv->log, s, &fdi);
3081 WLog_Print(priv->log, WLOG_ERROR,
3082 "rdpdr_server_read_file_directory_information failed with error %" PRIu32
3090 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 1))
3091 return ERROR_INVALID_DATA;
3096 if (ioStatus == STATUS_SUCCESS)
3099 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
3100 length > 0 ? &fdi : nullptr);
3102 irp->CompletionId = priv->NextCompletionId++;
3103 irp->Callback = rdpdr_server_drive_query_directory_callback2;
3105 if (!rdpdr_server_enqueue_irp(context, irp))
3107 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3108 rdpdr_server_irp_free(irp);
3109 return ERROR_INTERNAL_ERROR;
3113 return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId,
3114 irp->CompletionId,
nullptr);
3119 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
nullptr);
3122 irp->CompletionId = priv->NextCompletionId++;
3123 irp->Callback = rdpdr_server_drive_query_directory_callback3;
3125 if (!rdpdr_server_enqueue_irp(context, irp))
3127 rdpdr_server_irp_free(irp);
3128 return ERROR_INTERNAL_ERROR;
3131 return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
3141static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context,
wStream* s,
3142 RDPDR_IRP* irp, UINT32 deviceId,
3143 UINT32 completionId, UINT32 ioStatus)
3145 WINPR_ASSERT(context);
3146 WINPR_ASSERT(context->priv);
3149 RdpdrServerPrivate* priv = context->priv;
3150 WLog_Print(priv->log, WLOG_DEBUG,
3151 "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
3152 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3153 deviceId, completionId, ioStatus);
3155 if (ioStatus != STATUS_SUCCESS)
3158 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
nullptr);
3160 rdpdr_server_irp_free(irp);
3161 return CHANNEL_RC_OK;
3164 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3165 return ERROR_INVALID_DATA;
3167 const uint32_t fileId = Stream_Get_UINT32(s);
3169 irp->CompletionId = priv->NextCompletionId++;
3170 irp->Callback = rdpdr_server_drive_query_directory_callback2;
3171 irp->DeviceId = deviceId;
3172 irp->FileId = fileId;
3174 winpr_str_append(
"\\*", irp->PathName, ARRAYSIZE(irp->PathName),
nullptr);
3176 if (!rdpdr_server_enqueue_irp(context, irp))
3178 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3179 rdpdr_server_irp_free(irp);
3180 return ERROR_INTERNAL_ERROR;
3184 return rdpdr_server_send_device_query_directory_request(context, deviceId, fileId,
3185 irp->CompletionId, irp->PathName);
3193static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context,
void* callbackData,
3194 UINT32 deviceId,
const char* path)
3196 WINPR_ASSERT(context);
3197 WINPR_ASSERT(context->priv);
3199 RDPDR_IRP* irp =
nullptr;
3200 UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_query_directory_callback1,
3201 callbackData, &irp);
3202 if (ret != CHANNEL_RC_OK)
3205 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3206 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3209 return rdpdr_server_send_device_create_request(
3210 context, irp->DeviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3211 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3223static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context,
wStream* s,
3224 RDPDR_IRP* irp, UINT32 deviceId,
3225 UINT32 completionId, UINT32 ioStatus)
3227 WINPR_ASSERT(context);
3228 WINPR_ASSERT(context->priv);
3231 RdpdrServerPrivate* priv = context->priv;
3232 WLog_Print(priv->log, WLOG_DEBUG,
3233 "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3234 ", ioStatus=0x%" PRIx32
"",
3235 deviceId, completionId, ioStatus);
3237 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3238 return ERROR_INVALID_DATA;
3240 const uint32_t fileId = Stream_Get_UINT32(s);
3241 const uint8_t information = Stream_Get_UINT8(s);
3242 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3243 fileInformation2str(information));
3246 context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
3248 rdpdr_server_irp_free(irp);
3249 return CHANNEL_RC_OK;
3257static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context,
void* callbackData,
3258 UINT32 deviceId,
const char* path, UINT32 desiredAccess,
3259 UINT32 createDisposition)
3261 WINPR_ASSERT(context);
3262 WINPR_ASSERT(context->priv);
3264 RDPDR_IRP* irp =
nullptr;
3266 prepare_irp(context, deviceId, rdpdr_server_drive_open_file_callback, callbackData, &irp);
3267 if (ret != CHANNEL_RC_OK)
3270 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3271 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3274 return rdpdr_server_send_device_create_request(context, irp->DeviceId, irp->CompletionId,
3275 irp->PathName, desiredAccess | SYNCHRONIZE,
3276 FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
3288static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context,
wStream* s,
3289 RDPDR_IRP* irp, UINT32 deviceId,
3290 UINT32 completionId, UINT32 ioStatus)
3292 WINPR_ASSERT(context);
3293 WINPR_ASSERT(context->priv);
3296 RdpdrServerPrivate* priv = context->priv;
3297 WLog_Print(priv->log, WLOG_DEBUG,
3298 "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3299 ", ioStatus=0x%" PRIx32
"",
3300 deviceId, completionId, ioStatus);
3302 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3303 return ERROR_INVALID_DATA;
3305 const UINT32 length = Stream_Get_UINT32(s);
3306 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, length))
3307 return ERROR_INVALID_DATA;
3309 char* buffer =
nullptr;
3312 buffer = Stream_PointerAs(s,
char);
3313 Stream_Seek(s, length);
3317 context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
3319 rdpdr_server_irp_free(irp);
3320 return CHANNEL_RC_OK;
3328static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context,
void* callbackData,
3329 UINT32 deviceId, UINT32 fileId, UINT32 length,
3332 WINPR_ASSERT(context);
3333 WINPR_ASSERT(context->priv);
3335 RDPDR_IRP* irp =
nullptr;
3337 prepare_irp(context, deviceId, rdpdr_server_drive_read_file_callback, callbackData, &irp);
3338 if (ret != CHANNEL_RC_OK)
3341 irp->FileId = fileId;
3344 return rdpdr_server_send_device_read_request(context, irp->DeviceId, irp->FileId,
3345 irp->CompletionId, length, offset);
3357static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
wStream* s,
3358 RDPDR_IRP* irp, UINT32 deviceId,
3359 UINT32 completionId, UINT32 ioStatus)
3361 WINPR_ASSERT(context);
3362 WINPR_ASSERT(context->priv);
3365 RdpdrServerPrivate* priv = context->priv;
3366 WLog_Print(priv->log, WLOG_DEBUG,
3367 "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3368 ", ioStatus=0x%" PRIx32
"",
3369 deviceId, completionId, ioStatus);
3371 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3372 return ERROR_INVALID_DATA;
3375 const UINT32 length = Stream_Get_UINT32(s);
3377 Stream_Seek(s, MIN(Stream_GetRemainingLength(s), 1));
3380 context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
3382 rdpdr_server_irp_free(irp);
3383 return CHANNEL_RC_OK;
3391static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context,
void* callbackData,
3392 UINT32 deviceId, UINT32 fileId,
const char* buffer,
3393 UINT32 length, UINT32 offset)
3395 WINPR_ASSERT(context);
3396 WINPR_ASSERT(context->priv);
3398 RDPDR_IRP* irp =
nullptr;
3400 prepare_irp(context, deviceId, rdpdr_server_drive_write_file_callback, callbackData, &irp);
3401 if (ret != CHANNEL_RC_OK)
3404 irp->FileId = fileId;
3408 return rdpdr_server_send_device_write_request(context, irp->DeviceId, irp->FileId,
3409 irp->CompletionId, buffer, length, offset);
3422static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
wStream* s,
3423 RDPDR_IRP* irp, UINT32 deviceId,
3424 UINT32 completionId, UINT32 ioStatus)
3426 WINPR_ASSERT(context);
3427 WINPR_ASSERT(context->priv);
3430 RdpdrServerPrivate* priv = context->priv;
3432 WLog_Print(priv->log, WLOG_DEBUG,
3433 "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3434 ", ioStatus=0x%" PRIx32
"",
3435 deviceId, completionId, ioStatus);
3439 Stream_Seek(s, MIN(Stream_GetRemainingLength(s), 5));
3442 context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
3444 rdpdr_server_irp_free(irp);
3445 return CHANNEL_RC_OK;
3453static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context,
void* callbackData,
3454 UINT32 deviceId, UINT32 fileId)
3456 WINPR_ASSERT(context);
3457 WINPR_ASSERT(context->priv);
3459 RDPDR_IRP* irp =
nullptr;
3461 prepare_irp(context, deviceId, rdpdr_server_drive_close_file_callback, callbackData, &irp);
3462 if (ret != CHANNEL_RC_OK)
3465 irp->FileId = fileId;
3469 return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
3483static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context,
wStream* s,
3484 RDPDR_IRP* irp, UINT32 deviceId,
3485 UINT32 completionId, UINT32 ioStatus)
3488 WINPR_ASSERT(context);
3489 WINPR_ASSERT(context->priv);
3492 RdpdrServerPrivate* priv = context->priv;
3493 WLog_Print(priv->log, WLOG_DEBUG,
3494 "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3495 ", ioStatus=0x%" PRIx32
"",
3496 deviceId, completionId, ioStatus);
3498 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3500 rdpdr_server_irp_free(irp);
3501 return CHANNEL_RC_OK;
3509static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context,
wStream* s,
3510 RDPDR_IRP* irp, UINT32 deviceId,
3511 UINT32 completionId, UINT32 ioStatus)
3513 WINPR_ASSERT(context);
3514 WINPR_ASSERT(context->priv);
3517 RdpdrServerPrivate* priv = context->priv;
3518 WLog_Print(priv->log, WLOG_DEBUG,
3519 "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3520 ", ioStatus=0x%" PRIx32
"",
3521 deviceId, completionId, ioStatus);
3523 if (ioStatus != STATUS_SUCCESS)
3526 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3528 rdpdr_server_irp_free(irp);
3529 return CHANNEL_RC_OK;
3532 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3533 return ERROR_INVALID_DATA;
3535 const uint32_t fileId = Stream_Get_UINT32(s);
3536 const uint8_t information = Stream_Get_UINT8(s);
3538 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3539 fileInformation2str(information));
3541 irp->CompletionId = priv->NextCompletionId++;
3542 irp->Callback = rdpdr_server_drive_delete_file_callback2;
3543 irp->DeviceId = deviceId;
3544 irp->FileId = fileId;
3546 if (!rdpdr_server_enqueue_irp(context, irp))
3548 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3549 rdpdr_server_irp_free(irp);
3550 return ERROR_INTERNAL_ERROR;
3554 return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
3563static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context,
void* callbackData,
3564 UINT32 deviceId,
const char* path)
3566 WINPR_ASSERT(context);
3567 WINPR_ASSERT(context->priv);
3569 RDPDR_IRP* irp =
nullptr;
3570 UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_delete_file_callback1,
3571 callbackData, &irp);
3572 if (ret != CHANNEL_RC_OK)
3575 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3576 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3579 return rdpdr_server_send_device_create_request(
3580 context, irp->DeviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
3581 FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3593static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context,
wStream* s,
3594 RDPDR_IRP* irp, UINT32 deviceId,
3595 UINT32 completionId, UINT32 ioStatus)
3597 WINPR_UNUSED(context);
3599 WINPR_ASSERT(context);
3600 WINPR_ASSERT(context->priv);
3603 RdpdrServerPrivate* priv = context->priv;
3604 WLog_Print(priv->log, WLOG_DEBUG,
3605 "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32
", completionId=%" PRIu32
3606 ", ioStatus=0x%" PRIx32
"",
3607 deviceId, completionId, ioStatus);
3609 rdpdr_server_irp_free(irp);
3610 return CHANNEL_RC_OK;
3618static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context,
wStream* s,
3619 RDPDR_IRP* irp, UINT32 deviceId,
3620 UINT32 completionId, UINT32 ioStatus)
3622 WINPR_ASSERT(context);
3623 WINPR_ASSERT(context->priv);
3626 RdpdrServerPrivate* priv = context->priv;
3627 WLog_Print(priv->log, WLOG_DEBUG,
3628 "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3629 ", ioStatus=0x%" PRIx32
"",
3630 deviceId, completionId, ioStatus);
3632 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 4))
3633 return ERROR_INVALID_DATA;
3635 WINPR_ATTR_UNUSED
const UINT32 length = Stream_Get_UINT32(s);
3637 if (Stream_GetRemainingLength(s) > 0)
3641 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3643 irp->CompletionId = priv->NextCompletionId++;
3644 irp->Callback = rdpdr_server_drive_rename_file_callback3;
3645 irp->DeviceId = deviceId;
3647 if (!rdpdr_server_enqueue_irp(context, irp))
3649 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3650 rdpdr_server_irp_free(irp);
3651 return ERROR_INTERNAL_ERROR;
3655 return rdpdr_server_send_device_close_request(context, irp->DeviceId, irp->FileId,
3664static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context,
wStream* s,
3665 RDPDR_IRP* irp, UINT32 deviceId,
3666 UINT32 completionId, UINT32 ioStatus)
3668 WINPR_ASSERT(context);
3669 WINPR_ASSERT(context->priv);
3672 RdpdrServerPrivate* priv = context->priv;
3673 WLog_Print(priv->log, WLOG_DEBUG,
3674 "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3675 ", ioStatus=0x%" PRIx32
"",
3676 deviceId, completionId, ioStatus);
3678 if (ioStatus != STATUS_SUCCESS)
3681 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3683 rdpdr_server_irp_free(irp);
3684 return CHANNEL_RC_OK;
3687 if (!Stream_CheckAndLogRequiredLengthWLog(priv->log, s, 5))
3688 return ERROR_INVALID_DATA;
3690 const uint32_t fileId = Stream_Get_UINT32(s);
3691 const uint8_t information = Stream_Get_UINT8(s);
3692 WLog_Print(priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3693 fileInformation2str(information));
3696 irp->CompletionId = priv->NextCompletionId++;
3697 irp->Callback = rdpdr_server_drive_rename_file_callback2;
3698 irp->DeviceId = deviceId;
3699 irp->FileId = fileId;
3701 if (!rdpdr_server_enqueue_irp(context, irp))
3703 WLog_Print(priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3704 rdpdr_server_irp_free(irp);
3705 return ERROR_INTERNAL_ERROR;
3709 return rdpdr_server_send_device_file_rename_request(context, irp->DeviceId, irp->FileId,
3710 irp->CompletionId, irp->ExtraBuffer);
3718static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context,
void* callbackData,
3719 UINT32 deviceId,
const char* oldPath,
3720 const char* newPath)
3722 WINPR_ASSERT(context);
3723 WINPR_ASSERT(context->priv);
3725 RDPDR_IRP* irp =
nullptr;
3726 UINT ret = prepare_irp(context, deviceId, rdpdr_server_drive_rename_file_callback1,
3727 callbackData, &irp);
3728 if (ret != CHANNEL_RC_OK)
3731 strncpy(irp->PathName, oldPath,
sizeof(irp->PathName) - 1);
3732 strncpy(irp->ExtraBuffer, newPath,
sizeof(irp->ExtraBuffer) - 1);
3733 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3734 rdpdr_server_convert_slashes(irp->ExtraBuffer,
sizeof(irp->ExtraBuffer));
3737 return rdpdr_server_send_device_create_request(
3738 context, irp->DeviceId, irp->CompletionId, irp->PathName,
3739 DELETE | FILE_READ_ATTRIBUTES | SYNCHRONIZE, FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3742static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
3746 ListDictionary_Free(ctx->IrpList);
3747 HashTable_Free(ctx->devicelist);
3748 free(ctx->ClientComputerName);
3752#define TAG CHANNELS_TAG("rdpdr.server")
3753static RdpdrServerPrivate* rdpdr_server_private_new(
void)
3755 RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1,
sizeof(RdpdrServerPrivate));
3760 priv->log = WLog_Get(TAG);
3761 priv->VersionMajor = RDPDR_VERSION_MAJOR;
3762 priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
3763 priv->ClientId = g_ClientId++;
3764 priv->UserLoggedOnPdu = TRUE;
3765 priv->NextCompletionId = 1;
3766 priv->haveSmartcardDevice = FALSE;
3767 priv->smartcardDeviceId = 0;
3768 priv->IrpList = ListDictionary_New(TRUE);
3773 ListDictionary_ValueObject(priv->IrpList)->
fnObjectFree = rdpdr_server_list_free;
3775 priv->devicelist = HashTable_New(FALSE);
3776 if (!priv->devicelist)
3779 if (!HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash))
3783 wObject* obj = HashTable_ValueObject(priv->devicelist);
3790 wObject* obj = HashTable_KeyObject(priv->devicelist);
3798 rdpdr_server_private_free(priv);
3802static UINT rdpdr_server_smartcard_establish_context_callback(RdpdrServerContext* context,
3804 UINT32 deviceId, UINT32 completionId,
3807 WINPR_ASSERT(context);
3808 WINPR_ASSERT(context->priv);
3812 UINT result = CHANNEL_RC_OK;
3813 RdpdrServerPrivate* priv = context->priv;
3816 WLog_Print(priv->log, WLOG_DEBUG,
3817 "RdpdrServerSmartcardEstablishContextCallback: deviceId=%" PRIu32
3818 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3819 deviceId, completionId, ioStatus);
3821 if (ioStatus != STATUS_SUCCESS)
3823 if (context->OnSmartcardEstablishContextComplete)
3824 context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
3825 SCARD_F_INTERNAL_ERROR,
nullptr);
3829 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
3830 if (rc != SCARD_S_SUCCESS)
3832 result = ERROR_INVALID_DATA;
3836 if (context->OnSmartcardEstablishContextComplete)
3837 context->OnSmartcardEstablishContextComplete(context, irp->CallbackData, ioStatus,
3841 smartcard_operation_free(&op, FALSE);
3842 rdpdr_server_irp_free(irp);
3846static UINT rdpdr_server_smartcard_establish_context(RdpdrServerContext* context,
3847 void* callbackData, UINT32 dwScope,
3848 UINT32* completionId)
3850 WINPR_ASSERT(context);
3851 WINPR_ASSERT(context->priv);
3852 WINPR_ASSERT(completionId);
3854 RdpdrServerPrivate* priv = context->priv;
3855 RDPDR_IRP* irp =
nullptr;
3859 case SCARD_SCOPE_USER:
3860 case SCARD_SCOPE_TERMINAL:
3861 case SCARD_SCOPE_SYSTEM:
3864 WLog_Print(priv->log, WLOG_ERROR,
"invalid dwScope=0x%08" PRIx32, dwScope);
3865 return ERROR_INVALID_PARAMETER;
3868 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_ESTABLISHCONTEXT,
3869 rdpdr_server_smartcard_establish_context_callback,
3870 callbackData, &irp);
3871 if (result != CHANNEL_RC_OK)
3875 *completionId = irp->CompletionId;
3878 .ioControlCode = SCARD_IOCTL_ESTABLISHCONTEXT,
3879 .call.establishContext.dwScope = dwScope,
3882 wStream* s = Stream_New(
nullptr, 64);
3885 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
3886 result = CHANNEL_RC_NO_MEMORY;
3890 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
3891 if (rc != SCARD_S_SUCCESS)
3893 result = ERROR_INTERNAL_ERROR;
3897 result = rdpdr_server_send_device_control_request(
3898 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
3899 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
3903 if (result != CHANNEL_RC_OK)
3904 rdpdr_server_discard_request(context, irp->CompletionId);
3912static UINT rdpdr_server_smartcard_release_context_callback(RdpdrServerContext* context,
wStream* s,
3913 RDPDR_IRP* irp, UINT32 deviceId,
3914 UINT32 completionId, UINT32 ioStatus)
3916 WINPR_ASSERT(context);
3917 WINPR_ASSERT(context->priv);
3921 UINT result = CHANNEL_RC_OK;
3922 RdpdrServerPrivate* priv = context->priv;
3925 WLog_Print(priv->log, WLOG_DEBUG,
3926 "SmartcardReleaseContextCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3927 ", ioStatus=0x%" PRIx32,
3928 deviceId, completionId, ioStatus);
3930 if (ioStatus != STATUS_SUCCESS)
3932 if (context->OnSmartcardReleaseContextComplete)
3933 context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
3934 SCARD_F_INTERNAL_ERROR);
3938 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
3939 if (rc != SCARD_S_SUCCESS)
3941 result = ERROR_INVALID_DATA;
3945 if (context->OnSmartcardReleaseContextComplete)
3946 context->OnSmartcardReleaseContextComplete(context, irp->CallbackData, ioStatus,
3950 smartcard_operation_free(&op, FALSE);
3951 rdpdr_server_irp_free(irp);
3955static UINT rdpdr_server_smartcard_release_context(RdpdrServerContext* context,
void* callbackData,
3957 UINT32* completionId)
3959 WINPR_ASSERT(context);
3960 WINPR_ASSERT(context->priv);
3961 WINPR_ASSERT(hContext);
3962 WINPR_ASSERT(completionId);
3964 RdpdrServerPrivate* priv = context->priv;
3965 RDPDR_IRP* irp =
nullptr;
3968 prepare_smartcard_irp(context, SCARD_IOCTL_RELEASECONTEXT,
3969 rdpdr_server_smartcard_release_context_callback, callbackData, &irp);
3970 if (result != CHANNEL_RC_OK)
3973 *completionId = irp->CompletionId;
3976 .ioControlCode = SCARD_IOCTL_RELEASECONTEXT,
3977 .call.context.handles.hContext = *hContext,
3980 wStream* s = Stream_New(
nullptr, 64);
3983 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
3984 result = CHANNEL_RC_NO_MEMORY;
3988 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
3989 if (rc != SCARD_S_SUCCESS)
3991 result = ERROR_INTERNAL_ERROR;
3995 result = rdpdr_server_send_device_control_request(
3996 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
3997 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4001 if (result != CHANNEL_RC_OK)
4002 rdpdr_server_discard_request(context, irp->CompletionId);
4010static UINT rdpdr_server_smartcard_is_valid_context_callback(RdpdrServerContext* context,
4012 UINT32 deviceId, UINT32 completionId,
4015 WINPR_ASSERT(context);
4016 WINPR_ASSERT(context->priv);
4020 UINT result = CHANNEL_RC_OK;
4021 RdpdrServerPrivate* priv = context->priv;
4024 WLog_Print(priv->log, WLOG_DEBUG,
4025 "SmartcardIsValidContextCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4026 ", ioStatus=0x%" PRIx32,
4027 deviceId, completionId, ioStatus);
4029 if (ioStatus != STATUS_SUCCESS)
4031 if (context->OnSmartcardIsValidContextComplete)
4032 context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
4033 SCARD_F_INTERNAL_ERROR);
4037 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4038 if (rc != SCARD_S_SUCCESS)
4040 result = ERROR_INVALID_DATA;
4044 if (context->OnSmartcardIsValidContextComplete)
4045 context->OnSmartcardIsValidContextComplete(context, irp->CallbackData, ioStatus,
4049 smartcard_operation_free(&op, FALSE);
4050 rdpdr_server_irp_free(irp);
4054static UINT rdpdr_server_smartcard_is_valid_context(RdpdrServerContext* context,
void* callbackData,
4056 UINT32* completionId)
4058 WINPR_ASSERT(context);
4059 WINPR_ASSERT(context->priv);
4060 WINPR_ASSERT(hContext);
4061 WINPR_ASSERT(completionId);
4063 RdpdrServerPrivate* priv = context->priv;
4064 RDPDR_IRP* irp =
nullptr;
4067 prepare_smartcard_irp(context, SCARD_IOCTL_ISVALIDCONTEXT,
4068 rdpdr_server_smartcard_is_valid_context_callback, callbackData, &irp);
4069 if (result != CHANNEL_RC_OK)
4073 *completionId = irp->CompletionId;
4076 .ioControlCode = SCARD_IOCTL_ISVALIDCONTEXT,
4077 .call.context.handles.hContext = *hContext,
4080 wStream* s = Stream_New(
nullptr, 64);
4083 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4084 result = CHANNEL_RC_NO_MEMORY;
4088 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4089 if (rc != SCARD_S_SUCCESS)
4091 result = ERROR_INTERNAL_ERROR;
4095 result = rdpdr_server_send_device_control_request(
4096 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4097 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4101 if (result != CHANNEL_RC_OK)
4102 rdpdr_server_discard_request(context, irp->CompletionId);
4110static UINT rdpdr_server_smartcard_list_reader_groups_callback(RdpdrServerContext* context,
4112 UINT32 deviceId, UINT32 completionId,
4115 WINPR_ASSERT(context);
4116 WINPR_ASSERT(context->priv);
4120 UINT result = CHANNEL_RC_OK;
4121 RdpdrServerPrivate* priv = context->priv;
4124 WLog_Print(priv->log, WLOG_DEBUG,
4125 "SmartcardListReaderGroupsCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4126 ", ioStatus=0x%" PRIx32,
4127 deviceId, completionId, ioStatus);
4129 if (ioStatus != STATUS_SUCCESS)
4131 if (context->OnSmartcardListReaderGroupsComplete)
4132 context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
4133 SCARD_F_INTERNAL_ERROR,
nullptr);
4137 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4138 if (rc != SCARD_S_SUCCESS)
4140 result = ERROR_INVALID_DATA;
4144 if (context->OnSmartcardListReaderGroupsComplete)
4145 context->OnSmartcardListReaderGroupsComplete(context, irp->CallbackData, ioStatus,
4149 smartcard_operation_free(&op, FALSE);
4150 rdpdr_server_irp_free(irp);
4154static UINT rdpdr_server_smartcard_list_reader_groups(RdpdrServerContext* context,
4155 void* callbackData, UINT32 ioControlCode,
4157 UINT32* completionId)
4159 WINPR_ASSERT(context);
4160 WINPR_ASSERT(context->priv);
4162 WINPR_ASSERT(completionId);
4164 RdpdrServerPrivate* priv = context->priv;
4165 RDPDR_IRP* irp =
nullptr;
4167 UINT result = prepare_smartcard_irp(context, ioControlCode,
4168 rdpdr_server_smartcard_list_reader_groups_callback,
4169 callbackData, &irp);
4170 if (result != CHANNEL_RC_OK)
4174 *completionId = irp->CompletionId;
4177 .call.listReaderGroups = {
4178 .handles.hContext = call->handles.hContext,
4179 .fmszGroupsIsNULL = call->fmszGroupsIsNULL,
4180 .cchGroups = call->cchGroups,
4183 wStream* s = Stream_New(
nullptr, 32);
4186 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4187 result = CHANNEL_RC_NO_MEMORY;
4191 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4192 if (rc != SCARD_S_SUCCESS)
4194 result = ERROR_INTERNAL_ERROR;
4198 result = rdpdr_server_send_device_control_request(
4199 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4200 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4204 if (result != CHANNEL_RC_OK)
4205 rdpdr_server_discard_request(context, irp->CompletionId);
4212static UINT rdpdr_server_smartcard_list_reader_groupsA(RdpdrServerContext* context,
4215 UINT32* completionId)
4217 return rdpdr_server_smartcard_list_reader_groups(
4218 context, callbackData, SCARD_IOCTL_LISTREADERGROUPSA, call, completionId);
4221static UINT rdpdr_server_smartcard_list_reader_groupsW(RdpdrServerContext* context,
4224 UINT32* completionId)
4226 return rdpdr_server_smartcard_list_reader_groups(
4227 context, callbackData, SCARD_IOCTL_LISTREADERGROUPSW, call, completionId);
4231static UINT rdpdr_server_smartcard_list_readers_callback(RdpdrServerContext* context,
wStream* s,
4232 RDPDR_IRP* irp, UINT32 deviceId,
4233 UINT32 completionId, UINT32 ioStatus)
4235 WINPR_ASSERT(context);
4236 WINPR_ASSERT(context->priv);
4240 UINT result = CHANNEL_RC_OK;
4241 RdpdrServerPrivate* priv = context->priv;
4244 WLog_Print(priv->log, WLOG_DEBUG,
4245 "SmartcardListReadersCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4246 ", ioStatus=0x%" PRIx32,
4247 deviceId, completionId, ioStatus);
4249 if (ioStatus != STATUS_SUCCESS)
4251 if (context->OnSmartcardListReadersComplete)
4252 context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus,
4253 SCARD_F_INTERNAL_ERROR,
nullptr);
4257 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4258 if (rc != SCARD_S_SUCCESS)
4260 result = ERROR_INVALID_DATA;
4264 if (context->OnSmartcardListReadersComplete)
4265 context->OnSmartcardListReadersComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
4266 &op.
ret.listReaders);
4269 smartcard_operation_free(&op, FALSE);
4270 rdpdr_server_irp_free(irp);
4274static UINT rdpdr_server_smartcard_list_readers(RdpdrServerContext* context,
void* callbackData,
4276 UINT32* completionId)
4278 WINPR_ASSERT(context);
4279 WINPR_ASSERT(context->priv);
4281 WINPR_ASSERT(completionId);
4283 RdpdrServerPrivate* priv = context->priv;
4284 RDPDR_IRP* irp =
nullptr;
4286 UINT result = prepare_smartcard_irp(
4287 context, ioControlCode, rdpdr_server_smartcard_list_readers_callback, callbackData, &irp);
4288 if (result != CHANNEL_RC_OK)
4292 *completionId = irp->CompletionId;
4295 .call.listReaders = {
4296 .handles.hContext = call->handles.hContext,
4297 .cBytes = call->cBytes,
4298 .mszGroups = call->mszGroups,
4299 .fmszReadersIsNULL = call->fmszReadersIsNULL,
4300 .cchReaders = call->cchReaders,
4303 wStream* s = Stream_New(
nullptr, 256);
4306 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4307 result = CHANNEL_RC_NO_MEMORY;
4311 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4312 if (rc != SCARD_S_SUCCESS)
4314 result = ERROR_INTERNAL_ERROR;
4318 result = rdpdr_server_send_device_control_request(
4319 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4320 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4324 if (result != CHANNEL_RC_OK)
4325 rdpdr_server_discard_request(context, irp->CompletionId);
4332static UINT rdpdr_server_smartcard_list_readersA(RdpdrServerContext* context,
void* callbackData,
4335 return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSA,
4336 call, completionId);
4339static UINT rdpdr_server_smartcard_list_readersW(RdpdrServerContext* context,
void* callbackData,
4342 return rdpdr_server_smartcard_list_readers(context, callbackData, SCARD_IOCTL_LISTREADERSW,
4343 call, completionId);
4347static UINT rdpdr_server_smartcard_get_status_change_callback(RdpdrServerContext* context,
4349 UINT32 deviceId, UINT32 completionId,
4352 WINPR_ASSERT(context);
4353 WINPR_ASSERT(context->priv);
4357 UINT result = CHANNEL_RC_OK;
4358 RdpdrServerPrivate* priv = context->priv;
4361 WLog_Print(priv->log, WLOG_DEBUG,
4362 "SmartcardGetStatusChangeCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4363 ", ioStatus=0x%" PRIx32,
4364 deviceId, completionId, ioStatus);
4366 if (ioStatus != STATUS_SUCCESS)
4368 if (context->OnSmartcardGetStatusChangeComplete)
4369 context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
4370 SCARD_F_INTERNAL_ERROR,
nullptr);
4374 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4375 if (rc != SCARD_S_SUCCESS)
4377 result = ERROR_INVALID_DATA;
4381 if (context->OnSmartcardGetStatusChangeComplete)
4382 context->OnSmartcardGetStatusChangeComplete(context, irp->CallbackData, ioStatus,
4386 smartcard_operation_free(&op, FALSE);
4387 rdpdr_server_irp_free(irp);
4391static UINT rdpdr_server_smartcard_get_status_change(RdpdrServerContext* context,
4392 void* callbackData, UINT32 ioControlCode,
4393 const void* call, DWORD cReaders,
4394 UINT32* completionId)
4396 WINPR_ASSERT(context);
4397 WINPR_ASSERT(context->priv);
4399 WINPR_ASSERT(completionId);
4401 RdpdrServerPrivate* priv = context->priv;
4402 RDPDR_IRP* irp =
nullptr;
4404 UINT result = prepare_smartcard_irp(context, ioControlCode,
4405 rdpdr_server_smartcard_get_status_change_callback,
4406 callbackData, &irp);
4407 if (result != CHANNEL_RC_OK)
4411 *completionId = irp->CompletionId;
4414 op.ioControlCode = ioControlCode;
4416 switch (ioControlCode)
4418 case SCARD_IOCTL_GETSTATUSCHANGEA:
4421 case SCARD_IOCTL_GETSTATUSCHANGEW:
4425 WINPR_ASSERT(FALSE);
4426 return ERROR_INVALID_PARAMETER;
4429 wStream* s = Stream_New(
nullptr, 256 + cReaders * 256);
4432 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4433 result = CHANNEL_RC_NO_MEMORY;
4437 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4438 if (rc != SCARD_S_SUCCESS)
4440 result = ERROR_INTERNAL_ERROR;
4444 result = rdpdr_server_send_device_control_request(
4445 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4446 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4450 if (result != CHANNEL_RC_OK)
4451 rdpdr_server_discard_request(context, irp->CompletionId);
4458static UINT rdpdr_server_smartcard_get_status_changeA(RdpdrServerContext* context,
4461 UINT32* completionId)
4463 return rdpdr_server_smartcard_get_status_change(
4464 context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEA, call, call->cReaders, completionId);
4467static UINT rdpdr_server_smartcard_get_status_changeW(RdpdrServerContext* context,
4470 UINT32* completionId)
4472 return rdpdr_server_smartcard_get_status_change(
4473 context, callbackData, SCARD_IOCTL_GETSTATUSCHANGEW, call, call->cReaders, completionId);
4477static UINT rdpdr_server_smartcard_cancel_callback(RdpdrServerContext* context,
wStream* s,
4478 RDPDR_IRP* irp, UINT32 deviceId,
4479 UINT32 completionId, UINT32 ioStatus)
4481 WINPR_ASSERT(context);
4482 WINPR_ASSERT(context->priv);
4486 UINT result = CHANNEL_RC_OK;
4487 RdpdrServerPrivate* priv = context->priv;
4490 WLog_Print(priv->log, WLOG_DEBUG,
4491 "SmartcardCancelCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4492 ", ioStatus=0x%" PRIx32,
4493 deviceId, completionId, ioStatus);
4495 if (ioStatus != STATUS_SUCCESS)
4497 if (context->OnSmartcardCancelComplete)
4498 context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus,
4499 SCARD_F_INTERNAL_ERROR);
4503 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4504 if (rc != SCARD_S_SUCCESS)
4506 result = ERROR_INVALID_DATA;
4510 if (context->OnSmartcardCancelComplete)
4511 context->OnSmartcardCancelComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
4514 smartcard_operation_free(&op, FALSE);
4515 rdpdr_server_irp_free(irp);
4519static UINT rdpdr_server_smartcard_cancel(RdpdrServerContext* context,
void* callbackData,
4522 WINPR_ASSERT(context);
4523 WINPR_ASSERT(context->priv);
4524 WINPR_ASSERT(hContext);
4525 WINPR_ASSERT(completionId);
4527 RdpdrServerPrivate* priv = context->priv;
4528 RDPDR_IRP* irp =
nullptr;
4530 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_CANCEL,
4531 rdpdr_server_smartcard_cancel_callback, callbackData, &irp);
4532 if (result != CHANNEL_RC_OK)
4536 *completionId = irp->CompletionId;
4539 .ioControlCode = SCARD_IOCTL_CANCEL,
4540 .call.context.handles.hContext = *hContext,
4543 wStream* s = Stream_New(
nullptr, 64);
4546 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4547 result = CHANNEL_RC_NO_MEMORY;
4551 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4552 if (rc != SCARD_S_SUCCESS)
4554 result = ERROR_INTERNAL_ERROR;
4558 result = rdpdr_server_send_device_control_request(
4559 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4560 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4564 if (result != CHANNEL_RC_OK)
4565 rdpdr_server_discard_request(context, irp->CompletionId);
4573static UINT rdpdr_server_smartcard_connect_callback(RdpdrServerContext* context,
wStream* s,
4574 RDPDR_IRP* irp, UINT32 deviceId,
4575 UINT32 completionId, UINT32 ioStatus)
4577 WINPR_ASSERT(context);
4578 WINPR_ASSERT(context->priv);
4582 UINT result = CHANNEL_RC_OK;
4583 RdpdrServerPrivate* priv = context->priv;
4586 WLog_Print(priv->log, WLOG_DEBUG,
4587 "SmartcardConnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4588 ", ioStatus=0x%" PRIx32,
4589 deviceId, completionId, ioStatus);
4591 if (ioStatus != STATUS_SUCCESS)
4593 if (context->OnSmartcardConnectComplete)
4594 context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus,
4595 SCARD_F_INTERNAL_ERROR,
nullptr);
4599 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4600 if (rc != SCARD_S_SUCCESS)
4602 result = ERROR_INVALID_DATA;
4606 if (context->OnSmartcardConnectComplete)
4607 context->OnSmartcardConnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
4611 smartcard_operation_free(&op, FALSE);
4612 rdpdr_server_irp_free(irp);
4616static UINT rdpdr_server_smartcard_connect(RdpdrServerContext* context,
void* callbackData,
4617 UINT32 ioControlCode,
const void* call,
4618 UINT32* completionId)
4620 WINPR_ASSERT(context);
4621 WINPR_ASSERT(context->priv);
4623 WINPR_ASSERT(completionId);
4625 RdpdrServerPrivate* priv = context->priv;
4626 RDPDR_IRP* irp =
nullptr;
4628 UINT result = prepare_smartcard_irp(
4629 context, ioControlCode, rdpdr_server_smartcard_connect_callback, callbackData, &irp);
4630 if (result != CHANNEL_RC_OK)
4634 *completionId = irp->CompletionId;
4637 op.ioControlCode = ioControlCode;
4639 switch (ioControlCode)
4641 case SCARD_IOCTL_CONNECTA:
4644 case SCARD_IOCTL_CONNECTW:
4648 WINPR_ASSERT(FALSE);
4649 return ERROR_INVALID_PARAMETER;
4652 wStream* s = Stream_New(
nullptr, 512);
4655 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4656 result = CHANNEL_RC_NO_MEMORY;
4660 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4661 if (rc != SCARD_S_SUCCESS)
4663 result = ERROR_INTERNAL_ERROR;
4667 result = rdpdr_server_send_device_control_request(
4668 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4669 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4673 if (result != CHANNEL_RC_OK)
4674 rdpdr_server_discard_request(context, irp->CompletionId);
4681static UINT rdpdr_server_smartcard_connectA(RdpdrServerContext* context,
void* callbackData,
4684 return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTA, call,
4688static UINT rdpdr_server_smartcard_connectW(RdpdrServerContext* context,
void* callbackData,
4691 return rdpdr_server_smartcard_connect(context, callbackData, SCARD_IOCTL_CONNECTW, call,
4696static UINT rdpdr_server_smartcard_reconnect_callback(RdpdrServerContext* context,
wStream* s,
4697 RDPDR_IRP* irp, UINT32 deviceId,
4698 UINT32 completionId, UINT32 ioStatus)
4700 WINPR_ASSERT(context);
4701 WINPR_ASSERT(context->priv);
4705 UINT result = CHANNEL_RC_OK;
4706 RdpdrServerPrivate* priv = context->priv;
4709 WLog_Print(priv->log, WLOG_DEBUG,
4710 "SmartcardReconnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4711 ", ioStatus=0x%" PRIx32,
4712 deviceId, completionId, ioStatus);
4714 if (ioStatus != STATUS_SUCCESS)
4716 if (context->OnSmartcardReconnectComplete)
4717 context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus,
4718 SCARD_F_INTERNAL_ERROR,
nullptr);
4722 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4723 if (rc != SCARD_S_SUCCESS)
4725 result = ERROR_INVALID_DATA;
4729 if (context->OnSmartcardReconnectComplete)
4730 context->OnSmartcardReconnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
4734 smartcard_operation_free(&op, FALSE);
4735 rdpdr_server_irp_free(irp);
4739static UINT rdpdr_server_smartcard_reconnect(RdpdrServerContext* context,
void* callbackData,
4742 WINPR_ASSERT(context);
4743 WINPR_ASSERT(context->priv);
4745 WINPR_ASSERT(completionId);
4747 RdpdrServerPrivate* priv = context->priv;
4748 RDPDR_IRP* irp =
nullptr;
4751 prepare_smartcard_irp(context, SCARD_IOCTL_RECONNECT,
4752 rdpdr_server_smartcard_reconnect_callback, callbackData, &irp);
4753 if (result != CHANNEL_RC_OK)
4757 *completionId = irp->CompletionId;
4761 .handles.hContext = call->handles.hContext,
4762 .handles.hCard = call->handles.hCard,
4763 .dwShareMode = call->dwShareMode,
4764 .dwPreferredProtocols = call->dwPreferredProtocols,
4765 .dwInitialization = call->dwInitialization,
4768 wStream* s = Stream_New(
nullptr, 128);
4771 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4772 result = CHANNEL_RC_NO_MEMORY;
4776 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4777 if (rc != SCARD_S_SUCCESS)
4779 result = ERROR_INTERNAL_ERROR;
4783 result = rdpdr_server_send_device_control_request(
4784 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4785 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4789 if (result != CHANNEL_RC_OK)
4790 rdpdr_server_discard_request(context, irp->CompletionId);
4798static UINT rdpdr_server_smartcard_disconnect_callback(RdpdrServerContext* context,
wStream* s,
4799 RDPDR_IRP* irp, UINT32 deviceId,
4800 UINT32 completionId, UINT32 ioStatus)
4802 WINPR_ASSERT(context);
4803 WINPR_ASSERT(context->priv);
4807 UINT result = CHANNEL_RC_OK;
4808 RdpdrServerPrivate* priv = context->priv;
4811 WLog_Print(priv->log, WLOG_DEBUG,
4812 "SmartcardDisconnectCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4813 ", ioStatus=0x%" PRIx32,
4814 deviceId, completionId, ioStatus);
4816 if (ioStatus != STATUS_SUCCESS)
4818 if (context->OnSmartcardDisconnectComplete)
4819 context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus,
4820 SCARD_F_INTERNAL_ERROR);
4824 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4825 if (rc != SCARD_S_SUCCESS)
4827 result = ERROR_INVALID_DATA;
4831 if (context->OnSmartcardDisconnectComplete)
4832 context->OnSmartcardDisconnectComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
4835 smartcard_operation_free(&op, FALSE);
4836 rdpdr_server_irp_free(irp);
4840static UINT rdpdr_server_smartcard_disconnect(RdpdrServerContext* context,
void* callbackData,
4842 UINT32* completionId)
4844 WINPR_ASSERT(context);
4845 WINPR_ASSERT(context->priv);
4847 WINPR_ASSERT(completionId);
4849 RdpdrServerPrivate* priv = context->priv;
4850 RDPDR_IRP* irp =
nullptr;
4853 prepare_smartcard_irp(context, SCARD_IOCTL_DISCONNECT,
4854 rdpdr_server_smartcard_disconnect_callback, callbackData, &irp);
4855 if (result != CHANNEL_RC_OK)
4859 *completionId = irp->CompletionId;
4862 .call.hCardAndDisposition = {
4863 .handles.hContext = call->handles.hContext,
4864 .handles.hCard = call->handles.hCard,
4865 .dwDisposition = call->dwDisposition,
4868 wStream* s = Stream_New(
nullptr, 128);
4871 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4872 result = CHANNEL_RC_NO_MEMORY;
4876 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4877 if (rc != SCARD_S_SUCCESS)
4879 result = ERROR_INTERNAL_ERROR;
4883 result = rdpdr_server_send_device_control_request(
4884 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4885 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4889 if (result != CHANNEL_RC_OK)
4890 rdpdr_server_discard_request(context, irp->CompletionId);
4898static UINT rdpdr_server_smartcard_begin_transaction_callback(RdpdrServerContext* context,
4900 UINT32 deviceId, UINT32 completionId,
4903 WINPR_ASSERT(context);
4904 WINPR_ASSERT(context->priv);
4908 UINT result = CHANNEL_RC_OK;
4909 RdpdrServerPrivate* priv = context->priv;
4912 WLog_Print(priv->log, WLOG_DEBUG,
4913 "SmartcardBeginTransactionCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
4914 ", ioStatus=0x%" PRIx32,
4915 deviceId, completionId, ioStatus);
4917 if (ioStatus != STATUS_SUCCESS)
4919 if (context->OnSmartcardBeginTransactionComplete)
4920 context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
4921 SCARD_F_INTERNAL_ERROR);
4925 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
4926 if (rc != SCARD_S_SUCCESS)
4928 result = ERROR_INVALID_DATA;
4932 if (context->OnSmartcardBeginTransactionComplete)
4933 context->OnSmartcardBeginTransactionComplete(context, irp->CallbackData, ioStatus,
4937 smartcard_operation_free(&op, FALSE);
4938 rdpdr_server_irp_free(irp);
4942static UINT rdpdr_server_smartcard_begin_transaction(RdpdrServerContext* context,
4945 UINT32* completionId)
4947 WINPR_ASSERT(context);
4948 WINPR_ASSERT(context->priv);
4950 WINPR_ASSERT(completionId);
4952 RdpdrServerPrivate* priv = context->priv;
4953 RDPDR_IRP* irp =
nullptr;
4955 UINT result = prepare_smartcard_irp(context, SCARD_IOCTL_BEGINTRANSACTION,
4956 rdpdr_server_smartcard_begin_transaction_callback,
4957 callbackData, &irp);
4958 if (result != CHANNEL_RC_OK)
4962 *completionId = irp->CompletionId;
4965 .call.hCardAndDisposition = {
4966 .handles.hContext = call->handles.hContext,
4967 .handles.hCard = call->handles.hCard,
4968 .dwDisposition = SCARD_LEAVE_CARD,
4971 wStream* s = Stream_New(
nullptr, 128);
4974 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
4975 result = CHANNEL_RC_NO_MEMORY;
4979 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
4980 if (rc != SCARD_S_SUCCESS)
4982 result = ERROR_INTERNAL_ERROR;
4986 result = rdpdr_server_send_device_control_request(
4987 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
4988 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
4992 if (result != CHANNEL_RC_OK)
4993 rdpdr_server_discard_request(context, irp->CompletionId);
5001static UINT rdpdr_server_smartcard_end_transaction_callback(RdpdrServerContext* context,
wStream* s,
5002 RDPDR_IRP* irp, UINT32 deviceId,
5003 UINT32 completionId, UINT32 ioStatus)
5005 WINPR_ASSERT(context);
5006 WINPR_ASSERT(context->priv);
5010 UINT result = CHANNEL_RC_OK;
5011 RdpdrServerPrivate* priv = context->priv;
5014 WLog_Print(priv->log, WLOG_DEBUG,
5015 "SmartcardEndTransactionCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5016 ", ioStatus=0x%" PRIx32,
5017 deviceId, completionId, ioStatus);
5019 if (ioStatus != STATUS_SUCCESS)
5021 if (context->OnSmartcardEndTransactionComplete)
5022 context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
5023 SCARD_F_INTERNAL_ERROR);
5027 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5028 if (rc != SCARD_S_SUCCESS)
5030 result = ERROR_INVALID_DATA;
5034 if (context->OnSmartcardEndTransactionComplete)
5035 context->OnSmartcardEndTransactionComplete(context, irp->CallbackData, ioStatus,
5039 smartcard_operation_free(&op, FALSE);
5040 rdpdr_server_irp_free(irp);
5044static UINT rdpdr_server_smartcard_end_transaction(RdpdrServerContext* context,
void* callbackData,
5046 UINT32* completionId)
5048 WINPR_ASSERT(context);
5049 WINPR_ASSERT(context->priv);
5051 WINPR_ASSERT(completionId);
5053 RdpdrServerPrivate* priv = context->priv;
5054 RDPDR_IRP* irp =
nullptr;
5057 prepare_smartcard_irp(context, SCARD_IOCTL_ENDTRANSACTION,
5058 rdpdr_server_smartcard_end_transaction_callback, callbackData, &irp);
5059 if (result != CHANNEL_RC_OK)
5063 *completionId = irp->CompletionId;
5066 .call.hCardAndDisposition = {
5067 .handles.hContext = call->handles.hContext,
5068 .handles.hCard = call->handles.hCard,
5069 .dwDisposition = call->dwDisposition,
5072 wStream* s = Stream_New(
nullptr, 128);
5075 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5076 result = CHANNEL_RC_NO_MEMORY;
5080 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5081 if (rc != SCARD_S_SUCCESS)
5083 result = ERROR_INTERNAL_ERROR;
5087 result = rdpdr_server_send_device_control_request(
5088 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5089 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5093 if (result != CHANNEL_RC_OK)
5094 rdpdr_server_discard_request(context, irp->CompletionId);
5102static UINT rdpdr_server_smartcard_status_callback(RdpdrServerContext* context,
wStream* s,
5103 RDPDR_IRP* irp, UINT32 deviceId,
5104 UINT32 completionId, UINT32 ioStatus)
5106 WINPR_ASSERT(context);
5107 WINPR_ASSERT(context->priv);
5111 UINT result = CHANNEL_RC_OK;
5112 RdpdrServerPrivate* priv = context->priv;
5115 WLog_Print(priv->log, WLOG_DEBUG,
5116 "SmartcardStatusCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5117 ", ioStatus=0x%" PRIx32,
5118 deviceId, completionId, ioStatus);
5120 if (ioStatus != STATUS_SUCCESS)
5122 if (context->OnSmartcardStatusComplete)
5123 context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus,
5124 SCARD_F_INTERNAL_ERROR,
nullptr);
5128 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5129 if (rc != SCARD_S_SUCCESS)
5131 result = ERROR_INVALID_DATA;
5135 if (context->OnSmartcardStatusComplete)
5136 context->OnSmartcardStatusComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5140 smartcard_operation_free(&op, FALSE);
5141 rdpdr_server_irp_free(irp);
5145static UINT rdpdr_server_smartcard_status(RdpdrServerContext* context,
void* callbackData,
5147 UINT32* completionId)
5149 WINPR_ASSERT(context);
5150 WINPR_ASSERT(context->priv);
5152 WINPR_ASSERT(completionId);
5154 RdpdrServerPrivate* priv = context->priv;
5155 RDPDR_IRP* irp =
nullptr;
5157 UINT result = prepare_smartcard_irp(context, ioControlCode,
5158 rdpdr_server_smartcard_status_callback, callbackData, &irp);
5159 if (result != CHANNEL_RC_OK)
5163 *completionId = irp->CompletionId;
5167 .handles.hContext = call->handles.hContext,
5168 .handles.hCard = call->handles.hCard,
5169 .fmszReaderNamesIsNULL = call->fmszReaderNamesIsNULL,
5170 .cchReaderLen = call->cchReaderLen,
5171 .cbAtrLen = call->cbAtrLen,
5174 wStream* s = Stream_New(
nullptr, 128);
5177 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5178 result = CHANNEL_RC_NO_MEMORY;
5182 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5183 if (rc != SCARD_S_SUCCESS)
5185 result = ERROR_INTERNAL_ERROR;
5189 result = rdpdr_server_send_device_control_request(
5190 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5191 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5195 if (result != CHANNEL_RC_OK)
5196 rdpdr_server_discard_request(context, irp->CompletionId);
5203static UINT rdpdr_server_smartcard_statusA(RdpdrServerContext* context,
void* callbackData,
5206 return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSA, call,
5210static UINT rdpdr_server_smartcard_statusW(RdpdrServerContext* context,
void* callbackData,
5213 return rdpdr_server_smartcard_status(context, callbackData, SCARD_IOCTL_STATUSW, call,
5218static UINT rdpdr_server_smartcard_transmit_callback(RdpdrServerContext* context,
wStream* s,
5219 RDPDR_IRP* irp, UINT32 deviceId,
5220 UINT32 completionId, UINT32 ioStatus)
5222 WINPR_ASSERT(context);
5223 WINPR_ASSERT(context->priv);
5227 UINT result = CHANNEL_RC_OK;
5228 RdpdrServerPrivate* priv = context->priv;
5231 WLog_Print(priv->log, WLOG_DEBUG,
5232 "SmartcardTransmitCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5233 ", ioStatus=0x%" PRIx32,
5234 deviceId, completionId, ioStatus);
5236 if (ioStatus != STATUS_SUCCESS)
5238 if (context->OnSmartcardTransmitComplete)
5239 context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus,
5240 SCARD_F_INTERNAL_ERROR,
nullptr);
5244 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5245 if (rc != SCARD_S_SUCCESS)
5247 result = ERROR_INVALID_DATA;
5251 if (context->OnSmartcardTransmitComplete)
5252 context->OnSmartcardTransmitComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5256 smartcard_operation_free(&op, FALSE);
5257 rdpdr_server_irp_free(irp);
5261static UINT rdpdr_server_smartcard_transmit(RdpdrServerContext* context,
void* callbackData,
5264 WINPR_ASSERT(context);
5265 WINPR_ASSERT(context->priv);
5267 WINPR_ASSERT(completionId);
5269 RdpdrServerPrivate* priv = context->priv;
5270 RDPDR_IRP* irp =
nullptr;
5273 prepare_smartcard_irp(context, SCARD_IOCTL_TRANSMIT,
5274 rdpdr_server_smartcard_transmit_callback, callbackData, &irp);
5275 if (result != CHANNEL_RC_OK)
5279 *completionId = irp->CompletionId;
5282 .call.transmit = *call };
5284 wStream* s = Stream_New(
nullptr, 512 + call->cbSendLength);
5287 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5288 result = CHANNEL_RC_NO_MEMORY;
5292 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5293 if (rc != SCARD_S_SUCCESS)
5295 result = ERROR_INTERNAL_ERROR;
5299 result = rdpdr_server_send_device_control_request(
5300 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5301 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5305 if (result != CHANNEL_RC_OK)
5306 rdpdr_server_discard_request(context, irp->CompletionId);
5314static UINT rdpdr_server_smartcard_control_callback(RdpdrServerContext* context,
wStream* s,
5315 RDPDR_IRP* irp, UINT32 deviceId,
5316 UINT32 completionId, UINT32 ioStatus)
5318 WINPR_ASSERT(context);
5319 WINPR_ASSERT(context->priv);
5323 UINT result = CHANNEL_RC_OK;
5324 RdpdrServerPrivate* priv = context->priv;
5327 WLog_Print(priv->log, WLOG_DEBUG,
5328 "SmartcardControlCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5329 ", ioStatus=0x%" PRIx32,
5330 deviceId, completionId, ioStatus);
5332 if (ioStatus != STATUS_SUCCESS)
5334 if (context->OnSmartcardControlComplete)
5335 context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus,
5336 SCARD_F_INTERNAL_ERROR,
nullptr);
5340 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5341 if (rc != SCARD_S_SUCCESS)
5343 result = ERROR_INVALID_DATA;
5347 if (context->OnSmartcardControlComplete)
5348 context->OnSmartcardControlComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5352 smartcard_operation_free(&op, FALSE);
5353 rdpdr_server_irp_free(irp);
5357static UINT rdpdr_server_smartcard_control(RdpdrServerContext* context,
void* callbackData,
5360 WINPR_ASSERT(context);
5361 WINPR_ASSERT(context->priv);
5363 WINPR_ASSERT(completionId);
5365 RdpdrServerPrivate* priv = context->priv;
5366 RDPDR_IRP* irp =
nullptr;
5368 UINT result = prepare_smartcard_irp(
5369 context, SCARD_IOCTL_CONTROL, rdpdr_server_smartcard_control_callback, callbackData, &irp);
5370 if (result != CHANNEL_RC_OK)
5374 *completionId = irp->CompletionId;
5378 .handles.hContext = call->handles.hContext,
5379 .handles.hCard = call->handles.hCard,
5380 .dwControlCode = call->dwControlCode,
5381 .cbInBufferSize = call->cbInBufferSize,
5382 .pvInBuffer = call->pvInBuffer,
5383 .fpvOutBufferIsNULL = call->fpvOutBufferIsNULL,
5384 .cbOutBufferSize = call->cbOutBufferSize,
5387 wStream* s = Stream_New(
nullptr, 512 + call->cbOutBufferSize);
5390 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5391 result = CHANNEL_RC_NO_MEMORY;
5395 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5396 if (rc != SCARD_S_SUCCESS)
5398 result = ERROR_INTERNAL_ERROR;
5402 result = rdpdr_server_send_device_control_request(
5403 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5404 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5408 if (result != CHANNEL_RC_OK)
5409 rdpdr_server_discard_request(context, irp->CompletionId);
5417static UINT rdpdr_server_smartcard_get_attrib_callback(RdpdrServerContext* context,
wStream* s,
5418 RDPDR_IRP* irp, UINT32 deviceId,
5419 UINT32 completionId, UINT32 ioStatus)
5421 WINPR_ASSERT(context);
5422 WINPR_ASSERT(context->priv);
5426 UINT result = CHANNEL_RC_OK;
5427 RdpdrServerPrivate* priv = context->priv;
5430 WLog_Print(priv->log, WLOG_DEBUG,
5431 "SmartcardGetAttribCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5432 ", ioStatus=0x%" PRIx32,
5433 deviceId, completionId, ioStatus);
5435 if (ioStatus != STATUS_SUCCESS)
5437 if (context->OnSmartcardGetAttribComplete)
5438 context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus,
5439 SCARD_F_INTERNAL_ERROR,
nullptr);
5443 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5444 if (rc != SCARD_S_SUCCESS)
5446 result = ERROR_INVALID_DATA;
5450 if (context->OnSmartcardGetAttribComplete)
5451 context->OnSmartcardGetAttribComplete(context, irp->CallbackData, ioStatus, op.
returnCode,
5455 smartcard_operation_free(&op, FALSE);
5456 rdpdr_server_irp_free(irp);
5460static UINT rdpdr_server_smartcard_get_attrib(RdpdrServerContext* context,
void* callbackData,
5463 WINPR_ASSERT(context);
5464 WINPR_ASSERT(context->priv);
5466 WINPR_ASSERT(completionId);
5468 RdpdrServerPrivate* priv = context->priv;
5470 RDPDR_IRP* irp =
nullptr;
5472 prepare_smartcard_irp(context, SCARD_IOCTL_GETATTRIB,
5473 rdpdr_server_smartcard_get_attrib_callback, callbackData, &irp);
5474 if (ret != CHANNEL_RC_OK)
5478 *completionId = irp->CompletionId;
5481 .call.getAttrib = *call };
5483 UINT error = CHANNEL_RC_NO_MEMORY;
5484 wStream* s = Stream_New(
nullptr, 64);
5487 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5491 LONG status = smartcard_irp_device_control_encode_request(s, &op);
5492 if (status != SCARD_S_SUCCESS)
5494 error = ERROR_INTERNAL_ERROR;
5498 error = rdpdr_server_send_device_control_request(
5499 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5500 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5504 if (error != CHANNEL_RC_OK && irp)
5505 rdpdr_server_discard_request(context, irp->CompletionId);
5513static UINT rdpdr_server_smartcard_set_attrib_callback(RdpdrServerContext* context,
wStream* s,
5514 RDPDR_IRP* irp, UINT32 deviceId,
5515 UINT32 completionId, UINT32 ioStatus)
5517 WINPR_ASSERT(context);
5518 WINPR_ASSERT(context->priv);
5522 UINT result = CHANNEL_RC_OK;
5523 RdpdrServerPrivate* priv = context->priv;
5526 WLog_Print(priv->log, WLOG_DEBUG,
5527 "SmartcardSetAttribCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
5528 ", ioStatus=0x%" PRIx32,
5529 deviceId, completionId, ioStatus);
5531 if (ioStatus != STATUS_SUCCESS)
5533 if (context->OnSmartcardSetAttribComplete)
5534 context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus,
5535 SCARD_F_INTERNAL_ERROR);
5539 const LONG rc = smartcard_irp_device_control_decode_response(s, irp->IoControlCode, &op);
5540 if (rc != SCARD_S_SUCCESS)
5542 result = ERROR_INVALID_DATA;
5546 if (context->OnSmartcardSetAttribComplete)
5547 context->OnSmartcardSetAttribComplete(context, irp->CallbackData, ioStatus, op.
returnCode);
5550 smartcard_operation_free(&op, FALSE);
5551 rdpdr_server_irp_free(irp);
5555static UINT rdpdr_server_smartcard_set_attrib(RdpdrServerContext* context,
void* callbackData,
5558 WINPR_ASSERT(context);
5559 WINPR_ASSERT(context->priv);
5561 WINPR_ASSERT(completionId);
5563 RdpdrServerPrivate* priv = context->priv;
5564 RDPDR_IRP* irp =
nullptr;
5567 prepare_smartcard_irp(context, SCARD_IOCTL_SETATTRIB,
5568 rdpdr_server_smartcard_set_attrib_callback, callbackData, &irp);
5569 if (result != CHANNEL_RC_OK)
5573 *completionId = irp->CompletionId;
5577 .handles.hContext = call->handles.hContext,
5578 .handles.hCard = call->handles.hCard,
5579 .dwAttrId = call->dwAttrId,
5580 .cbAttrLen = call->cbAttrLen,
5581 .pbAttr = call->pbAttr,
5584 wStream* s = Stream_New(
nullptr, 64 + call->cbAttrLen);
5587 WLog_Print(priv->log, WLOG_ERROR,
"Stream_New failed!");
5588 result = CHANNEL_RC_NO_MEMORY;
5592 const LONG rc = smartcard_irp_device_control_encode_request(s, &op);
5593 if (rc != SCARD_S_SUCCESS)
5595 result = ERROR_INTERNAL_ERROR;
5599 result = rdpdr_server_send_device_control_request(
5600 context, irp->DeviceId, irp->CompletionId, irp->IoControlCode,
5601 SCARD_IOCTL_MAX_OUTPUT_BUFFER_LENGTH, Stream_Buffer(s), Stream_Length(s));
5605 if (result != CHANNEL_RC_OK)
5606 rdpdr_server_discard_request(context, irp->CompletionId);
5613RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
5615 RdpdrServerContext* context = (RdpdrServerContext*)calloc(1,
sizeof(RdpdrServerContext));
5621 context->Start = rdpdr_server_start;
5622 context->Stop = rdpdr_server_stop;
5623 context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
5624 context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
5625 context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
5626 context->DriveOpenFile = rdpdr_server_drive_open_file;
5627 context->DriveReadFile = rdpdr_server_drive_read_file;
5628 context->DriveWriteFile = rdpdr_server_drive_write_file;
5629 context->DriveCloseFile = rdpdr_server_drive_close_file;
5630 context->DriveDeleteFile = rdpdr_server_drive_delete_file;
5631 context->DriveRenameFile = rdpdr_server_drive_rename_file;
5632 context->SmartcardEstablishContext = rdpdr_server_smartcard_establish_context;
5633 context->SmartcardReleaseContext = rdpdr_server_smartcard_release_context;
5634 context->SmartcardIsValidContext = rdpdr_server_smartcard_is_valid_context;
5635 context->SmartcardListReaderGroupsA = rdpdr_server_smartcard_list_reader_groupsA;
5636 context->SmartcardListReaderGroupsW = rdpdr_server_smartcard_list_reader_groupsW;
5637 context->SmartcardListReadersA = rdpdr_server_smartcard_list_readersA;
5638 context->SmartcardListReadersW = rdpdr_server_smartcard_list_readersW;
5639 context->SmartcardGetStatusChangeA = rdpdr_server_smartcard_get_status_changeA;
5640 context->SmartcardGetStatusChangeW = rdpdr_server_smartcard_get_status_changeW;
5641 context->SmartcardCancel = rdpdr_server_smartcard_cancel;
5642 context->SmartcardConnectA = rdpdr_server_smartcard_connectA;
5643 context->SmartcardConnectW = rdpdr_server_smartcard_connectW;
5644 context->SmartcardReconnect = rdpdr_server_smartcard_reconnect;
5645 context->SmartcardDisconnect = rdpdr_server_smartcard_disconnect;
5646 context->SmartcardBeginTransaction = rdpdr_server_smartcard_begin_transaction;
5647 context->SmartcardEndTransaction = rdpdr_server_smartcard_end_transaction;
5648 context->SmartcardStatusA = rdpdr_server_smartcard_statusA;
5649 context->SmartcardStatusW = rdpdr_server_smartcard_statusW;
5650 context->SmartcardTransmit = rdpdr_server_smartcard_transmit;
5651 context->SmartcardControl = rdpdr_server_smartcard_control;
5652 context->SmartcardGetAttrib = rdpdr_server_smartcard_get_attrib;
5653 context->SmartcardSetAttrib = rdpdr_server_smartcard_set_attrib;
5654 context->priv = rdpdr_server_private_new();
5659 context->supported = UINT16_MAX;
5663 WINPR_PRAGMA_DIAG_PUSH
5664 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
5665 rdpdr_server_context_free(context);
5666 WINPR_PRAGMA_DIAG_POP
5670void rdpdr_server_context_free(RdpdrServerContext* context)
5675 rdpdr_server_private_free(context->priv);
5679void rdpdr_server_discard_request(RdpdrServerContext* context, UINT32 completionId)
5681 WINPR_ASSERT(context);
5683 RdpdrServerPrivate* priv = context->priv;
5684 const uintptr_t key = completionId + 1ull;
5685 ListDictionary_Remove(priv->IrpList, (
void*)key);
union SMARTCARD_OPERATION::@35 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