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 "rdpdr_main.h"
37#define RDPDR_ADD_PRINTER_EVENT 0x00000001
38#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
39#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
40#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
42#define RDPDR_HEADER_LENGTH 4
43#define RDPDR_CAPABILITY_HEADER_LENGTH 8
45struct s_rdpdr_server_private
54 char* ClientComputerName;
58 wListDictionary* IrpList;
59 UINT32 NextCompletionId;
61 wHashTable* devicelist;
63 UINT32 SpecialDeviceTypeCap;
68static const char* fileInformation2str(uint8_t val)
73 return "FILE_DOES_NOT_EXIST";
77 return "FILE_OVERWRITTEN";
78 case FILE_OVERWRITTEN:
79 return "FILE_CREATED";
82 case FILE_DOES_NOT_EXIST:
83 return "FILE_SUPERSEDED";
85 return "FILE_UNKNOWN";
89static const char* DR_DRIVE_LOCK_REQ2str(uint32_t op)
93 case RDP_LOWIO_OP_SHAREDLOCK:
94 return "RDP_LOWIO_OP_UNLOCK_MULTIPLE";
95 case RDP_LOWIO_OP_EXCLUSIVELOCK:
96 return "RDP_LOWIO_OP_UNLOCK";
97 case RDP_LOWIO_OP_UNLOCK:
98 return "RDP_LOWIO_OP_EXCLUSIVELOCK";
99 case RDP_LOWIO_OP_UNLOCK_MULTIPLE:
100 return "RDP_LOWIO_OP_SHAREDLOCK";
102 return "RDP_LOWIO_OP_UNKNOWN";
110 free(device->DeviceData);
114static void rdpdr_device_free_h(
void* obj)
117 rdpdr_device_free(other);
120static UINT32 rdpdr_deviceid_hash(
const void*
id)
123 return *((
const UINT32*)
id);
126static BOOL rdpdr_device_equal(
const void* v1,
const void* v2)
128 const UINT32* p1 = (
const UINT32*)v1;
129 const UINT32* p2 = (
const UINT32*)v2;
142static void* rdpdr_device_clone(
const void* val)
154 if (other->DeviceData)
156 tmp->DeviceData = malloc(other->DeviceDataLength);
157 if (!tmp->DeviceData)
159 memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
164 rdpdr_device_free(tmp);
168static void* rdpdr_device_key_clone(
const void* pvval)
170 const UINT32* val = pvval;
174 UINT32* ptr = calloc(1,
sizeof(UINT32));
181static void rdpdr_device_key_free(
void* obj)
186static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
189 return HashTable_GetItemValue(priv->devicelist, &DeviceId);
192static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
194 const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
199 WLog_Print(priv->log, WLOG_WARN,
"[del] Device Id: 0x%08" PRIX32
": no such device",
203 WLog_Print(priv->log, WLOG_DEBUG,
204 "[del] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
205 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
206 return HashTable_Remove(priv->devicelist, &DeviceId);
209static BOOL rdpdr_add_device(RdpdrServerPrivate* priv,
const RdpdrDevice* device)
212 WINPR_ASSERT(device);
214 WLog_Print(priv->log, WLOG_DEBUG,
215 "[add] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
216 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
218 return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
221static UINT32 g_ClientId = 0;
223static const WCHAR* rdpdr_read_ustring(wLog* log,
wStream* s,
size_t bytelen)
225 const size_t charlen = (bytelen + 1) /
sizeof(WCHAR);
226 const WCHAR* str = Stream_ConstPointer(s);
227 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, bytelen))
229 if (_wcsnlen(str, charlen) == charlen)
231 WLog_Print(log, WLOG_WARN,
"[rdpdr] unicode string not '\\0' terminated");
234 Stream_Seek(s, bytelen);
238static RDPDR_IRP* rdpdr_server_irp_new(
void)
244static void rdpdr_server_irp_free(
RDPDR_IRP* irp)
249static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context,
RDPDR_IRP* irp)
251 WINPR_ASSERT(context);
252 WINPR_ASSERT(context->priv);
253 const uintptr_t key = irp->CompletionId + 1ull;
254 return ListDictionary_Add(context->priv->IrpList, (
void*)key, irp);
257static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
260 WINPR_ASSERT(context);
261 WINPR_ASSERT(context->priv);
263 const uintptr_t key = completionId + 1ull;
264 irp = (
RDPDR_IRP*)ListDictionary_Take(context->priv->IrpList, (
void*)key);
268static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context,
wStream* s)
273 WINPR_ASSERT(context);
274 WINPR_ASSERT(context->priv);
277 Stream_SealLength(s);
278 const size_t length = Stream_Length(s);
279 WINPR_ASSERT(length <= UINT32_MAX);
280 Stream_SetPosition(s, 0);
282 if (length >= RDPDR_HEADER_LENGTH)
285 Stream_Read_UINT16(s, header.Component);
286 Stream_Read_UINT16(s, header.PacketId);
288 WLog_Print(context->priv->log, WLOG_DEBUG,
289 "sending message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
290 rdpdr_component_string(header.Component), header.Component,
291 rdpdr_packetid_string(header.PacketId), header.PacketId);
293 winpr_HexLogDump(context->priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
294 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
295 (ULONG)length, &written);
296 Stream_Free(s, TRUE);
297 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
305static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
311 WINPR_ASSERT(context);
312 WINPR_ASSERT(context->priv);
314 header.Component = RDPDR_CTYP_CORE;
315 header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
317 error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
318 if (error != CHANNEL_RC_OK)
321 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
325 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
326 return CHANNEL_RC_NO_MEMORY;
329 Stream_Write_UINT16(s, header.Component);
330 Stream_Write_UINT16(s, header.PacketId);
331 Stream_Write_UINT16(s, context->priv->VersionMajor);
332 Stream_Write_UINT16(s, context->priv->VersionMinor);
333 Stream_Write_UINT32(s, context->priv->ClientId);
334 return rdpdr_seal_send_free_request(context, s);
342static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
wStream* s,
346 UINT16 VersionMajor = 0;
347 UINT16 VersionMinor = 0;
348 WINPR_ASSERT(context);
349 WINPR_ASSERT(context->priv);
350 WINPR_ASSERT(header);
352 WINPR_UNUSED(header);
354 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
355 return ERROR_INVALID_DATA;
357 Stream_Read_UINT16(s, VersionMajor);
358 Stream_Read_UINT16(s, VersionMinor);
359 Stream_Read_UINT32(s, ClientId);
360 WLog_Print(context->priv->log, WLOG_DEBUG,
361 "Client Announce Response: VersionMajor: 0x%08" PRIX16
" VersionMinor: 0x%04" PRIX16
362 " ClientId: 0x%08" PRIX32
"",
363 VersionMajor, VersionMinor, ClientId);
364 context->priv->ClientId = ClientId;
366 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
367 VersionMinor, ClientId);
375static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context,
wStream* s,
378 UINT32 UnicodeFlag = 0;
380 UINT32 ComputerNameLen = 0;
382 WINPR_ASSERT(context);
383 WINPR_ASSERT(context->priv);
385 WINPR_ASSERT(header);
386 WINPR_UNUSED(header);
388 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
389 return ERROR_INVALID_DATA;
391 Stream_Read_UINT32(s, UnicodeFlag);
392 Stream_Read_UINT32(s, CodePage);
393 Stream_Read_UINT32(s, ComputerNameLen);
396 UnicodeFlag = UnicodeFlag & 0x00000001;
399 WLog_Print(context->priv->log, WLOG_WARN,
400 "[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
401 "must be 0, but is 0x%08" PRIx32,
411 if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
413 WLog_Print(context->priv->log, WLOG_ERROR,
414 "invalid unicode computer name length: %" PRIu32
"", ComputerNameLen);
415 return ERROR_INVALID_DATA;
420 if (ComputerNameLen > 256 || ComputerNameLen < 1)
422 WLog_Print(context->priv->log, WLOG_ERROR,
423 "invalid ascii computer name length: %" PRIu32
"", ComputerNameLen);
424 return ERROR_INVALID_DATA;
428 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, ComputerNameLen))
429 return ERROR_INVALID_DATA;
432 const char* computerName = Stream_ConstPointer(s);
433 if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
435 WLog_Print(context->priv->log, WLOG_ERROR,
"computer name must be null terminated");
436 return ERROR_INVALID_DATA;
439 if (context->priv->ClientComputerName)
441 free(context->priv->ClientComputerName);
442 context->priv->ClientComputerName = NULL;
447 context->priv->ClientComputerName =
448 Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen /
sizeof(WCHAR), NULL);
449 if (!context->priv->ClientComputerName)
451 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to convert client computer name");
452 return ERROR_INVALID_DATA;
457 const char* name = Stream_ConstPointer(s);
458 context->priv->ClientComputerName = _strdup(name);
459 Stream_Seek(s, ComputerNameLen);
461 if (!context->priv->ClientComputerName)
463 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to duplicate client computer name");
464 return CHANNEL_RC_NO_MEMORY;
468 WLog_Print(context->priv->log, WLOG_DEBUG,
"ClientComputerName: %s",
469 context->priv->ClientComputerName);
470 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
471 context->priv->ClientComputerName);
474static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context,
wStream* s,
477 WINPR_ASSERT(context);
478 WINPR_ASSERT(context->priv);
479 UINT error = rdpdr_write_capset_header(context->priv->log, s, header);
480 if (error != CHANNEL_RC_OK)
483 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0, NULL);
491static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context,
wStream* s,
494 WINPR_ASSERT(context);
495 WINPR_ASSERT(context->priv);
496 WINPR_ASSERT(header);
498 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
499 return ERROR_INVALID_DATA;
501 const UINT32 OsType = Stream_Get_UINT32(s);
502 const UINT32 OsVersion =
503 Stream_Get_UINT32(s);
504 const UINT32 VersionMajor = Stream_Get_UINT16(s);
505 const UINT32 VersionMinor = Stream_Get_UINT16(s);
506 const UINT32 IoCode1 = Stream_Get_UINT32(s);
507 const UINT32 IoCode2 =
508 Stream_Get_UINT32(s);
509 const UINT32 ExtendedPdu = Stream_Get_UINT32(s);
510 const UINT32 ExtraFlags1 = Stream_Get_UINT32(s);
511 const UINT32 ExtraFlags2 = Stream_Get_UINT32(
515 char buffer[1024] = { 0 };
516 WLog_Print(context->priv->log, WLOG_TRACE,
517 "OsType=%" PRIu32
", OsVersion=%" PRIu32
", VersionMajor=%" PRIu32
518 ", VersionMinor=%" PRIu32
", IoCode1=%s, IoCode2=%" PRIu32
519 ", ExtendedPdu=%" PRIu32
", ExtraFlags1=%" PRIu32
", ExtraFlags2=%" PRIu32,
520 OsType, OsVersion, VersionMajor, VersionMinor,
521 rdpdr_irp_mask2str(IoCode1, buffer,
sizeof(buffer)), IoCode2, ExtendedPdu,
522 ExtraFlags1, ExtraFlags2);
525 if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
527 WLog_Print(context->priv->log, WLOG_ERROR,
"unsupported RDPDR version %" PRIu16
".%" PRIu16,
528 VersionMajor, VersionMinor);
529 return ERROR_INVALID_DATA;
532 switch (VersionMinor)
534 case RDPDR_MINOR_RDP_VERSION_13:
535 case RDPDR_MINOR_RDP_VERSION_6_X:
536 case RDPDR_MINOR_RDP_VERSION_5_2:
537 case RDPDR_MINOR_RDP_VERSION_5_1:
538 case RDPDR_MINOR_RDP_VERSION_5_0:
541 WLog_Print(context->priv->log, WLOG_WARN,
542 "unsupported RDPDR minor version %" PRIu16
".%" PRIu16, VersionMajor,
547 UINT32 SpecialTypeDeviceCap = 0;
548 if (header->Version == GENERAL_CAPABILITY_VERSION_02)
550 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
551 return ERROR_INVALID_DATA;
553 SpecialTypeDeviceCap = Stream_Get_UINT32(s);
555 context->priv->SpecialDeviceTypeCap = SpecialTypeDeviceCap;
558 RDPDR_IRP_MJ_CREATE | RDPDR_IRP_MJ_CLEANUP | RDPDR_IRP_MJ_CLOSE | RDPDR_IRP_MJ_READ |
559 RDPDR_IRP_MJ_WRITE | RDPDR_IRP_MJ_FLUSH_BUFFERS | RDPDR_IRP_MJ_SHUTDOWN |
560 RDPDR_IRP_MJ_DEVICE_CONTROL | RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION |
561 RDPDR_IRP_MJ_SET_VOLUME_INFORMATION | RDPDR_IRP_MJ_QUERY_INFORMATION |
562 RDPDR_IRP_MJ_SET_INFORMATION | RDPDR_IRP_MJ_DIRECTORY_CONTROL | RDPDR_IRP_MJ_LOCK_CONTROL;
564 if ((IoCode1 & mask) == 0)
566 char buffer[1024] = { 0 };
567 WLog_Print(context->priv->log, WLOG_ERROR,
"Missing IRP mask values %s",
568 rdpdr_irp_mask2str(IoCode1 & mask, buffer,
sizeof(buffer)));
569 return ERROR_INVALID_DATA;
571 context->priv->IoCode1 = IoCode1;
575 WLog_Print(context->priv->log, WLOG_WARN,
576 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ioCode2 is "
577 "reserved for future use, expected value 0 got %" PRIu32,
581 if ((ExtendedPdu & RDPDR_CLIENT_DISPLAY_NAME_PDU) == 0)
583 WLog_Print(context->priv->log, WLOG_WARN,
584 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) extendedPDU "
585 "should always set RDPDR_CLIENT_DISPLAY_NAME_PDU[0x00000002]");
588 context->priv->ExtendedPDU = ExtendedPdu;
589 context->priv->UserLoggedOnPdu = (ExtendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
591 if (ExtraFlags2 != 0)
593 WLog_Print(context->priv->log, WLOG_WARN,
594 "[MS-RDPEFS] 2.2.2.7.1 General Capability Set (GENERAL_CAPS_SET) ExtraFlags2 is "
595 "reserved for future use, expected value 0 got %" PRIu32,
599 return CHANNEL_RC_OK;
607static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context,
wStream* s)
610 UINT32 extendedPdu = 0;
611 UINT32 extraFlags1 = 0;
612 UINT32 SpecialTypeDeviceCap = 0;
614 GENERAL_CAPABILITY_VERSION_02 };
616 WINPR_ASSERT(context);
617 WINPR_ASSERT(context->priv);
620 ioCode1 |= RDPDR_IRP_MJ_CREATE;
621 ioCode1 |= RDPDR_IRP_MJ_CLEANUP;
622 ioCode1 |= RDPDR_IRP_MJ_CLOSE;
623 ioCode1 |= RDPDR_IRP_MJ_READ;
624 ioCode1 |= RDPDR_IRP_MJ_WRITE;
625 ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS;
626 ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN;
627 ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL;
628 ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION;
629 ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION;
630 ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION;
631 ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION;
632 ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL;
633 ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL;
634 ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY;
635 ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY;
637 extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU;
638 extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS;
640 if (context->priv->UserLoggedOnPdu)
641 extendedPdu |= RDPDR_USER_LOGGEDON_PDU;
644 extraFlags1 |= ENABLE_ASYNCIO;
645 SpecialTypeDeviceCap = 0;
647 UINT error = rdpdr_write_capset_header(context->priv->log, s, &header);
648 if (error != CHANNEL_RC_OK)
651 const BYTE* data = Stream_ConstPointer(s);
652 const size_t start = Stream_GetPosition(s);
653 Stream_Write_UINT32(s, 0);
654 Stream_Write_UINT32(s, 0);
655 Stream_Write_UINT16(s, context->priv->VersionMajor);
656 Stream_Write_UINT16(s, context->priv->VersionMinor);
657 Stream_Write_UINT32(s, ioCode1);
658 Stream_Write_UINT32(s, 0);
659 Stream_Write_UINT32(s, extendedPdu);
660 Stream_Write_UINT32(s, extraFlags1);
663 Stream_Write_UINT32(s, SpecialTypeDeviceCap);
664 const size_t end = Stream_GetPosition(s);
665 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
673static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context,
wStream* s,
676 WINPR_ASSERT(context);
677 WINPR_ASSERT(context->priv);
679 WINPR_ASSERT(header);
680 WINPR_UNUSED(context);
681 WINPR_UNUSED(header);
684 return CHANNEL_RC_OK;
692static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context,
wStream* s)
695 PRINT_CAPABILITY_VERSION_01 };
696 WINPR_UNUSED(context);
697 WINPR_ASSERT(context);
698 WINPR_ASSERT(context->priv);
700 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
708static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context,
wStream* s,
711 WINPR_UNUSED(context);
713 WINPR_UNUSED(header);
714 WINPR_ASSERT(context);
715 WINPR_ASSERT(context->priv);
717 return CHANNEL_RC_OK;
725static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
wStream* s)
728 PORT_CAPABILITY_VERSION_01 };
729 WINPR_UNUSED(context);
730 WINPR_ASSERT(context);
731 WINPR_ASSERT(context->priv);
733 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
741static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
wStream* s,
744 WINPR_ASSERT(context);
745 WINPR_ASSERT(context->priv);
746 WINPR_UNUSED(context);
747 WINPR_UNUSED(header);
750 return CHANNEL_RC_OK;
758static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
wStream* s)
761 DRIVE_CAPABILITY_VERSION_02 };
763 WINPR_ASSERT(context);
764 WINPR_ASSERT(context->priv);
765 WINPR_UNUSED(context);
767 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
775static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context,
wStream* s,
778 WINPR_ASSERT(context);
779 WINPR_ASSERT(context->priv);
780 WINPR_UNUSED(context);
781 WINPR_UNUSED(header);
784 return CHANNEL_RC_OK;
792static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context,
wStream* s)
795 SMARTCARD_CAPABILITY_VERSION_01 };
796 WINPR_ASSERT(context);
797 WINPR_ASSERT(context->priv);
799 WINPR_UNUSED(context);
801 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
809static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
813 UINT16 numCapabilities = 0;
815 WINPR_ASSERT(context);
816 WINPR_ASSERT(context->priv);
818 header.Component = RDPDR_CTYP_CORE;
819 header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
822 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
825 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
826 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
829 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
832 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
835 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
839 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
840 return CHANNEL_RC_NO_MEMORY;
843 Stream_Write_UINT16(s, header.Component);
844 Stream_Write_UINT16(s, header.PacketId);
845 Stream_Write_UINT16(s, numCapabilities);
846 Stream_Write_UINT16(s, 0);
848 if ((error = rdpdr_server_write_general_capability_set(context, s)))
850 WLog_Print(context->priv->log, WLOG_ERROR,
851 "rdpdr_server_write_general_capability_set failed with error %" PRIu32
"!",
856 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
858 if ((error = rdpdr_server_write_drive_capability_set(context, s)))
860 WLog_Print(context->priv->log, WLOG_ERROR,
861 "rdpdr_server_write_drive_capability_set failed with error %" PRIu32
"!",
867 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
868 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
870 if ((error = rdpdr_server_write_port_capability_set(context, s)))
872 WLog_Print(context->priv->log, WLOG_ERROR,
873 "rdpdr_server_write_port_capability_set failed with error %" PRIu32
"!",
879 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
881 if ((error = rdpdr_server_write_printer_capability_set(context, s)))
883 WLog_Print(context->priv->log, WLOG_ERROR,
884 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
890 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
892 if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
894 WLog_Print(context->priv->log, WLOG_ERROR,
895 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
901 return rdpdr_seal_send_free_request(context, s);
903 Stream_Free(s, TRUE);
912static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context,
wStream* s,
916 UINT16 numCapabilities = 0;
918 WINPR_ASSERT(context);
919 WINPR_ASSERT(context->priv);
921 WINPR_UNUSED(header);
923 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
924 return ERROR_INVALID_DATA;
926 Stream_Read_UINT16(s, numCapabilities);
927 Stream_Seek_UINT16(s);
930 for (UINT16 i = 0; i < numCapabilities; i++)
933 const size_t start = Stream_GetPosition(s);
935 if ((status = rdpdr_read_capset_header(context->priv->log, s, &capabilityHeader)))
937 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
941 status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
942 Stream_GetRemainingLength(s), Stream_ConstPointer(s));
943 if (status != CHANNEL_RC_OK)
946 caps |= capabilityHeader.CapabilityType;
947 switch (capabilityHeader.CapabilityType)
949 case CAP_GENERAL_TYPE:
951 rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
953 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
960 case CAP_PRINTER_TYPE:
962 rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
964 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
972 if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
974 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
983 rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
985 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
992 case CAP_SMARTCARD_TYPE:
994 rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
996 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
1004 WLog_Print(context->priv->log, WLOG_WARN,
"Unknown capabilityType %" PRIu16
"",
1005 capabilityHeader.CapabilityType);
1006 Stream_Seek(s, capabilityHeader.CapabilityLength);
1007 return ERROR_INVALID_DATA;
1010 for (UINT16 x = 0; x < 16; x++)
1012 const UINT16 mask = (UINT16)(1 << x);
1013 if (((caps & mask) != 0) && ((context->supported & mask) == 0))
1015 WLog_Print(context->priv->log, WLOG_WARN,
1016 "client sent capability %s we did not announce!",
1022 if ((caps & mask) == 0)
1023 context->supported &= ~mask;
1026 const size_t end = Stream_GetPosition(s);
1027 const size_t diff = end - start;
1028 if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
1030 WLog_Print(context->priv->log, WLOG_WARN,
1031 "{capability %s[0x%04" PRIx16
"]} processed %" PRIuz
1032 " bytes, but expected to be %" PRIu16,
1033 rdpdr_cap_type_string(capabilityHeader.CapabilityType),
1034 capabilityHeader.CapabilityType, diff, capabilityHeader.CapabilityLength);
1038 return CHANNEL_RC_OK;
1046static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
1051 WINPR_ASSERT(context);
1052 WINPR_ASSERT(context->priv);
1054 header.Component = RDPDR_CTYP_CORE;
1055 header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
1056 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
1060 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1061 return CHANNEL_RC_NO_MEMORY;
1064 Stream_Write_UINT16(s, header.Component);
1065 Stream_Write_UINT16(s, header.PacketId);
1066 Stream_Write_UINT16(s, context->priv->VersionMajor);
1067 Stream_Write_UINT16(s, context->priv->VersionMinor);
1068 Stream_Write_UINT32(s, context->priv->ClientId);
1069 return rdpdr_seal_send_free_request(context, s);
1077static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context,
1081 UINT32 DeviceCount = 0;
1083 WINPR_ASSERT(context);
1084 WINPR_ASSERT(context->priv);
1086 WINPR_UNUSED(header);
1088 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1089 return ERROR_INVALID_DATA;
1091 Stream_Read_UINT32(s, DeviceCount);
1092 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1094 for (UINT32 i = 0; i < DeviceCount; i++)
1099 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
1100 return ERROR_INVALID_DATA;
1102 Stream_Read_UINT32(s, device.DeviceType);
1103 Stream_Read_UINT32(s, device.DeviceId);
1104 Stream_Read(s, device.PreferredDosName, 8);
1105 Stream_Read_UINT32(s, device.DeviceDataLength);
1106 device.DeviceData = Stream_Pointer(s);
1108 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, device.DeviceDataLength))
1109 return ERROR_INVALID_DATA;
1111 if (!rdpdr_add_device(context->priv, &device))
1112 return ERROR_INTERNAL_ERROR;
1114 error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
1115 if (error != CHANNEL_RC_OK)
1118 switch (device.DeviceType)
1120 case RDPDR_DTYP_FILESYSTEM:
1121 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1122 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
1125 case RDPDR_DTYP_PRINT:
1126 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1127 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
1130 case RDPDR_DTYP_SERIAL:
1131 if (device.DeviceDataLength != 0)
1133 WLog_Print(context->priv->log, WLOG_WARN,
1134 "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32
"]",
1135 device.DeviceDataLength);
1136 error = ERROR_INVALID_DATA;
1138 else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1140 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
1143 case RDPDR_DTYP_PARALLEL:
1144 if (device.DeviceDataLength != 0)
1146 WLog_Print(context->priv->log, WLOG_WARN,
1147 "[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32
"]",
1148 device.DeviceDataLength);
1149 error = ERROR_INVALID_DATA;
1151 else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1152 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
1156 case RDPDR_DTYP_SMARTCARD:
1157 if (device.DeviceDataLength != 0)
1159 WLog_Print(context->priv->log, WLOG_WARN,
1160 "[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32
"]",
1161 device.DeviceDataLength);
1162 error = ERROR_INVALID_DATA;
1164 else if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1166 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardCreate, context, &device);
1170 WLog_Print(context->priv->log, WLOG_WARN,
1171 "[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
1172 "(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
1173 " at position %" PRIu32,
1174 device.DeviceType, i);
1175 error = ERROR_INVALID_DATA;
1179 if (error != CHANNEL_RC_OK)
1182 Stream_Seek(s, device.DeviceDataLength);
1185 return CHANNEL_RC_OK;
1193static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context,
wStream* s,
1196 UINT32 DeviceCount = 0;
1197 UINT32 DeviceType = 0;
1198 UINT32 DeviceId = 0;
1199 WINPR_ASSERT(context);
1200 WINPR_ASSERT(context->priv);
1202 WINPR_UNUSED(header);
1204 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1205 return ERROR_INVALID_DATA;
1207 Stream_Read_UINT32(s, DeviceCount);
1208 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1210 for (UINT32 i = 0; i < DeviceCount; i++)
1215 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1216 return ERROR_INVALID_DATA;
1218 Stream_Read_UINT32(s, DeviceId);
1219 device = rdpdr_get_device_by_id(context->priv, DeviceId);
1220 WLog_Print(context->priv->log, WLOG_DEBUG,
"Device %" PRIu32
" Id: 0x%08" PRIX32
"", i,
1224 DeviceType = device->DeviceType;
1227 IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
1228 if (error != CHANNEL_RC_OK)
1233 case RDPDR_DTYP_FILESYSTEM:
1234 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1235 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
1238 case RDPDR_DTYP_PRINT:
1239 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1241 IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
1244 case RDPDR_DTYP_SERIAL:
1245 if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1247 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
1250 case RDPDR_DTYP_PARALLEL:
1251 if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1252 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
1256 case RDPDR_DTYP_SMARTCARD:
1257 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1259 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
1266 if (error != CHANNEL_RC_OK)
1269 if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
1270 return ERROR_INVALID_DATA;
1273 return CHANNEL_RC_OK;
1276static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
wStream* s,
1277 WINPR_ATTR_UNUSED UINT32 DeviceId,
1278 WINPR_ATTR_UNUSED UINT32 FileId,
1279 WINPR_ATTR_UNUSED UINT32 CompletionId)
1281 const WCHAR* path = NULL;
1282 UINT32 DesiredAccess = 0;
1283 UINT32 AllocationSize = 0;
1284 UINT32 FileAttributes = 0;
1285 UINT32 SharedAccess = 0;
1286 UINT32 CreateDisposition = 0;
1287 UINT32 CreateOptions = 0;
1288 UINT32 PathLength = 0;
1290 WINPR_ASSERT(context);
1291 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1292 return ERROR_INVALID_DATA;
1294 Stream_Read_UINT32(s, DesiredAccess);
1295 Stream_Read_UINT32(s, AllocationSize);
1296 Stream_Read_UINT32(s, FileAttributes);
1297 Stream_Read_UINT32(s, SharedAccess);
1298 Stream_Read_UINT32(s, CreateDisposition);
1299 Stream_Read_UINT32(s, CreateOptions);
1300 Stream_Read_UINT32(s, PathLength);
1302 path = rdpdr_read_ustring(context->priv->log, s, PathLength);
1303 if (!path && (PathLength > 0))
1304 return ERROR_INVALID_DATA;
1306 WLog_Print(context->priv->log, WLOG_WARN,
1307 "[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
1308 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1310 return CHANNEL_RC_OK;
1313static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context,
wStream* s,
1314 WINPR_ATTR_UNUSED UINT32 DeviceId,
1315 WINPR_ATTR_UNUSED UINT32 FileId,
1316 WINPR_ATTR_UNUSED UINT32 CompletionId)
1318 WINPR_ASSERT(context);
1319 WINPR_ASSERT(context->priv);
1321 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1322 return ERROR_INVALID_DATA;
1326 WLog_Print(context->priv->log, WLOG_WARN,
1327 "[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
1328 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1330 return CHANNEL_RC_OK;
1333static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context,
wStream* s,
1334 WINPR_ATTR_UNUSED UINT32 DeviceId,
1335 WINPR_ATTR_UNUSED UINT32 FileId,
1336 WINPR_ATTR_UNUSED UINT32 CompletionId)
1341 WINPR_ASSERT(context);
1342 WINPR_ASSERT(context->priv);
1343 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1344 return ERROR_INVALID_DATA;
1346 Stream_Read_UINT32(s, Length);
1347 Stream_Read_UINT64(s, Offset);
1350 WLog_Print(context->priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32,
1353 WLog_Print(context->priv->log, WLOG_WARN,
1354 "[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
1355 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1357 return CHANNEL_RC_OK;
1360static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context,
wStream* s,
1361 WINPR_ATTR_UNUSED UINT32 DeviceId,
1362 WINPR_ATTR_UNUSED UINT32 FileId,
1363 WINPR_ATTR_UNUSED UINT32 CompletionId)
1368 WINPR_ASSERT(context);
1369 WINPR_ASSERT(context->priv);
1371 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1372 return ERROR_INVALID_DATA;
1374 Stream_Read_UINT32(s, Length);
1375 Stream_Read_UINT64(s, Offset);
1378 WLog_Print(context->priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32,
1381 const BYTE* data = Stream_ConstPointer(s);
1382 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1383 return ERROR_INVALID_DATA;
1384 Stream_Seek(s, Length);
1386 WLog_Print(context->priv->log, WLOG_WARN,
1387 "[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
1388 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)data);
1390 return CHANNEL_RC_OK;
1393static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* context,
wStream* s,
1394 WINPR_ATTR_UNUSED UINT32 DeviceId,
1395 WINPR_ATTR_UNUSED UINT32 FileId,
1396 WINPR_ATTR_UNUSED UINT32 CompletionId)
1398 UINT32 OutputBufferLength = 0;
1399 UINT32 InputBufferLength = 0;
1400 UINT32 IoControlCode = 0;
1402 WINPR_ASSERT(context);
1403 WINPR_ASSERT(context->priv);
1405 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1406 return ERROR_INVALID_DATA;
1408 Stream_Read_UINT32(s, OutputBufferLength);
1409 Stream_Read_UINT32(s, InputBufferLength);
1410 Stream_Read_UINT32(s, IoControlCode);
1413 const BYTE* InputBuffer = Stream_ConstPointer(s);
1414 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, InputBufferLength))
1415 return ERROR_INVALID_DATA;
1416 Stream_Seek(s, InputBufferLength);
1418 WLog_Print(context->priv->log, WLOG_WARN,
1419 "[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
1420 WLog_Print(context->priv->log, WLOG_WARN,
1421 "TODO: parse %p [%" PRIu32
"], OutputBufferLength=%" PRIu32,
1422 (
const void*)InputBuffer, InputBufferLength, OutputBufferLength);
1424 return CHANNEL_RC_OK;
1427static UINT rdpdr_server_receive_io_query_volume_information_request(
1428 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1429 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1431 UINT32 FsInformationClass = 0;
1434 WINPR_ASSERT(context);
1435 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1436 return ERROR_INVALID_DATA;
1438 Stream_Read_UINT32(s, FsInformationClass);
1439 Stream_Read_UINT32(s, Length);
1442 WLog_Print(context->priv->log, WLOG_DEBUG,
1443 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1444 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1446 const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
1447 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1448 return ERROR_INVALID_DATA;
1449 Stream_Seek(s, Length);
1451 WLog_Print(context->priv->log, WLOG_WARN,
1452 "[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
1453 "(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
1454 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryVolumeBuffer);
1456 return CHANNEL_RC_OK;
1459static UINT rdpdr_server_receive_io_set_volume_information_request(
1460 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1461 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1463 UINT32 FsInformationClass = 0;
1466 WINPR_ASSERT(context);
1467 WINPR_ASSERT(context->priv);
1469 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1470 return ERROR_INVALID_DATA;
1472 Stream_Read_UINT32(s, FsInformationClass);
1473 Stream_Read_UINT32(s, Length);
1476 WLog_Print(context->priv->log, WLOG_DEBUG,
1477 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1478 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1480 const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
1481 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1482 return ERROR_INVALID_DATA;
1483 Stream_Seek(s, Length);
1485 WLog_Print(context->priv->log, WLOG_WARN,
1486 "[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
1487 "(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
1488 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetVolumeBuffer);
1490 return CHANNEL_RC_OK;
1493static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext* context,
1495 WINPR_ATTR_UNUSED UINT32 DeviceId,
1496 WINPR_ATTR_UNUSED UINT32 FileId,
1497 WINPR_ATTR_UNUSED UINT32 CompletionId)
1499 UINT32 FsInformationClass = 0;
1502 WINPR_ASSERT(context);
1503 WINPR_ASSERT(context->priv);
1505 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1506 return ERROR_INVALID_DATA;
1508 Stream_Read_UINT32(s, FsInformationClass);
1509 Stream_Read_UINT32(s, Length);
1512 WLog_Print(context->priv->log, WLOG_DEBUG,
1513 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1514 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1516 const BYTE* QueryBuffer = Stream_ConstPointer(s);
1517 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1518 return ERROR_INVALID_DATA;
1519 Stream_Seek(s, Length);
1521 WLog_Print(context->priv->log, WLOG_WARN,
1522 "[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
1523 "(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
1524 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)QueryBuffer);
1526 return CHANNEL_RC_OK;
1529static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext* context,
wStream* s,
1530 WINPR_ATTR_UNUSED UINT32 DeviceId,
1531 WINPR_ATTR_UNUSED UINT32 FileId,
1532 WINPR_ATTR_UNUSED UINT32 CompletionId)
1534 UINT32 FsInformationClass = 0;
1537 WINPR_ASSERT(context);
1538 WINPR_ASSERT(context->priv);
1540 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1541 return ERROR_INVALID_DATA;
1543 Stream_Read_UINT32(s, FsInformationClass);
1544 Stream_Read_UINT32(s, Length);
1547 WLog_Print(context->priv->log, WLOG_DEBUG,
1548 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1549 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1551 const BYTE* SetBuffer = Stream_ConstPointer(s);
1552 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1553 return ERROR_INVALID_DATA;
1554 Stream_Seek(s, Length);
1556 WLog_Print(context->priv->log, WLOG_WARN,
1557 "[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
1558 "(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
1559 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)SetBuffer);
1561 return CHANNEL_RC_OK;
1564static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext* context,
wStream* s,
1565 WINPR_ATTR_UNUSED UINT32 DeviceId,
1566 WINPR_ATTR_UNUSED UINT32 FileId,
1567 WINPR_ATTR_UNUSED UINT32 CompletionId)
1569 BYTE InitialQuery = 0;
1570 UINT32 FsInformationClass = 0;
1571 UINT32 PathLength = 0;
1573 WINPR_ASSERT(context);
1574 WINPR_ASSERT(context->priv);
1576 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1577 return ERROR_INVALID_DATA;
1579 Stream_Read_UINT32(s, FsInformationClass);
1580 Stream_Read_UINT8(s, InitialQuery);
1581 Stream_Read_UINT32(s, PathLength);
1584 const WCHAR* wPath = rdpdr_read_ustring(context->priv->log, s, PathLength);
1585 if (!wPath && (PathLength > 0))
1586 return ERROR_INVALID_DATA;
1588 char* Path = ConvertWCharNToUtf8Alloc(wPath, PathLength /
sizeof(WCHAR), NULL);
1589 WLog_Print(context->priv->log, WLOG_DEBUG,
1590 "Got FSInformationClass %s [0x%08" PRIx32
"], InitialQuery [%" PRIu8
1591 "] Path[%" PRIu32
"] %s",
1592 FSInformationClass2Tag(FsInformationClass), FsInformationClass, InitialQuery,
1596 WLog_Print(context->priv->log, WLOG_WARN,
1597 "[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
1598 "(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
1599 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1601 return CHANNEL_RC_OK;
1604static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext* context,
1606 WINPR_ATTR_UNUSED UINT32 DeviceId,
1607 WINPR_ATTR_UNUSED UINT32 FileId,
1608 WINPR_ATTR_UNUSED UINT32 CompletionId)
1611 UINT32 CompletionFilter = 0;
1613 WINPR_ASSERT(context);
1614 WINPR_ASSERT(context->priv);
1616 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1617 return ERROR_INVALID_DATA;
1619 Stream_Read_UINT8(s, WatchTree);
1620 Stream_Read_UINT32(s, CompletionFilter);
1623 WLog_Print(context->priv->log, WLOG_WARN,
1624 "[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
1625 "(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
1626 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1628 return CHANNEL_RC_OK;
1631static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext* context,
1633 UINT32 FileId, UINT32 CompletionId,
1634 UINT32 MinorFunction)
1636 WINPR_ASSERT(context);
1637 WINPR_ASSERT(context->priv);
1639 switch (MinorFunction)
1641 case IRP_MN_QUERY_DIRECTORY:
1642 return rdpdr_server_receive_io_query_directory_request(context, s, DeviceId, FileId,
1644 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
1645 return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
1648 WLog_Print(context->priv->log, WLOG_WARN,
1649 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
1650 "MajorFunction=%s, MinorFunction=%08" PRIx32
" is not supported",
1651 rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
1652 return ERROR_INVALID_DATA;
1656static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* context,
wStream* s,
1657 WINPR_ATTR_UNUSED UINT32 DeviceId,
1658 WINPR_ATTR_UNUSED UINT32 FileId,
1659 WINPR_ATTR_UNUSED UINT32 CompletionId)
1661 WINPR_ASSERT(context);
1662 WINPR_ASSERT(context->priv);
1664 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1665 return ERROR_INVALID_DATA;
1667 const uint32_t Operation = Stream_Get_UINT32(s);
1668 uint32_t Lock = Stream_Get_UINT32(s);
1669 const uint32_t NumLocks = Stream_Get_UINT32(s);
1672 WLog_Print(context->priv->log, WLOG_DEBUG,
1673 "IRP_MJ_LOCK_CONTROL, Operation=%s, Lock=0x%08" PRIx32
", NumLocks=%" PRIu32,
1674 DR_DRIVE_LOCK_REQ2str(Operation), Lock, NumLocks);
1678 for (UINT32 x = 0; x < NumLocks; x++)
1683 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 16))
1684 return ERROR_INVALID_DATA;
1686 Stream_Read_UINT64(s, Length);
1687 Stream_Read_UINT64(s, Offset);
1689 WLog_Print(context->priv->log, WLOG_DEBUG,
1690 "Locking at Offset=0x%08" PRIx64
" [Length %" PRIu64
"]", Offset, Length);
1693 WLog_Print(context->priv->log, WLOG_WARN,
1694 "[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
1695 "[Lock=0x%08" PRIx32
"]"
1698 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1700 return CHANNEL_RC_OK;
1703static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
wStream* s,
1706 UINT32 DeviceId = 0;
1708 UINT32 CompletionId = 0;
1709 UINT32 MajorFunction = 0;
1710 UINT32 MinorFunction = 0;
1712 WINPR_ASSERT(context);
1713 WINPR_ASSERT(context->priv);
1714 WINPR_ASSERT(header);
1716 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
1717 return ERROR_INVALID_DATA;
1719 Stream_Read_UINT32(s, DeviceId);
1720 Stream_Read_UINT32(s, FileId);
1721 Stream_Read_UINT32(s, CompletionId);
1722 Stream_Read_UINT32(s, MajorFunction);
1723 Stream_Read_UINT32(s, MinorFunction);
1724 if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
1725 WLog_Print(context->priv->log, WLOG_WARN,
1726 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
1727 "MinorFunction=0x%08" PRIx32
" != 0",
1728 rdpdr_irp_string(MajorFunction), MinorFunction);
1730 switch (MajorFunction)
1733 return rdpdr_server_receive_io_create_request(context, s, DeviceId, FileId,
1736 return rdpdr_server_receive_io_close_request(context, s, DeviceId, FileId,
1739 return rdpdr_server_receive_io_read_request(context, s, DeviceId, FileId, CompletionId);
1741 return rdpdr_server_receive_io_write_request(context, s, DeviceId, FileId,
1743 case IRP_MJ_DEVICE_CONTROL:
1744 return rdpdr_server_receive_io_device_control_request(context, s, DeviceId, FileId,
1746 case IRP_MJ_QUERY_VOLUME_INFORMATION:
1747 return rdpdr_server_receive_io_query_volume_information_request(context, s, DeviceId,
1748 FileId, CompletionId);
1749 case IRP_MJ_QUERY_INFORMATION:
1750 return rdpdr_server_receive_io_query_information_request(context, s, DeviceId, FileId,
1752 case IRP_MJ_SET_INFORMATION:
1753 return rdpdr_server_receive_io_set_information_request(context, s, DeviceId, FileId,
1755 case IRP_MJ_DIRECTORY_CONTROL:
1756 return rdpdr_server_receive_io_directory_control_request(context, s, DeviceId, FileId,
1757 CompletionId, MinorFunction);
1758 case IRP_MJ_LOCK_CONTROL:
1759 return rdpdr_server_receive_io_lock_control_request(context, s, DeviceId, FileId,
1761 case IRP_MJ_SET_VOLUME_INFORMATION:
1762 return rdpdr_server_receive_io_set_volume_information_request(context, s, DeviceId,
1763 FileId, CompletionId);
1767 context->priv->log, WLOG_WARN,
1768 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
1769 WLog_Print(context->priv->log, WLOG_WARN,
1770 "got DeviceId=0x%08" PRIx32
", FileId=0x%08" PRIx32
1771 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
1772 ", MinorFunction=0x%08" PRIx32,
1773 DeviceId, FileId, CompletionId, MajorFunction, MinorFunction);
1774 return ERROR_INVALID_DATA;
1783static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context,
wStream* s,
1786 UINT32 deviceId = 0;
1787 UINT32 completionId = 0;
1788 UINT32 ioStatus = 0;
1790 UINT error = CHANNEL_RC_OK;
1791 WINPR_ASSERT(context);
1792 WINPR_ASSERT(context->priv);
1794 WINPR_ASSERT(header);
1796 WINPR_UNUSED(header);
1798 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
1799 return ERROR_INVALID_DATA;
1801 Stream_Read_UINT32(s, deviceId);
1802 Stream_Read_UINT32(s, completionId);
1803 Stream_Read_UINT32(s, ioStatus);
1804 WLog_Print(context->priv->log, WLOG_DEBUG,
1805 "deviceId=%" PRIu32
", completionId=0x%" PRIx32
", ioStatus=0x%" PRIx32
"", deviceId,
1806 completionId, ioStatus);
1807 irp = rdpdr_server_dequeue_irp(context, completionId);
1811 WLog_Print(context->priv->log, WLOG_ERROR,
"IRP not found for completionId=0x%" PRIx32
"",
1813 return CHANNEL_RC_OK;
1819 error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
1830static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
1835 WINPR_ASSERT(context);
1836 WINPR_ASSERT(context->priv);
1838 header.Component = RDPDR_CTYP_CORE;
1839 header.PacketId = PAKID_CORE_USER_LOGGEDON;
1840 s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
1844 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1845 return CHANNEL_RC_NO_MEMORY;
1848 Stream_Write_UINT16(s, header.Component);
1849 Stream_Write_UINT16(s, header.PacketId);
1850 return rdpdr_seal_send_free_request(context, s);
1853static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context,
wStream* s)
1855 char PortDosName[9] = { 0 };
1856 UINT32 PnPNameLen = 0;
1857 UINT32 DriverNameLen = 0;
1858 UINT32 PrinterNameLen = 0;
1859 UINT32 CachedFieldsLen = 0;
1860 const WCHAR* PnPName = NULL;
1861 const WCHAR* DriverName = NULL;
1862 const WCHAR* PrinterName = NULL;
1864 WINPR_ASSERT(context);
1865 WINPR_ASSERT(context->priv);
1867 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 24))
1868 return ERROR_INVALID_DATA;
1870 Stream_Read(s, PortDosName, 8);
1871 Stream_Read_UINT32(s, PnPNameLen);
1872 Stream_Read_UINT32(s, DriverNameLen);
1873 Stream_Read_UINT32(s, PrinterNameLen);
1874 Stream_Read_UINT32(s, CachedFieldsLen);
1876 PnPName = rdpdr_read_ustring(context->priv->log, s, PnPNameLen);
1877 if (!PnPName && (PnPNameLen > 0))
1878 return ERROR_INVALID_DATA;
1879 DriverName = rdpdr_read_ustring(context->priv->log, s, DriverNameLen);
1880 if (!DriverName && (DriverNameLen > 0))
1881 return ERROR_INVALID_DATA;
1882 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1883 if (!PrinterName && (PrinterNameLen > 0))
1884 return ERROR_INVALID_DATA;
1886 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1887 return ERROR_INVALID_DATA;
1888 Stream_Seek(s, CachedFieldsLen);
1890 WLog_Print(context->priv->log, WLOG_WARN,
1891 "[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
1892 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1893 return CHANNEL_RC_OK;
1896static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context,
wStream* s)
1898 UINT32 PrinterNameLen = 0;
1899 UINT32 CachedFieldsLen = 0;
1900 const WCHAR* PrinterName = NULL;
1902 WINPR_ASSERT(context);
1904 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1905 return ERROR_INVALID_DATA;
1907 Stream_Read_UINT32(s, PrinterNameLen);
1908 Stream_Read_UINT32(s, CachedFieldsLen);
1910 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1911 if (!PrinterName && (PrinterNameLen > 0))
1912 return ERROR_INVALID_DATA;
1914 const BYTE* config = Stream_ConstPointer(s);
1915 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1916 return ERROR_INVALID_DATA;
1917 Stream_Seek(s, CachedFieldsLen);
1920 context->priv->log, WLOG_WARN,
1921 "[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
1922 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", (
const void*)config);
1923 return CHANNEL_RC_OK;
1926static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context,
wStream* s)
1928 UINT32 PrinterNameLen = 0;
1929 const WCHAR* PrinterName = NULL;
1931 WINPR_ASSERT(context);
1932 WINPR_ASSERT(context->priv);
1934 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1935 return ERROR_INVALID_DATA;
1937 Stream_Read_UINT32(s, PrinterNameLen);
1939 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1940 if (!PrinterName && (PrinterNameLen > 0))
1941 return ERROR_INVALID_DATA;
1944 context->priv->log, WLOG_WARN,
1945 "[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
1946 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1947 return CHANNEL_RC_OK;
1950static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context,
wStream* s)
1952 UINT32 OldPrinterNameLen = 0;
1953 UINT32 NewPrinterNameLen = 0;
1954 const WCHAR* OldPrinterName = NULL;
1955 const WCHAR* NewPrinterName = NULL;
1957 WINPR_ASSERT(context);
1958 WINPR_ASSERT(context->priv);
1960 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1961 return ERROR_INVALID_DATA;
1963 Stream_Read_UINT32(s, OldPrinterNameLen);
1964 Stream_Read_UINT32(s, NewPrinterNameLen);
1966 OldPrinterName = rdpdr_read_ustring(context->priv->log, s, OldPrinterNameLen);
1967 if (!OldPrinterName && (OldPrinterNameLen > 0))
1968 return ERROR_INVALID_DATA;
1969 NewPrinterName = rdpdr_read_ustring(context->priv->log, s, NewPrinterNameLen);
1970 if (!NewPrinterName && (NewPrinterNameLen > 0))
1971 return ERROR_INVALID_DATA;
1974 context->priv->log, WLOG_WARN,
1975 "[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
1976 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1977 return CHANNEL_RC_OK;
1981rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context,
wStream* s,
1986 WINPR_ASSERT(context);
1987 WINPR_ASSERT(context->priv);
1988 WINPR_ASSERT(header);
1990 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1991 return ERROR_INVALID_DATA;
1993 Stream_Read_UINT32(s, EventId);
1996 case RDPDR_ADD_PRINTER_EVENT:
1997 return rdpdr_server_receive_prn_cache_add_printer(context, s);
1998 case RDPDR_UPDATE_PRINTER_EVENT:
1999 return rdpdr_server_receive_prn_cache_update_printer(context, s);
2000 case RDPDR_DELETE_PRINTER_EVENT:
2001 return rdpdr_server_receive_prn_cache_delete_printer(context, s);
2002 case RDPDR_RENAME_PRINTER_EVENT:
2003 return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
2005 WLog_Print(context->priv->log, WLOG_WARN,
2006 "[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
2007 return ERROR_INVALID_DATA;
2011static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context,
wStream* s,
2014 UINT32 PrinterId = 0;
2017 WINPR_ASSERT(context);
2018 WINPR_ASSERT(context->priv);
2019 WINPR_ASSERT(header);
2021 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
2022 return ERROR_INVALID_DATA;
2024 Stream_Read_UINT32(s, PrinterId);
2025 Stream_Read_UINT32(s, Flags);
2028 context->priv->log, WLOG_WARN,
2029 "[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
2030 WLog_Print(context->priv->log, WLOG_WARN,
"PrinterId=0x%08" PRIx32
", Flags=0x%08" PRIx32,
2032 return CHANNEL_RC_OK;
2040static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context,
wStream* s,
2043 UINT error = ERROR_INVALID_DATA;
2044 WINPR_ASSERT(context);
2045 WINPR_ASSERT(context->priv);
2047 WINPR_ASSERT(header);
2049 WLog_Print(context->priv->log, WLOG_DEBUG,
2050 "receiving message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
2051 rdpdr_component_string(header->Component), header->Component,
2052 rdpdr_packetid_string(header->PacketId), header->PacketId);
2054 if (header->Component == RDPDR_CTYP_CORE)
2056 switch (header->PacketId)
2058 case PAKID_CORE_SERVER_ANNOUNCE:
2059 WLog_Print(context->priv->log, WLOG_ERROR,
2060 "[MS-RDPEFS] 2.2.2.2 Server Announce Request "
2061 "(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
2064 case PAKID_CORE_CLIENTID_CONFIRM:
2065 error = rdpdr_server_receive_announce_response(context, s, header);
2068 case PAKID_CORE_CLIENT_NAME:
2069 error = rdpdr_server_receive_client_name_request(context, s, header);
2070 if (error == CHANNEL_RC_OK)
2071 error = rdpdr_server_send_core_capability_request(context);
2072 if (error == CHANNEL_RC_OK)
2073 error = rdpdr_server_send_client_id_confirm(context);
2076 case PAKID_CORE_USER_LOGGEDON:
2077 WLog_Print(context->priv->log, WLOG_ERROR,
2078 "[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
2079 "must not be sent by a client!");
2082 case PAKID_CORE_SERVER_CAPABILITY:
2083 WLog_Print(context->priv->log, WLOG_ERROR,
2084 "[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
2085 "(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
2088 case PAKID_CORE_CLIENT_CAPABILITY:
2089 error = rdpdr_server_receive_core_capability_response(context, s, header);
2090 if (error == CHANNEL_RC_OK)
2092 if (context->priv->UserLoggedOnPdu)
2093 error = rdpdr_server_send_user_logged_on(context);
2098 case PAKID_CORE_DEVICELIST_ANNOUNCE:
2099 error = rdpdr_server_receive_device_list_announce_request(context, s, header);
2102 case PAKID_CORE_DEVICELIST_REMOVE:
2103 error = rdpdr_server_receive_device_list_remove_request(context, s, header);
2106 case PAKID_CORE_DEVICE_REPLY:
2107 WLog_Print(context->priv->log, WLOG_ERROR,
2108 "[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
2109 "(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
2112 case PAKID_CORE_DEVICE_IOREQUEST:
2113 error = rdpdr_server_receive_device_io_request(context, s, header);
2116 case PAKID_CORE_DEVICE_IOCOMPLETION:
2117 error = rdpdr_server_receive_device_io_completion(context, s, header);
2121 WLog_Print(context->priv->log, WLOG_WARN,
2122 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2123 rdpdr_component_string(header->Component), header->Component,
2124 rdpdr_packetid_string(header->PacketId));
2128 else if (header->Component == RDPDR_CTYP_PRN)
2130 switch (header->PacketId)
2132 case PAKID_PRN_CACHE_DATA:
2133 error = rdpdr_server_receive_prn_cache_data_request(context, s, header);
2136 case PAKID_PRN_USING_XPS:
2137 error = rdpdr_server_receive_prn_using_xps_request(context, s, header);
2141 WLog_Print(context->priv->log, WLOG_WARN,
2142 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2143 rdpdr_component_string(header->Component), header->Component,
2144 rdpdr_packetid_string(header->PacketId));
2150 WLog_Print(context->priv->log, WLOG_WARN,
2151 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2152 rdpdr_component_string(header->Component), header->Component,
2153 rdpdr_packetid_string(header->PacketId));
2156 return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
2159static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
2163 void* buffer = NULL;
2164 HANDLE events[8] = { 0 };
2165 HANDLE ChannelEvent = NULL;
2166 DWORD BytesReturned = 0;
2168 RdpdrServerContext* context = (RdpdrServerContext*)arg;
2169 wStream* s = Stream_New(NULL, 4096);
2171 WINPR_ASSERT(context);
2172 WINPR_ASSERT(context->priv);
2176 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2177 error = CHANNEL_RC_NO_MEMORY;
2181 if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
2182 &BytesReturned) == TRUE)
2184 if (BytesReturned ==
sizeof(HANDLE))
2185 ChannelEvent = *(HANDLE*)buffer;
2187 WTSFreeMemory(buffer);
2191 events[nCount++] = ChannelEvent;
2192 events[nCount++] = context->priv->StopEvent;
2194 if ((error = rdpdr_server_send_announce_request(context)))
2196 WLog_Print(context->priv->log, WLOG_ERROR,
2197 "rdpdr_server_send_announce_request failed with error %" PRIu32
"!", error);
2203 size_t capacity = 0;
2205 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2207 if (status == WAIT_FAILED)
2209 error = GetLastError();
2210 WLog_Print(context->priv->log, WLOG_ERROR,
2211 "WaitForMultipleObjects failed with error %" PRIu32
"!", error);
2215 status = WaitForSingleObject(context->priv->StopEvent, 0);
2217 if (status == WAIT_FAILED)
2219 error = GetLastError();
2220 WLog_Print(context->priv->log, WLOG_ERROR,
2221 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2225 if (status == WAIT_OBJECT_0)
2228 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned))
2230 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2231 error = ERROR_INTERNAL_ERROR;
2234 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
2236 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_EnsureRemainingCapacity failed!");
2237 error = ERROR_INTERNAL_ERROR;
2241 capacity = MIN(Stream_Capacity(s), UINT32_MAX);
2242 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s,
char),
2243 (ULONG)capacity, &BytesReturned))
2245 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2246 error = ERROR_INTERNAL_ERROR;
2250 if (BytesReturned >= RDPDR_HEADER_LENGTH)
2252 Stream_SetPosition(s, 0);
2253 Stream_SetLength(s, BytesReturned);
2255 while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH)
2259 Stream_Read_UINT16(s, header.Component);
2260 Stream_Read_UINT16(s, header.PacketId);
2262 if ((error = rdpdr_server_receive_pdu(context, s, &header)))
2264 WLog_Print(context->priv->log, WLOG_ERROR,
2265 "rdpdr_server_receive_pdu failed with error %" PRIu32
"!", error);
2273 Stream_Free(s, TRUE);
2276 if (error && context->rdpcontext)
2277 setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
2288static UINT rdpdr_server_start(RdpdrServerContext* context)
2290 WINPR_ASSERT(context);
2291 WINPR_ASSERT(context->priv);
2292 context->priv->ChannelHandle =
2293 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPDR_SVC_CHANNEL_NAME);
2295 if (!context->priv->ChannelHandle)
2297 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelOpen failed!");
2298 return CHANNEL_RC_BAD_CHANNEL;
2301 if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
2303 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateEvent failed!");
2304 return ERROR_INTERNAL_ERROR;
2307 if (!(context->priv->Thread =
2308 CreateThread(NULL, 0, rdpdr_server_thread, (
void*)context, 0, NULL)))
2310 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateThread failed!");
2311 (void)CloseHandle(context->priv->StopEvent);
2312 context->priv->StopEvent = NULL;
2313 return ERROR_INTERNAL_ERROR;
2316 return CHANNEL_RC_OK;
2324static UINT rdpdr_server_stop(RdpdrServerContext* context)
2327 WINPR_ASSERT(context);
2328 WINPR_ASSERT(context->priv);
2330 if (context->priv->StopEvent)
2332 (void)SetEvent(context->priv->StopEvent);
2334 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
2336 error = GetLastError();
2337 WLog_Print(context->priv->log, WLOG_ERROR,
2338 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2342 (void)CloseHandle(context->priv->Thread);
2343 context->priv->Thread = NULL;
2344 (void)CloseHandle(context->priv->StopEvent);
2345 context->priv->StopEvent = NULL;
2348 if (context->priv->ChannelHandle)
2350 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
2351 context->priv->ChannelHandle = NULL;
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,
2377 UINT32 fileNameLength = 0;
2381 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
2382 return ERROR_INVALID_DATA;
2384 Stream_Read_UINT32(s, fdi->NextEntryOffset);
2385 Stream_Read_UINT32(s, fdi->FileIndex);
2386 Stream_Read_INT64(s, fdi->CreationTime.QuadPart);
2387 Stream_Read_INT64(s, fdi->LastAccessTime.QuadPart);
2388 Stream_Read_INT64(s, fdi->LastWriteTime.QuadPart);
2389 Stream_Read_INT64(s, fdi->ChangeTime.QuadPart);
2390 Stream_Read_INT64(s, fdi->EndOfFile.QuadPart);
2391 Stream_Read_INT64(s, fdi->AllocationSize.QuadPart);
2392 Stream_Read_UINT32(s, fdi->FileAttributes);
2393 Stream_Read_UINT32(s, fileNameLength);
2395 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
2396 return ERROR_INVALID_DATA;
2398 if (fileNameLength /
sizeof(WCHAR) > ARRAYSIZE(fdi->FileName))
2399 return ERROR_INVALID_DATA;
2401#if defined(__MINGW32__) || defined(WITH_WCHAR_FILE_DIRECTORY_INFORMATION)
2402 if (Stream_Read_UTF16_String(s, fdi->FileName, fileNameLength /
sizeof(WCHAR)))
2403 return ERROR_INVALID_DATA;
2405 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, fileNameLength /
sizeof(WCHAR), fdi->FileName,
2406 ARRAYSIZE(fdi->FileName)) < 0)
2407 return ERROR_INVALID_DATA;
2409 return CHANNEL_RC_OK;
2417static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, UINT32 deviceId,
2418 UINT32 completionId,
const char* path,
2419 UINT32 desiredAccess, UINT32 createOptions,
2420 UINT32 createDisposition)
2422 size_t pathLength = 0;
2424 WINPR_ASSERT(context);
2425 WINPR_ASSERT(context->priv);
2427 WLog_Print(context->priv->log, WLOG_DEBUG,
2428 "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
2429 ", path=%s, desiredAccess=0x%" PRIx32
" createOptions=0x%" PRIx32
2430 " createDisposition=0x%" PRIx32
"",
2431 deviceId, path, desiredAccess, createOptions, createDisposition);
2433 pathLength = (strlen(path) + 1U) *
sizeof(WCHAR);
2434 s = Stream_New(NULL, 256U + pathLength);
2438 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2439 return CHANNEL_RC_NO_MEMORY;
2442 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
2443 Stream_Write_UINT32(s, desiredAccess);
2444 Stream_Write_UINT32(s, 0);
2445 Stream_Write_UINT32(s, 0);
2446 Stream_Write_UINT32(s, 0);
2447 Stream_Write_UINT32(s, 3);
2448 Stream_Write_UINT32(s, createDisposition);
2449 Stream_Write_UINT32(s, createOptions);
2450 WINPR_ASSERT(pathLength <= UINT32_MAX);
2451 Stream_Write_UINT32(s, (UINT32)pathLength);
2453 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2454 pathLength /
sizeof(WCHAR), TRUE) < 0)
2456 Stream_Free(s, TRUE);
2457 return ERROR_INTERNAL_ERROR;
2459 return rdpdr_seal_send_free_request(context, s);
2467static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId,
2468 UINT32 fileId, UINT32 completionId)
2471 WINPR_ASSERT(context);
2472 WINPR_ASSERT(context->priv);
2474 WLog_Print(context->priv->log, WLOG_DEBUG,
2475 "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
"",
2477 s = Stream_New(NULL, 128);
2481 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2482 return CHANNEL_RC_NO_MEMORY;
2485 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0);
2487 return rdpdr_seal_send_free_request(context, s);
2495static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, UINT32 deviceId,
2496 UINT32 fileId, UINT32 completionId, UINT32 length,
2500 WINPR_ASSERT(context);
2501 WINPR_ASSERT(context->priv);
2503 WLog_Print(context->priv->log, WLOG_DEBUG,
2504 "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2505 ", length=%" PRIu32
", offset=%" PRIu32
"",
2506 deviceId, fileId, length, offset);
2507 s = Stream_New(NULL, 128);
2511 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2512 return CHANNEL_RC_NO_MEMORY;
2515 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0);
2516 Stream_Write_UINT32(s, length);
2517 Stream_Write_UINT32(s, offset);
2518 Stream_Write_UINT32(s, 0);
2520 return rdpdr_seal_send_free_request(context, s);
2528static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, UINT32 deviceId,
2529 UINT32 fileId, UINT32 completionId,
2530 const char* data, UINT32 length, UINT32 offset)
2533 WINPR_ASSERT(context);
2534 WINPR_ASSERT(context->priv);
2536 WLog_Print(context->priv->log, WLOG_DEBUG,
2537 "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2538 ", length=%" PRIu32
", offset=%" PRIu32
"",
2539 deviceId, fileId, length, offset);
2540 s = Stream_New(NULL, 64 + length);
2544 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2545 return CHANNEL_RC_NO_MEMORY;
2548 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0);
2549 Stream_Write_UINT32(s, length);
2550 Stream_Write_UINT32(s, offset);
2551 Stream_Write_UINT32(s, 0);
2553 Stream_Write(s, data, length);
2554 return rdpdr_seal_send_free_request(context, s);
2562static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context,
2563 UINT32 deviceId, UINT32 fileId,
2564 UINT32 completionId,
const char* path)
2566 size_t pathLength = 0;
2568 WINPR_ASSERT(context);
2569 WINPR_ASSERT(context->priv);
2571 WLog_Print(context->priv->log, WLOG_DEBUG,
2572 "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2574 deviceId, fileId, path);
2576 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2577 s = Stream_New(NULL, 64 + pathLength);
2581 WLog_Print(context->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_DIRECTORY_CONTROL,
2586 IRP_MN_QUERY_DIRECTORY);
2587 Stream_Write_UINT32(s, FileDirectoryInformation);
2588 Stream_Write_UINT8(s, path ? 1 : 0);
2589 WINPR_ASSERT(pathLength <= UINT32_MAX);
2590 Stream_Write_UINT32(s, (UINT32)pathLength);
2596 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2597 pathLength /
sizeof(WCHAR), TRUE) < 0)
2599 Stream_Free(s, TRUE);
2600 return ERROR_INTERNAL_ERROR;
2604 return rdpdr_seal_send_free_request(context, s);
2612static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context,
2613 UINT32 deviceId, UINT32 fileId,
2614 UINT32 completionId,
const char* path)
2616 size_t pathLength = 0;
2618 WINPR_ASSERT(context);
2619 WINPR_ASSERT(context->priv);
2621 WLog_Print(context->priv->log, WLOG_DEBUG,
2622 "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2624 deviceId, fileId, path);
2626 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2627 s = Stream_New(NULL, 64 + pathLength);
2631 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2632 return CHANNEL_RC_NO_MEMORY;
2635 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION,
2637 Stream_Write_UINT32(s, FileRenameInformation);
2638 WINPR_ASSERT(pathLength <= UINT32_MAX - 6U);
2639 Stream_Write_UINT32(s, (UINT32)pathLength + 6U);
2642 Stream_Write_UINT8(s, 0);
2643 Stream_Write_UINT8(s, 0);
2644 Stream_Write_UINT32(s, (UINT32)pathLength);
2649 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2650 pathLength /
sizeof(WCHAR), TRUE) < 0)
2652 Stream_Free(s, TRUE);
2653 return ERROR_INTERNAL_ERROR;
2657 return rdpdr_seal_send_free_request(context, s);
2660static void rdpdr_server_convert_slashes(
char* path,
int size)
2662 WINPR_ASSERT(path || (size <= 0));
2664 for (
int i = 0; (i < size) && (path[i] !=
'\0'); i++)
2680static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context,
wStream* s,
2682 UINT32 completionId, UINT32 ioStatus)
2684 WINPR_ASSERT(context);
2685 WINPR_ASSERT(context->priv);
2690 WLog_Print(context->priv->log, WLOG_DEBUG,
2691 "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
2692 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2693 deviceId, completionId, ioStatus);
2695 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2697 rdpdr_server_irp_free(irp);
2698 return CHANNEL_RC_OK;
2706static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context,
wStream* s,
2708 UINT32 completionId, UINT32 ioStatus)
2710 WINPR_ASSERT(context);
2711 WINPR_ASSERT(context->priv);
2714 WLog_Print(context->priv->log, WLOG_DEBUG,
2715 "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
2716 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2717 deviceId, completionId, ioStatus);
2719 if (ioStatus != STATUS_SUCCESS)
2722 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2724 rdpdr_server_irp_free(irp);
2725 return CHANNEL_RC_OK;
2728 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2729 return ERROR_INVALID_DATA;
2731 const uint32_t fileId = Stream_Get_UINT32(s);
2732 const uint8_t information = Stream_Get_UINT8(s);
2733 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2734 fileInformation2str(information));
2737 irp->CompletionId = context->priv->NextCompletionId++;
2738 irp->Callback = rdpdr_server_drive_create_directory_callback2;
2739 irp->DeviceId = deviceId;
2740 irp->FileId = fileId;
2742 if (!rdpdr_server_enqueue_irp(context, irp))
2744 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2745 rdpdr_server_irp_free(irp);
2746 return ERROR_INTERNAL_ERROR;
2750 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2758static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context,
void* callbackData,
2759 UINT32 deviceId,
const char* path)
2762 WINPR_ASSERT(context);
2763 WINPR_ASSERT(context->priv);
2764 WINPR_ASSERT(callbackData);
2766 irp = rdpdr_server_irp_new();
2770 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2771 return CHANNEL_RC_NO_MEMORY;
2774 irp->CompletionId = context->priv->NextCompletionId++;
2775 irp->Callback = rdpdr_server_drive_create_directory_callback1;
2776 irp->CallbackData = callbackData;
2777 irp->DeviceId = deviceId;
2778 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2779 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2781 if (!rdpdr_server_enqueue_irp(context, irp))
2783 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2784 rdpdr_server_irp_free(irp);
2785 return ERROR_INTERNAL_ERROR;
2789 return rdpdr_server_send_device_create_request(
2790 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
2791 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
2803static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context,
wStream* s,
2805 UINT32 completionId, UINT32 ioStatus)
2808 WINPR_ASSERT(context);
2809 WINPR_ASSERT(context->priv);
2812 WLog_Print(context->priv->log, WLOG_DEBUG,
2813 "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
2814 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2815 deviceId, completionId, ioStatus);
2817 context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
2819 rdpdr_server_irp_free(irp);
2820 return CHANNEL_RC_OK;
2828static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context,
wStream* s,
2830 UINT32 completionId, UINT32 ioStatus)
2832 WINPR_ASSERT(context);
2833 WINPR_ASSERT(context->priv);
2835 WLog_Print(context->priv->log, WLOG_DEBUG,
2836 "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
2837 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2838 deviceId, completionId, ioStatus);
2840 if (ioStatus != STATUS_SUCCESS)
2843 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
2845 rdpdr_server_irp_free(irp);
2846 return CHANNEL_RC_OK;
2849 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2850 return ERROR_INVALID_DATA;
2852 const uint32_t fileId = Stream_Get_UINT32(s);
2853 const uint8_t information = Stream_Get_UINT8(s);
2854 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2855 fileInformation2str(information));
2858 irp->CompletionId = context->priv->NextCompletionId++;
2859 irp->Callback = rdpdr_server_drive_delete_directory_callback2;
2860 irp->DeviceId = deviceId;
2861 irp->FileId = fileId;
2863 if (!rdpdr_server_enqueue_irp(context, irp))
2865 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2866 rdpdr_server_irp_free(irp);
2867 return ERROR_INTERNAL_ERROR;
2871 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2879static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context,
void* callbackData,
2880 UINT32 deviceId,
const char* path)
2882 RDPDR_IRP* irp = rdpdr_server_irp_new();
2883 WINPR_ASSERT(context);
2884 WINPR_ASSERT(context->priv);
2889 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2890 return CHANNEL_RC_NO_MEMORY;
2893 irp->CompletionId = context->priv->NextCompletionId++;
2894 irp->Callback = rdpdr_server_drive_delete_directory_callback1;
2895 irp->CallbackData = callbackData;
2896 irp->DeviceId = deviceId;
2897 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2898 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2900 if (!rdpdr_server_enqueue_irp(context, irp))
2902 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2903 rdpdr_server_irp_free(irp);
2904 return ERROR_INTERNAL_ERROR;
2908 return rdpdr_server_send_device_create_request(
2909 context, deviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
2910 FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
2922static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context,
wStream* s,
2924 UINT32 completionId, UINT32 ioStatus)
2930 WINPR_ASSERT(context);
2931 WINPR_ASSERT(context->priv);
2933 WLog_Print(context->priv->log, WLOG_DEBUG,
2934 "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
2935 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2936 deviceId, completionId, ioStatus);
2938 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
2939 return ERROR_INVALID_DATA;
2941 Stream_Read_UINT32(s, length);
2945 if ((error = rdpdr_server_read_file_directory_information(context->priv->log, s, &fdi)))
2947 WLog_Print(context->priv->log, WLOG_ERROR,
2948 "rdpdr_server_read_file_directory_information failed with error %" PRIu32
2956 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 1))
2957 return ERROR_INVALID_DATA;
2962 if (ioStatus == STATUS_SUCCESS)
2965 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
2966 length > 0 ? &fdi : NULL);
2968 irp->CompletionId = context->priv->NextCompletionId++;
2969 irp->Callback = rdpdr_server_drive_query_directory_callback2;
2971 if (!rdpdr_server_enqueue_irp(context, irp))
2973 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2974 rdpdr_server_irp_free(irp);
2975 return ERROR_INTERNAL_ERROR;
2979 return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId,
2980 irp->CompletionId, NULL);
2985 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
2987 rdpdr_server_irp_free(irp);
2990 return CHANNEL_RC_OK;
2998static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context,
wStream* s,
3000 UINT32 completionId, UINT32 ioStatus)
3002 WINPR_ASSERT(context);
3003 WINPR_ASSERT(context->priv);
3005 WLog_Print(context->priv->log, WLOG_DEBUG,
3006 "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
3007 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
3008 deviceId, completionId, ioStatus);
3010 if (ioStatus != STATUS_SUCCESS)
3013 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
3015 rdpdr_server_irp_free(irp);
3016 return CHANNEL_RC_OK;
3019 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
3020 return ERROR_INVALID_DATA;
3022 const uint32_t fileId = Stream_Get_UINT32(s);
3024 irp->CompletionId = context->priv->NextCompletionId++;
3025 irp->Callback = rdpdr_server_drive_query_directory_callback2;
3026 irp->DeviceId = deviceId;
3027 irp->FileId = fileId;
3028 winpr_str_append(
"\\*.*", irp->PathName, ARRAYSIZE(irp->PathName), NULL);
3030 if (!rdpdr_server_enqueue_irp(context, irp))
3032 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3033 rdpdr_server_irp_free(irp);
3034 return ERROR_INTERNAL_ERROR;
3038 return rdpdr_server_send_device_query_directory_request(context, deviceId, fileId,
3039 irp->CompletionId, irp->PathName);
3047static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context,
void* callbackData,
3048 UINT32 deviceId,
const char* path)
3050 RDPDR_IRP* irp = rdpdr_server_irp_new();
3051 WINPR_ASSERT(context);
3052 WINPR_ASSERT(context->priv);
3057 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3058 return CHANNEL_RC_NO_MEMORY;
3061 irp->CompletionId = context->priv->NextCompletionId++;
3062 irp->Callback = rdpdr_server_drive_query_directory_callback1;
3063 irp->CallbackData = callbackData;
3064 irp->DeviceId = deviceId;
3065 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3066 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3068 if (!rdpdr_server_enqueue_irp(context, irp))
3070 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3071 rdpdr_server_irp_free(irp);
3072 return ERROR_INTERNAL_ERROR;
3076 return rdpdr_server_send_device_create_request(
3077 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3078 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3090static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context,
wStream* s,
3092 UINT32 completionId, UINT32 ioStatus)
3094 WINPR_ASSERT(context);
3095 WINPR_ASSERT(context->priv);
3097 WLog_Print(context->priv->log, WLOG_DEBUG,
3098 "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3099 ", ioStatus=0x%" PRIx32
"",
3100 deviceId, completionId, ioStatus);
3102 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3103 return ERROR_INVALID_DATA;
3105 const uint32_t fileId = Stream_Get_UINT32(s);
3106 const uint8_t information = Stream_Get_UINT8(s);
3107 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3108 fileInformation2str(information));
3111 context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
3113 rdpdr_server_irp_free(irp);
3114 return CHANNEL_RC_OK;
3122static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context,
void* callbackData,
3123 UINT32 deviceId,
const char* path, UINT32 desiredAccess,
3124 UINT32 createDisposition)
3126 RDPDR_IRP* irp = rdpdr_server_irp_new();
3127 WINPR_ASSERT(context);
3128 WINPR_ASSERT(context->priv);
3133 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3134 return CHANNEL_RC_NO_MEMORY;
3137 irp->CompletionId = context->priv->NextCompletionId++;
3138 irp->Callback = rdpdr_server_drive_open_file_callback;
3139 irp->CallbackData = callbackData;
3140 irp->DeviceId = deviceId;
3141 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3142 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3144 if (!rdpdr_server_enqueue_irp(context, irp))
3146 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3147 rdpdr_server_irp_free(irp);
3148 return ERROR_INTERNAL_ERROR;
3152 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
3153 irp->PathName, desiredAccess | SYNCHRONIZE,
3154 FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
3166static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context,
wStream* s,
3168 UINT32 completionId, UINT32 ioStatus)
3171 char* buffer = NULL;
3172 WINPR_ASSERT(context);
3173 WINPR_ASSERT(context->priv);
3175 WLog_Print(context->priv->log, WLOG_DEBUG,
3176 "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3177 ", ioStatus=0x%" PRIx32
"",
3178 deviceId, completionId, ioStatus);
3180 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
3181 return ERROR_INVALID_DATA;
3183 Stream_Read_UINT32(s, length);
3185 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3186 return ERROR_INVALID_DATA;
3190 buffer = Stream_Pointer(s);
3191 Stream_Seek(s, length);
3195 context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
3197 rdpdr_server_irp_free(irp);
3198 return CHANNEL_RC_OK;
3206static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context,
void* callbackData,
3207 UINT32 deviceId, UINT32 fileId, UINT32 length,
3210 RDPDR_IRP* irp = rdpdr_server_irp_new();
3211 WINPR_ASSERT(context);
3212 WINPR_ASSERT(context->priv);
3217 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3218 return CHANNEL_RC_NO_MEMORY;
3221 irp->CompletionId = context->priv->NextCompletionId++;
3222 irp->Callback = rdpdr_server_drive_read_file_callback;
3223 irp->CallbackData = callbackData;
3224 irp->DeviceId = deviceId;
3225 irp->FileId = fileId;
3227 if (!rdpdr_server_enqueue_irp(context, irp))
3229 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3230 rdpdr_server_irp_free(irp);
3231 return ERROR_INTERNAL_ERROR;
3236 return rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId,
3249static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
wStream* s,
3251 UINT32 completionId, UINT32 ioStatus)
3254 WINPR_ASSERT(context);
3255 WINPR_ASSERT(context->priv);
3257 WLog_Print(context->priv->log, WLOG_DEBUG,
3258 "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3259 ", ioStatus=0x%" PRIx32
"",
3260 deviceId, completionId, ioStatus);
3262 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3263 return ERROR_INVALID_DATA;
3265 Stream_Read_UINT32(s, length);
3268 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3269 return ERROR_INVALID_DATA;
3272 context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
3274 rdpdr_server_irp_free(irp);
3275 return CHANNEL_RC_OK;
3283static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context,
void* callbackData,
3284 UINT32 deviceId, UINT32 fileId,
const char* buffer,
3285 UINT32 length, UINT32 offset)
3287 RDPDR_IRP* irp = rdpdr_server_irp_new();
3288 WINPR_ASSERT(context);
3289 WINPR_ASSERT(context->priv);
3294 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3295 return CHANNEL_RC_NO_MEMORY;
3298 irp->CompletionId = context->priv->NextCompletionId++;
3299 irp->Callback = rdpdr_server_drive_write_file_callback;
3300 irp->CallbackData = callbackData;
3301 irp->DeviceId = deviceId;
3302 irp->FileId = fileId;
3304 if (!rdpdr_server_enqueue_irp(context, irp))
3306 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3307 rdpdr_server_irp_free(irp);
3308 return ERROR_INTERNAL_ERROR;
3313 return rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId,
3314 buffer, length, offset);
3326static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
wStream* s,
3328 UINT32 completionId, UINT32 ioStatus)
3331 WINPR_ASSERT(context);
3332 WINPR_ASSERT(context->priv);
3335 WLog_Print(context->priv->log, WLOG_DEBUG,
3336 "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3337 ", ioStatus=0x%" PRIx32
"",
3338 deviceId, completionId, ioStatus);
3341 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3342 return ERROR_INVALID_DATA;
3347 context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
3349 rdpdr_server_irp_free(irp);
3350 return CHANNEL_RC_OK;
3358static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context,
void* callbackData,
3359 UINT32 deviceId, UINT32 fileId)
3361 RDPDR_IRP* irp = rdpdr_server_irp_new();
3362 WINPR_ASSERT(context);
3363 WINPR_ASSERT(context->priv);
3368 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3369 return CHANNEL_RC_NO_MEMORY;
3372 irp->CompletionId = context->priv->NextCompletionId++;
3373 irp->Callback = rdpdr_server_drive_close_file_callback;
3374 irp->CallbackData = callbackData;
3375 irp->DeviceId = deviceId;
3376 irp->FileId = fileId;
3378 if (!rdpdr_server_enqueue_irp(context, irp))
3380 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3381 rdpdr_server_irp_free(irp);
3382 return ERROR_INTERNAL_ERROR;
3387 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3399static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context,
wStream* s,
3401 UINT32 completionId, UINT32 ioStatus)
3404 WINPR_ASSERT(context);
3405 WINPR_ASSERT(context->priv);
3408 WLog_Print(context->priv->log, WLOG_DEBUG,
3409 "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3410 ", ioStatus=0x%" PRIx32
"",
3411 deviceId, completionId, ioStatus);
3413 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3415 rdpdr_server_irp_free(irp);
3416 return CHANNEL_RC_OK;
3424static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context,
wStream* s,
3426 UINT32 completionId, UINT32 ioStatus)
3428 WINPR_ASSERT(context);
3429 WINPR_ASSERT(context->priv);
3431 WLog_Print(context->priv->log, WLOG_DEBUG,
3432 "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3433 ", ioStatus=0x%" PRIx32
"",
3434 deviceId, completionId, ioStatus);
3436 if (ioStatus != STATUS_SUCCESS)
3439 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3441 rdpdr_server_irp_free(irp);
3442 return CHANNEL_RC_OK;
3445 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3446 return ERROR_INVALID_DATA;
3448 const uint32_t fileId = Stream_Get_UINT32(s);
3449 const uint8_t information = Stream_Get_UINT8(s);
3451 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3452 fileInformation2str(information));
3454 irp->CompletionId = context->priv->NextCompletionId++;
3455 irp->Callback = rdpdr_server_drive_delete_file_callback2;
3456 irp->DeviceId = deviceId;
3457 irp->FileId = fileId;
3459 if (!rdpdr_server_enqueue_irp(context, irp))
3461 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3462 rdpdr_server_irp_free(irp);
3463 return ERROR_INTERNAL_ERROR;
3467 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3475static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context,
void* callbackData,
3476 UINT32 deviceId,
const char* path)
3478 RDPDR_IRP* irp = rdpdr_server_irp_new();
3479 WINPR_ASSERT(context);
3480 WINPR_ASSERT(context->priv);
3485 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3486 return CHANNEL_RC_NO_MEMORY;
3489 irp->CompletionId = context->priv->NextCompletionId++;
3490 irp->Callback = rdpdr_server_drive_delete_file_callback1;
3491 irp->CallbackData = callbackData;
3492 irp->DeviceId = deviceId;
3493 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3494 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3496 if (!rdpdr_server_enqueue_irp(context, irp))
3498 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3499 rdpdr_server_irp_free(irp);
3500 return ERROR_INTERNAL_ERROR;
3504 return rdpdr_server_send_device_create_request(
3505 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3506 FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3518static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context,
wStream* s,
3520 UINT32 completionId, UINT32 ioStatus)
3522 WINPR_UNUSED(context);
3524 WINPR_ASSERT(context);
3525 WINPR_ASSERT(context->priv);
3528 WLog_Print(context->priv->log, WLOG_DEBUG,
3529 "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32
", completionId=%" PRIu32
3530 ", ioStatus=0x%" PRIx32
"",
3531 deviceId, completionId, ioStatus);
3533 rdpdr_server_irp_free(irp);
3534 return CHANNEL_RC_OK;
3542static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context,
wStream* s,
3544 UINT32 completionId, UINT32 ioStatus)
3547 WINPR_ASSERT(context);
3548 WINPR_ASSERT(context->priv);
3550 WLog_Print(context->priv->log, WLOG_DEBUG,
3551 "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3552 ", ioStatus=0x%" PRIx32
"",
3553 deviceId, completionId, ioStatus);
3555 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3556 return ERROR_INVALID_DATA;
3558 Stream_Read_UINT32(s, length);
3561 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3563 irp->CompletionId = context->priv->NextCompletionId++;
3564 irp->Callback = rdpdr_server_drive_rename_file_callback3;
3565 irp->DeviceId = deviceId;
3567 if (!rdpdr_server_enqueue_irp(context, irp))
3569 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3570 rdpdr_server_irp_free(irp);
3571 return ERROR_INTERNAL_ERROR;
3575 return rdpdr_server_send_device_close_request(context, deviceId, irp->FileId,
3584static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context,
wStream* s,
3586 UINT32 completionId, UINT32 ioStatus)
3588 WINPR_ASSERT(context);
3589 WINPR_ASSERT(context->priv);
3591 WLog_Print(context->priv->log, WLOG_DEBUG,
3592 "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3593 ", ioStatus=0x%" PRIx32
"",
3594 deviceId, completionId, ioStatus);
3596 if (ioStatus != STATUS_SUCCESS)
3599 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3601 rdpdr_server_irp_free(irp);
3602 return CHANNEL_RC_OK;
3605 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3606 return ERROR_INVALID_DATA;
3608 const uint32_t fileId = Stream_Get_UINT32(s);
3609 const uint8_t information = Stream_Get_UINT8(s);
3610 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3611 fileInformation2str(information));
3614 irp->CompletionId = context->priv->NextCompletionId++;
3615 irp->Callback = rdpdr_server_drive_rename_file_callback2;
3616 irp->DeviceId = deviceId;
3617 irp->FileId = fileId;
3619 if (!rdpdr_server_enqueue_irp(context, irp))
3621 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3622 rdpdr_server_irp_free(irp);
3623 return ERROR_INTERNAL_ERROR;
3627 return rdpdr_server_send_device_file_rename_request(context, deviceId, fileId,
3628 irp->CompletionId, irp->ExtraBuffer);
3636static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context,
void* callbackData,
3637 UINT32 deviceId,
const char* oldPath,
3638 const char* newPath)
3640 WINPR_ASSERT(context);
3641 WINPR_ASSERT(context->priv);
3642 RDPDR_IRP* irp = rdpdr_server_irp_new();
3646 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3647 return CHANNEL_RC_NO_MEMORY;
3650 irp->CompletionId = context->priv->NextCompletionId++;
3651 irp->Callback = rdpdr_server_drive_rename_file_callback1;
3652 irp->CallbackData = callbackData;
3653 irp->DeviceId = deviceId;
3654 strncpy(irp->PathName, oldPath,
sizeof(irp->PathName) - 1);
3655 strncpy(irp->ExtraBuffer, newPath,
sizeof(irp->ExtraBuffer) - 1);
3656 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3657 rdpdr_server_convert_slashes(irp->ExtraBuffer,
sizeof(irp->ExtraBuffer));
3659 if (!rdpdr_server_enqueue_irp(context, irp))
3661 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3662 rdpdr_server_irp_free(irp);
3663 return ERROR_INTERNAL_ERROR;
3668 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
3669 irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3670 FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3673static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
3677 ListDictionary_Free(ctx->IrpList);
3678 HashTable_Free(ctx->devicelist);
3679 free(ctx->ClientComputerName);
3683#define TAG CHANNELS_TAG("rdpdr.server")
3684static RdpdrServerPrivate* rdpdr_server_private_new(
void)
3686 RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1,
sizeof(RdpdrServerPrivate));
3691 priv->log = WLog_Get(TAG);
3692 priv->VersionMajor = RDPDR_VERSION_MAJOR;
3693 priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
3694 priv->ClientId = g_ClientId++;
3695 priv->UserLoggedOnPdu = TRUE;
3696 priv->NextCompletionId = 1;
3697 priv->IrpList = ListDictionary_New(TRUE);
3702 priv->devicelist = HashTable_New(FALSE);
3703 if (!priv->devicelist)
3706 HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash);
3709 wObject* obj = HashTable_ValueObject(priv->devicelist);
3716 wObject* obj = HashTable_KeyObject(priv->devicelist);
3724 rdpdr_server_private_free(priv);
3728RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
3730 RdpdrServerContext* context = (RdpdrServerContext*)calloc(1,
sizeof(RdpdrServerContext));
3736 context->Start = rdpdr_server_start;
3737 context->Stop = rdpdr_server_stop;
3738 context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
3739 context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
3740 context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
3741 context->DriveOpenFile = rdpdr_server_drive_open_file;
3742 context->DriveReadFile = rdpdr_server_drive_read_file;
3743 context->DriveWriteFile = rdpdr_server_drive_write_file;
3744 context->DriveCloseFile = rdpdr_server_drive_close_file;
3745 context->DriveDeleteFile = rdpdr_server_drive_delete_file;
3746 context->DriveRenameFile = rdpdr_server_drive_rename_file;
3747 context->priv = rdpdr_server_private_new();
3752 context->supported = UINT16_MAX;
3756 WINPR_PRAGMA_DIAG_PUSH
3757 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3758 rdpdr_server_context_free(context);
3759 WINPR_PRAGMA_DIAG_POP
3763void rdpdr_server_context_free(RdpdrServerContext* context)
3768 rdpdr_server_private_free(context->priv);
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_rdpdr_dtyp_string(UINT32 type)
Returns a string representation of RDPDR_DTYP_*.
This struct contains function pointer to initialize/free objects.
OBJECT_FREE_FN fnObjectFree
OBJECT_EQUALS_FN fnObjectEquals
OBJECT_NEW_FN fnObjectNew