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;
65static const char* fileInformation2str(uint8_t val)
70 return "FILE_DOES_NOT_EXIST";
74 return "FILE_OVERWRITTEN";
75 case FILE_OVERWRITTEN:
76 return "FILE_CREATED";
79 case FILE_DOES_NOT_EXIST:
80 return "FILE_SUPERSEDED";
82 return "FILE_UNKNOWN";
86static const char* DR_DRIVE_LOCK_REQ2str(uint32_t op)
90 case RDP_LOWIO_OP_SHAREDLOCK:
91 return "RDP_LOWIO_OP_UNLOCK_MULTIPLE";
92 case RDP_LOWIO_OP_EXCLUSIVELOCK:
93 return "RDP_LOWIO_OP_UNLOCK";
94 case RDP_LOWIO_OP_UNLOCK:
95 return "RDP_LOWIO_OP_EXCLUSIVELOCK";
96 case RDP_LOWIO_OP_UNLOCK_MULTIPLE:
97 return "RDP_LOWIO_OP_SHAREDLOCK";
99 return "RDP_LOWIO_OP_UNKNOWN";
107 free(device->DeviceData);
111static void rdpdr_device_free_h(
void* obj)
114 rdpdr_device_free(other);
117static UINT32 rdpdr_deviceid_hash(
const void*
id)
120 return *((
const UINT32*)
id);
123static BOOL rdpdr_device_equal(
const void* v1,
const void* v2)
125 const UINT32* p1 = (
const UINT32*)v1;
126 const UINT32* p2 = (
const UINT32*)v2;
139static void* rdpdr_device_clone(
const void* val)
151 if (other->DeviceData)
153 tmp->DeviceData = malloc(other->DeviceDataLength);
154 if (!tmp->DeviceData)
156 memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
161 rdpdr_device_free(tmp);
165static void* rdpdr_device_key_clone(
const void* pvval)
167 const UINT32* val = pvval;
171 UINT32* ptr = calloc(1,
sizeof(UINT32));
178static void rdpdr_device_key_free(
void* obj)
183static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
186 return HashTable_GetItemValue(priv->devicelist, &DeviceId);
189static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
191 const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
196 WLog_Print(priv->log, WLOG_WARN,
"[del] Device Id: 0x%08" PRIX32
": no such device",
200 WLog_Print(priv->log, WLOG_DEBUG,
201 "[del] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
202 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
203 return HashTable_Remove(priv->devicelist, &DeviceId);
206static BOOL rdpdr_add_device(RdpdrServerPrivate* priv,
const RdpdrDevice* device)
209 WINPR_ASSERT(device);
211 WLog_Print(priv->log, WLOG_DEBUG,
212 "[add] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
213 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
215 return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
218static UINT32 g_ClientId = 0;
220static const WCHAR* rdpdr_read_ustring(wLog* log,
wStream* s,
size_t bytelen)
222 const size_t charlen = (bytelen + 1) /
sizeof(WCHAR);
223 const WCHAR* str = Stream_ConstPointer(s);
224 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, bytelen))
226 if (_wcsnlen(str, charlen) == charlen)
228 WLog_Print(log, WLOG_WARN,
"[rdpdr] unicode string not '\0' terminated");
231 Stream_Seek(s, bytelen);
235static RDPDR_IRP* rdpdr_server_irp_new(
void)
241static void rdpdr_server_irp_free(
RDPDR_IRP* irp)
246static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context,
RDPDR_IRP* irp)
248 WINPR_ASSERT(context);
249 WINPR_ASSERT(context->priv);
250 const uintptr_t key = irp->CompletionId + 1ull;
251 return ListDictionary_Add(context->priv->IrpList, (
void*)key, irp);
254static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
257 WINPR_ASSERT(context);
258 WINPR_ASSERT(context->priv);
260 const uintptr_t key = completionId + 1ull;
261 irp = (
RDPDR_IRP*)ListDictionary_Take(context->priv->IrpList, (
void*)key);
265static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context,
wStream* s)
270 WINPR_ASSERT(context);
271 WINPR_ASSERT(context->priv);
274 Stream_SealLength(s);
275 const size_t length = Stream_Length(s);
276 WINPR_ASSERT(length <= UINT32_MAX);
277 Stream_SetPosition(s, 0);
279 if (length >= RDPDR_HEADER_LENGTH)
282 Stream_Read_UINT16(s, header.Component);
283 Stream_Read_UINT16(s, header.PacketId);
285 WLog_Print(context->priv->log, WLOG_DEBUG,
286 "sending message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
287 rdpdr_component_string(header.Component), header.Component,
288 rdpdr_packetid_string(header.PacketId), header.PacketId);
290 winpr_HexLogDump(context->priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
291 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
292 (ULONG)length, &written);
293 Stream_Free(s, TRUE);
294 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
302static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
308 WINPR_ASSERT(context);
309 WINPR_ASSERT(context->priv);
311 header.Component = RDPDR_CTYP_CORE;
312 header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
314 error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
315 if (error != CHANNEL_RC_OK)
318 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
322 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
323 return CHANNEL_RC_NO_MEMORY;
326 Stream_Write_UINT16(s, header.Component);
327 Stream_Write_UINT16(s, header.PacketId);
328 Stream_Write_UINT16(s, context->priv->VersionMajor);
329 Stream_Write_UINT16(s, context->priv->VersionMinor);
330 Stream_Write_UINT32(s, context->priv->ClientId);
331 return rdpdr_seal_send_free_request(context, s);
339static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
wStream* s,
343 UINT16 VersionMajor = 0;
344 UINT16 VersionMinor = 0;
345 WINPR_ASSERT(context);
346 WINPR_ASSERT(context->priv);
347 WINPR_ASSERT(header);
349 WINPR_UNUSED(header);
351 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
352 return ERROR_INVALID_DATA;
354 Stream_Read_UINT16(s, VersionMajor);
355 Stream_Read_UINT16(s, VersionMinor);
356 Stream_Read_UINT32(s, ClientId);
357 WLog_Print(context->priv->log, WLOG_DEBUG,
358 "Client Announce Response: VersionMajor: 0x%08" PRIX16
" VersionMinor: 0x%04" PRIX16
359 " ClientId: 0x%08" PRIX32
"",
360 VersionMajor, VersionMinor, ClientId);
361 context->priv->ClientId = ClientId;
363 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
364 VersionMinor, ClientId);
372static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context,
wStream* s,
375 UINT32 UnicodeFlag = 0;
377 UINT32 ComputerNameLen = 0;
379 WINPR_ASSERT(context);
380 WINPR_ASSERT(context->priv);
382 WINPR_ASSERT(header);
383 WINPR_UNUSED(header);
385 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
386 return ERROR_INVALID_DATA;
388 Stream_Read_UINT32(s, UnicodeFlag);
389 Stream_Read_UINT32(s, CodePage);
390 Stream_Read_UINT32(s, ComputerNameLen);
393 UnicodeFlag = UnicodeFlag & 0x00000001;
396 WLog_Print(context->priv->log, WLOG_WARN,
397 "[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
398 "must be 0, but is 0x%08" PRIx32,
408 if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
410 WLog_Print(context->priv->log, WLOG_ERROR,
411 "invalid unicode computer name length: %" PRIu32
"", ComputerNameLen);
412 return ERROR_INVALID_DATA;
417 if (ComputerNameLen > 256 || ComputerNameLen < 1)
419 WLog_Print(context->priv->log, WLOG_ERROR,
420 "invalid ascii computer name length: %" PRIu32
"", ComputerNameLen);
421 return ERROR_INVALID_DATA;
425 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, ComputerNameLen))
426 return ERROR_INVALID_DATA;
429 const char* computerName = Stream_ConstPointer(s);
430 if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
432 WLog_Print(context->priv->log, WLOG_ERROR,
"computer name must be null terminated");
433 return ERROR_INVALID_DATA;
436 if (context->priv->ClientComputerName)
438 free(context->priv->ClientComputerName);
439 context->priv->ClientComputerName = NULL;
444 context->priv->ClientComputerName =
445 Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen /
sizeof(WCHAR), NULL);
446 if (!context->priv->ClientComputerName)
448 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to convert client computer name");
449 return ERROR_INVALID_DATA;
454 const char* name = Stream_ConstPointer(s);
455 context->priv->ClientComputerName = _strdup(name);
456 Stream_Seek(s, ComputerNameLen);
458 if (!context->priv->ClientComputerName)
460 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to duplicate client computer name");
461 return CHANNEL_RC_NO_MEMORY;
465 WLog_Print(context->priv->log, WLOG_DEBUG,
"ClientComputerName: %s",
466 context->priv->ClientComputerName);
467 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
468 context->priv->ClientComputerName);
471static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context,
wStream* s,
474 WINPR_ASSERT(context);
475 WINPR_ASSERT(context->priv);
476 UINT error = rdpdr_write_capset_header(context->priv->log, s, header);
477 if (error != CHANNEL_RC_OK)
480 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0, NULL);
488static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context,
wStream* s,
492 UINT32 extraFlags1 = 0;
493 UINT32 extendedPdu = 0;
494 UINT16 VersionMajor = 0;
495 UINT16 VersionMinor = 0;
496 UINT32 SpecialTypeDeviceCap = 0;
497 WINPR_ASSERT(context);
498 WINPR_ASSERT(context->priv);
499 WINPR_ASSERT(header);
501 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
502 return ERROR_INVALID_DATA;
504 Stream_Seek_UINT32(s);
505 Stream_Seek_UINT32(s);
506 Stream_Read_UINT16(s, VersionMajor);
507 Stream_Read_UINT16(s, VersionMinor);
508 Stream_Read_UINT32(s, ioCode1);
509 Stream_Seek_UINT32(s);
510 Stream_Read_UINT32(s, extendedPdu);
511 Stream_Read_UINT32(s, extraFlags1);
512 Stream_Seek_UINT32(s);
514 if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
516 WLog_Print(context->priv->log, WLOG_ERROR,
"unsupported RDPDR version %" PRIu16
".%" PRIu16,
517 VersionMajor, VersionMinor);
518 return ERROR_INVALID_DATA;
521 switch (VersionMinor)
523 case RDPDR_MINOR_RDP_VERSION_13:
524 case RDPDR_MINOR_RDP_VERSION_6_X:
525 case RDPDR_MINOR_RDP_VERSION_5_2:
526 case RDPDR_MINOR_RDP_VERSION_5_1:
527 case RDPDR_MINOR_RDP_VERSION_5_0:
530 WLog_Print(context->priv->log, WLOG_WARN,
531 "unsupported RDPDR minor version %" PRIu16
".%" PRIu16, VersionMajor,
536 if (header->Version == GENERAL_CAPABILITY_VERSION_02)
538 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
539 return ERROR_INVALID_DATA;
541 Stream_Read_UINT32(s, SpecialTypeDeviceCap);
544 context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
545 return CHANNEL_RC_OK;
553static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context,
wStream* s)
556 UINT32 extendedPdu = 0;
557 UINT32 extraFlags1 = 0;
558 UINT32 SpecialTypeDeviceCap = 0;
560 GENERAL_CAPABILITY_VERSION_02 };
562 WINPR_ASSERT(context);
563 WINPR_ASSERT(context->priv);
566 ioCode1 |= RDPDR_IRP_MJ_CREATE;
567 ioCode1 |= RDPDR_IRP_MJ_CLEANUP;
568 ioCode1 |= RDPDR_IRP_MJ_CLOSE;
569 ioCode1 |= RDPDR_IRP_MJ_READ;
570 ioCode1 |= RDPDR_IRP_MJ_WRITE;
571 ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS;
572 ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN;
573 ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL;
574 ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION;
575 ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION;
576 ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION;
577 ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION;
578 ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL;
579 ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL;
580 ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY;
581 ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY;
583 extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU;
584 extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS;
586 if (context->priv->UserLoggedOnPdu)
587 extendedPdu |= RDPDR_USER_LOGGEDON_PDU;
590 extraFlags1 |= ENABLE_ASYNCIO;
591 SpecialTypeDeviceCap = 0;
593 UINT error = rdpdr_write_capset_header(context->priv->log, s, &header);
594 if (error != CHANNEL_RC_OK)
597 const BYTE* data = Stream_ConstPointer(s);
598 const size_t start = Stream_GetPosition(s);
599 Stream_Write_UINT32(s, 0);
600 Stream_Write_UINT32(s, 0);
601 Stream_Write_UINT16(s, context->priv->VersionMajor);
602 Stream_Write_UINT16(s, context->priv->VersionMinor);
603 Stream_Write_UINT32(s, ioCode1);
604 Stream_Write_UINT32(s, 0);
605 Stream_Write_UINT32(s, extendedPdu);
606 Stream_Write_UINT32(s, extraFlags1);
609 Stream_Write_UINT32(s, SpecialTypeDeviceCap);
610 const size_t end = Stream_GetPosition(s);
611 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
619static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context,
wStream* s,
622 WINPR_ASSERT(context);
623 WINPR_ASSERT(context->priv);
625 WINPR_ASSERT(header);
626 WINPR_UNUSED(context);
627 WINPR_UNUSED(header);
630 return CHANNEL_RC_OK;
638static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context,
wStream* s)
641 PRINT_CAPABILITY_VERSION_01 };
642 WINPR_UNUSED(context);
643 WINPR_ASSERT(context);
644 WINPR_ASSERT(context->priv);
646 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
654static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context,
wStream* s,
657 WINPR_UNUSED(context);
659 WINPR_UNUSED(header);
660 WINPR_ASSERT(context);
661 WINPR_ASSERT(context->priv);
663 return CHANNEL_RC_OK;
671static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
wStream* s)
674 PORT_CAPABILITY_VERSION_01 };
675 WINPR_UNUSED(context);
676 WINPR_ASSERT(context);
677 WINPR_ASSERT(context->priv);
679 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
687static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
wStream* s,
690 WINPR_ASSERT(context);
691 WINPR_ASSERT(context->priv);
692 WINPR_UNUSED(context);
693 WINPR_UNUSED(header);
696 return CHANNEL_RC_OK;
704static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
wStream* s)
707 DRIVE_CAPABILITY_VERSION_02 };
709 WINPR_ASSERT(context);
710 WINPR_ASSERT(context->priv);
711 WINPR_UNUSED(context);
713 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
721static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context,
wStream* s,
724 WINPR_ASSERT(context);
725 WINPR_ASSERT(context->priv);
726 WINPR_UNUSED(context);
727 WINPR_UNUSED(header);
730 return CHANNEL_RC_OK;
738static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context,
wStream* s)
741 SMARTCARD_CAPABILITY_VERSION_01 };
742 WINPR_ASSERT(context);
743 WINPR_ASSERT(context->priv);
745 WINPR_UNUSED(context);
747 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
755static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
759 UINT16 numCapabilities = 0;
761 WINPR_ASSERT(context);
762 WINPR_ASSERT(context->priv);
764 header.Component = RDPDR_CTYP_CORE;
765 header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
768 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
771 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
772 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
775 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
778 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
781 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
785 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
786 return CHANNEL_RC_NO_MEMORY;
789 Stream_Write_UINT16(s, header.Component);
790 Stream_Write_UINT16(s, header.PacketId);
791 Stream_Write_UINT16(s, numCapabilities);
792 Stream_Write_UINT16(s, 0);
794 if ((error = rdpdr_server_write_general_capability_set(context, s)))
796 WLog_Print(context->priv->log, WLOG_ERROR,
797 "rdpdr_server_write_general_capability_set failed with error %" PRIu32
"!",
802 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
804 if ((error = rdpdr_server_write_drive_capability_set(context, s)))
806 WLog_Print(context->priv->log, WLOG_ERROR,
807 "rdpdr_server_write_drive_capability_set failed with error %" PRIu32
"!",
813 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
814 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
816 if ((error = rdpdr_server_write_port_capability_set(context, s)))
818 WLog_Print(context->priv->log, WLOG_ERROR,
819 "rdpdr_server_write_port_capability_set failed with error %" PRIu32
"!",
825 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
827 if ((error = rdpdr_server_write_printer_capability_set(context, s)))
829 WLog_Print(context->priv->log, WLOG_ERROR,
830 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
836 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
838 if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
840 WLog_Print(context->priv->log, WLOG_ERROR,
841 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
847 return rdpdr_seal_send_free_request(context, s);
849 Stream_Free(s, TRUE);
858static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context,
wStream* s,
862 UINT16 numCapabilities = 0;
864 WINPR_ASSERT(context);
865 WINPR_ASSERT(context->priv);
867 WINPR_UNUSED(header);
869 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
870 return ERROR_INVALID_DATA;
872 Stream_Read_UINT16(s, numCapabilities);
873 Stream_Seek_UINT16(s);
876 for (UINT16 i = 0; i < numCapabilities; i++)
879 const size_t start = Stream_GetPosition(s);
881 if ((status = rdpdr_read_capset_header(context->priv->log, s, &capabilityHeader)))
883 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
887 status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
888 Stream_GetRemainingLength(s), Stream_ConstPointer(s));
889 if (status != CHANNEL_RC_OK)
892 caps |= capabilityHeader.CapabilityType;
893 switch (capabilityHeader.CapabilityType)
895 case CAP_GENERAL_TYPE:
897 rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
899 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
906 case CAP_PRINTER_TYPE:
908 rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
910 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
918 if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
920 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
929 rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
931 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
938 case CAP_SMARTCARD_TYPE:
940 rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
942 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
950 WLog_Print(context->priv->log, WLOG_WARN,
"Unknown capabilityType %" PRIu16
"",
951 capabilityHeader.CapabilityType);
952 Stream_Seek(s, capabilityHeader.CapabilityLength);
953 return ERROR_INVALID_DATA;
956 for (UINT16 x = 0; x < 16; x++)
958 const UINT16 mask = (UINT16)(1 << x);
959 if (((caps & mask) != 0) && ((context->supported & mask) == 0))
961 WLog_Print(context->priv->log, WLOG_WARN,
962 "client sent capability %s we did not announce!",
968 if ((caps & mask) == 0)
969 context->supported &= ~mask;
972 const size_t end = Stream_GetPosition(s);
973 const size_t diff = end - start;
974 if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
976 WLog_Print(context->priv->log, WLOG_WARN,
977 "{capability %s[0x%04" PRIx16
"]} processed %" PRIuz
978 " bytes, but expected to be %" PRIu16,
979 rdpdr_cap_type_string(capabilityHeader.CapabilityType),
980 capabilityHeader.CapabilityType, diff, capabilityHeader.CapabilityLength);
984 return CHANNEL_RC_OK;
992static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
997 WINPR_ASSERT(context);
998 WINPR_ASSERT(context->priv);
1000 header.Component = RDPDR_CTYP_CORE;
1001 header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
1002 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
1006 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1007 return CHANNEL_RC_NO_MEMORY;
1010 Stream_Write_UINT16(s, header.Component);
1011 Stream_Write_UINT16(s, header.PacketId);
1012 Stream_Write_UINT16(s, context->priv->VersionMajor);
1013 Stream_Write_UINT16(s, context->priv->VersionMinor);
1014 Stream_Write_UINT32(s, context->priv->ClientId);
1015 return rdpdr_seal_send_free_request(context, s);
1023static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context,
1027 UINT32 DeviceCount = 0;
1029 WINPR_ASSERT(context);
1030 WINPR_ASSERT(context->priv);
1032 WINPR_UNUSED(header);
1034 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1035 return ERROR_INVALID_DATA;
1037 Stream_Read_UINT32(s, DeviceCount);
1038 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1040 for (UINT32 i = 0; i < DeviceCount; i++)
1045 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
1046 return ERROR_INVALID_DATA;
1048 Stream_Read_UINT32(s, device.DeviceType);
1049 Stream_Read_UINT32(s, device.DeviceId);
1050 Stream_Read(s, device.PreferredDosName, 8);
1051 Stream_Read_UINT32(s, device.DeviceDataLength);
1052 device.DeviceData = Stream_Pointer(s);
1054 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, device.DeviceDataLength))
1055 return ERROR_INVALID_DATA;
1057 if (!rdpdr_add_device(context->priv, &device))
1058 return ERROR_INTERNAL_ERROR;
1060 error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
1061 if (error != CHANNEL_RC_OK)
1064 switch (device.DeviceType)
1066 case RDPDR_DTYP_FILESYSTEM:
1067 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1068 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
1071 case RDPDR_DTYP_PRINT:
1072 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1073 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
1076 case RDPDR_DTYP_SERIAL:
1077 if (device.DeviceDataLength != 0)
1079 WLog_Print(context->priv->log, WLOG_WARN,
1080 "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32
"]",
1081 device.DeviceDataLength);
1082 error = ERROR_INVALID_DATA;
1084 else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1086 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
1089 case RDPDR_DTYP_PARALLEL:
1090 if (device.DeviceDataLength != 0)
1092 WLog_Print(context->priv->log, WLOG_WARN,
1093 "[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32
"]",
1094 device.DeviceDataLength);
1095 error = ERROR_INVALID_DATA;
1097 else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1098 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
1102 case RDPDR_DTYP_SMARTCARD:
1103 if (device.DeviceDataLength != 0)
1105 WLog_Print(context->priv->log, WLOG_WARN,
1106 "[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32
"]",
1107 device.DeviceDataLength);
1108 error = ERROR_INVALID_DATA;
1110 else if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1112 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardCreate, context, &device);
1116 WLog_Print(context->priv->log, WLOG_WARN,
1117 "[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
1118 "(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
1119 " at position %" PRIu32,
1120 device.DeviceType, i);
1121 error = ERROR_INVALID_DATA;
1125 if (error != CHANNEL_RC_OK)
1128 Stream_Seek(s, device.DeviceDataLength);
1131 return CHANNEL_RC_OK;
1139static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context,
wStream* s,
1142 UINT32 DeviceCount = 0;
1143 UINT32 DeviceType = 0;
1144 UINT32 DeviceId = 0;
1145 WINPR_ASSERT(context);
1146 WINPR_ASSERT(context->priv);
1148 WINPR_UNUSED(header);
1150 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1151 return ERROR_INVALID_DATA;
1153 Stream_Read_UINT32(s, DeviceCount);
1154 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1156 for (UINT32 i = 0; i < DeviceCount; i++)
1161 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1162 return ERROR_INVALID_DATA;
1164 Stream_Read_UINT32(s, DeviceId);
1165 device = rdpdr_get_device_by_id(context->priv, DeviceId);
1166 WLog_Print(context->priv->log, WLOG_DEBUG,
"Device %" PRIu32
" Id: 0x%08" PRIX32
"", i,
1170 DeviceType = device->DeviceType;
1173 IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
1174 if (error != CHANNEL_RC_OK)
1179 case RDPDR_DTYP_FILESYSTEM:
1180 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1181 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
1184 case RDPDR_DTYP_PRINT:
1185 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1187 IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
1190 case RDPDR_DTYP_SERIAL:
1191 if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1193 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
1196 case RDPDR_DTYP_PARALLEL:
1197 if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1198 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
1202 case RDPDR_DTYP_SMARTCARD:
1203 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1205 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
1212 if (error != CHANNEL_RC_OK)
1215 if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
1216 return ERROR_INVALID_DATA;
1219 return CHANNEL_RC_OK;
1222static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
wStream* s,
1223 WINPR_ATTR_UNUSED UINT32 DeviceId,
1224 WINPR_ATTR_UNUSED UINT32 FileId,
1225 WINPR_ATTR_UNUSED UINT32 CompletionId)
1227 const WCHAR* path = NULL;
1228 UINT32 DesiredAccess = 0;
1229 UINT32 AllocationSize = 0;
1230 UINT32 FileAttributes = 0;
1231 UINT32 SharedAccess = 0;
1232 UINT32 CreateDisposition = 0;
1233 UINT32 CreateOptions = 0;
1234 UINT32 PathLength = 0;
1236 WINPR_ASSERT(context);
1237 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1238 return ERROR_INVALID_DATA;
1240 Stream_Read_UINT32(s, DesiredAccess);
1241 Stream_Read_UINT32(s, AllocationSize);
1242 Stream_Read_UINT32(s, FileAttributes);
1243 Stream_Read_UINT32(s, SharedAccess);
1244 Stream_Read_UINT32(s, CreateDisposition);
1245 Stream_Read_UINT32(s, CreateOptions);
1246 Stream_Read_UINT32(s, PathLength);
1248 path = rdpdr_read_ustring(context->priv->log, s, PathLength);
1249 if (!path && (PathLength > 0))
1250 return ERROR_INVALID_DATA;
1252 WLog_Print(context->priv->log, WLOG_WARN,
1253 "[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
1254 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1256 return CHANNEL_RC_OK;
1259static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context,
wStream* s,
1260 WINPR_ATTR_UNUSED UINT32 DeviceId,
1261 WINPR_ATTR_UNUSED UINT32 FileId,
1262 WINPR_ATTR_UNUSED UINT32 CompletionId)
1264 WINPR_ASSERT(context);
1265 WINPR_ASSERT(context->priv);
1267 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1268 return ERROR_INVALID_DATA;
1272 WLog_Print(context->priv->log, WLOG_WARN,
1273 "[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
1274 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1276 return CHANNEL_RC_OK;
1279static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context,
wStream* s,
1280 WINPR_ATTR_UNUSED UINT32 DeviceId,
1281 WINPR_ATTR_UNUSED UINT32 FileId,
1282 WINPR_ATTR_UNUSED UINT32 CompletionId)
1287 WINPR_ASSERT(context);
1288 WINPR_ASSERT(context->priv);
1289 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1290 return ERROR_INVALID_DATA;
1292 Stream_Read_UINT32(s, Length);
1293 Stream_Read_UINT64(s, Offset);
1296 WLog_Print(context->priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32,
1299 WLog_Print(context->priv->log, WLOG_WARN,
1300 "[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
1301 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1303 return CHANNEL_RC_OK;
1306static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context,
wStream* s,
1307 WINPR_ATTR_UNUSED UINT32 DeviceId,
1308 WINPR_ATTR_UNUSED UINT32 FileId,
1309 WINPR_ATTR_UNUSED UINT32 CompletionId)
1314 WINPR_ASSERT(context);
1315 WINPR_ASSERT(context->priv);
1317 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1318 return ERROR_INVALID_DATA;
1320 Stream_Read_UINT32(s, Length);
1321 Stream_Read_UINT64(s, Offset);
1324 WLog_Print(context->priv->log, WLOG_DEBUG,
"Got Offset [0x%016" PRIx64
"], Length %" PRIu32,
1327 const BYTE* data = Stream_ConstPointer(s);
1328 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1329 return ERROR_INVALID_DATA;
1330 Stream_Seek(s, Length);
1332 WLog_Print(context->priv->log, WLOG_WARN,
1333 "[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
1334 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", data);
1336 return CHANNEL_RC_OK;
1339static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* context,
wStream* s,
1340 WINPR_ATTR_UNUSED UINT32 DeviceId,
1341 WINPR_ATTR_UNUSED UINT32 FileId,
1342 WINPR_ATTR_UNUSED UINT32 CompletionId)
1344 UINT32 OutputBufferLength = 0;
1345 UINT32 InputBufferLength = 0;
1346 UINT32 IoControlCode = 0;
1348 WINPR_ASSERT(context);
1349 WINPR_ASSERT(context->priv);
1351 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1352 return ERROR_INVALID_DATA;
1354 Stream_Read_UINT32(s, OutputBufferLength);
1355 Stream_Read_UINT32(s, InputBufferLength);
1356 Stream_Read_UINT32(s, IoControlCode);
1359 const BYTE* InputBuffer = Stream_ConstPointer(s);
1360 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, InputBufferLength))
1361 return ERROR_INVALID_DATA;
1362 Stream_Seek(s, InputBufferLength);
1364 WLog_Print(context->priv->log, WLOG_WARN,
1365 "[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
1366 WLog_Print(context->priv->log, WLOG_WARN,
1367 "TODO: parse %p [%" PRIu32
"], OutputBufferLength=%" PRIu32, InputBuffer,
1368 InputBufferLength, OutputBufferLength);
1370 return CHANNEL_RC_OK;
1373static UINT rdpdr_server_receive_io_query_volume_information_request(
1374 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1375 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1377 UINT32 FsInformationClass = 0;
1380 WINPR_ASSERT(context);
1381 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1382 return ERROR_INVALID_DATA;
1384 Stream_Read_UINT32(s, FsInformationClass);
1385 Stream_Read_UINT32(s, Length);
1388 WLog_Print(context->priv->log, WLOG_DEBUG,
1389 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1390 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1392 const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
1393 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1394 return ERROR_INVALID_DATA;
1395 Stream_Seek(s, Length);
1397 WLog_Print(context->priv->log, WLOG_WARN,
1398 "[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
1399 "(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
1400 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", QueryVolumeBuffer);
1402 return CHANNEL_RC_OK;
1405static UINT rdpdr_server_receive_io_set_volume_information_request(
1406 RdpdrServerContext* context,
wStream* s, WINPR_ATTR_UNUSED UINT32 DeviceId,
1407 WINPR_ATTR_UNUSED UINT32 FileId, WINPR_ATTR_UNUSED UINT32 CompletionId)
1409 UINT32 FsInformationClass = 0;
1412 WINPR_ASSERT(context);
1413 WINPR_ASSERT(context->priv);
1415 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1416 return ERROR_INVALID_DATA;
1418 Stream_Read_UINT32(s, FsInformationClass);
1419 Stream_Read_UINT32(s, Length);
1422 WLog_Print(context->priv->log, WLOG_DEBUG,
1423 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1424 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1426 const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
1427 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1428 return ERROR_INVALID_DATA;
1429 Stream_Seek(s, Length);
1431 WLog_Print(context->priv->log, WLOG_WARN,
1432 "[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
1433 "(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
1434 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", SetVolumeBuffer);
1436 return CHANNEL_RC_OK;
1439static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext* context,
1441 WINPR_ATTR_UNUSED UINT32 DeviceId,
1442 WINPR_ATTR_UNUSED UINT32 FileId,
1443 WINPR_ATTR_UNUSED UINT32 CompletionId)
1445 UINT32 FsInformationClass = 0;
1448 WINPR_ASSERT(context);
1449 WINPR_ASSERT(context->priv);
1451 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1452 return ERROR_INVALID_DATA;
1454 Stream_Read_UINT32(s, FsInformationClass);
1455 Stream_Read_UINT32(s, Length);
1458 WLog_Print(context->priv->log, WLOG_DEBUG,
1459 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1460 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1462 const BYTE* QueryBuffer = Stream_ConstPointer(s);
1463 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1464 return ERROR_INVALID_DATA;
1465 Stream_Seek(s, Length);
1467 WLog_Print(context->priv->log, WLOG_WARN,
1468 "[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
1469 "(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
1470 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", QueryBuffer);
1472 return CHANNEL_RC_OK;
1475static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext* context,
wStream* s,
1476 WINPR_ATTR_UNUSED UINT32 DeviceId,
1477 WINPR_ATTR_UNUSED UINT32 FileId,
1478 WINPR_ATTR_UNUSED UINT32 CompletionId)
1480 UINT32 FsInformationClass = 0;
1483 WINPR_ASSERT(context);
1484 WINPR_ASSERT(context->priv);
1486 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1487 return ERROR_INVALID_DATA;
1489 Stream_Read_UINT32(s, FsInformationClass);
1490 Stream_Read_UINT32(s, Length);
1493 WLog_Print(context->priv->log, WLOG_DEBUG,
1494 "Got FSInformationClass %s [0x%08" PRIx32
"], Length %" PRIu32,
1495 FSInformationClass2Tag(FsInformationClass), FsInformationClass, Length);
1497 const BYTE* SetBuffer = Stream_ConstPointer(s);
1498 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1499 return ERROR_INVALID_DATA;
1500 Stream_Seek(s, Length);
1502 WLog_Print(context->priv->log, WLOG_WARN,
1503 "[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
1504 "(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
1505 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", SetBuffer);
1507 return CHANNEL_RC_OK;
1510static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext* context,
wStream* s,
1511 WINPR_ATTR_UNUSED UINT32 DeviceId,
1512 WINPR_ATTR_UNUSED UINT32 FileId,
1513 WINPR_ATTR_UNUSED UINT32 CompletionId)
1515 BYTE InitialQuery = 0;
1516 UINT32 FsInformationClass = 0;
1517 UINT32 PathLength = 0;
1519 WINPR_ASSERT(context);
1520 WINPR_ASSERT(context->priv);
1522 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1523 return ERROR_INVALID_DATA;
1525 Stream_Read_UINT32(s, FsInformationClass);
1526 Stream_Read_UINT8(s, InitialQuery);
1527 Stream_Read_UINT32(s, PathLength);
1530 const WCHAR* wPath = rdpdr_read_ustring(context->priv->log, s, PathLength);
1531 if (!wPath && (PathLength > 0))
1532 return ERROR_INVALID_DATA;
1534 char* Path = ConvertWCharNToUtf8Alloc(wPath, PathLength /
sizeof(WCHAR), NULL);
1535 WLog_Print(context->priv->log, WLOG_DEBUG,
1536 "Got FSInformationClass %s [0x%08" PRIx32
"], InitialQuery [%" PRIu8
1537 "] Path[%" PRIu32
"] %s",
1538 FSInformationClass2Tag(FsInformationClass), FsInformationClass, InitialQuery,
1542 WLog_Print(context->priv->log, WLOG_WARN,
1543 "[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
1544 "(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
1545 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1547 return CHANNEL_RC_OK;
1550static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext* context,
1552 WINPR_ATTR_UNUSED UINT32 DeviceId,
1553 WINPR_ATTR_UNUSED UINT32 FileId,
1554 WINPR_ATTR_UNUSED UINT32 CompletionId)
1557 UINT32 CompletionFilter = 0;
1559 WINPR_ASSERT(context);
1560 WINPR_ASSERT(context->priv);
1562 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1563 return ERROR_INVALID_DATA;
1565 Stream_Read_UINT8(s, WatchTree);
1566 Stream_Read_UINT32(s, CompletionFilter);
1569 WLog_Print(context->priv->log, WLOG_WARN,
1570 "[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
1571 "(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
1572 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1574 return CHANNEL_RC_OK;
1577static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext* context,
1579 UINT32 FileId, UINT32 CompletionId,
1580 UINT32 MinorFunction)
1582 WINPR_ASSERT(context);
1583 WINPR_ASSERT(context->priv);
1585 switch (MinorFunction)
1587 case IRP_MN_QUERY_DIRECTORY:
1588 return rdpdr_server_receive_io_query_directory_request(context, s, DeviceId, FileId,
1590 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
1591 return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
1594 WLog_Print(context->priv->log, WLOG_WARN,
1595 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
1596 "MajorFunction=%s, MinorFunction=%08" PRIx32
" is not supported",
1597 rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
1598 return ERROR_INVALID_DATA;
1602static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* context,
wStream* s,
1603 WINPR_ATTR_UNUSED UINT32 DeviceId,
1604 WINPR_ATTR_UNUSED UINT32 FileId,
1605 WINPR_ATTR_UNUSED UINT32 CompletionId)
1607 WINPR_ASSERT(context);
1608 WINPR_ASSERT(context->priv);
1610 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1611 return ERROR_INVALID_DATA;
1613 const uint32_t Operation = Stream_Get_UINT32(s);
1614 uint32_t Lock = Stream_Get_UINT32(s);
1615 const uint32_t NumLocks = Stream_Get_UINT32(s);
1618 WLog_Print(context->priv->log, WLOG_DEBUG,
1619 "IRP_MJ_LOCK_CONTROL, Operation=%s, Lock=0x%08" PRIx32
", NumLocks=%" PRIu32,
1620 DR_DRIVE_LOCK_REQ2str(Operation));
1624 for (UINT32 x = 0; x < NumLocks; x++)
1629 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 16))
1630 return ERROR_INVALID_DATA;
1632 Stream_Read_UINT64(s, Length);
1633 Stream_Read_UINT64(s, Offset);
1635 WLog_Print(context->priv->log, WLOG_DEBUG,
1636 "Locking at Offset=0x%08" PRIx64
" [Length %" PRIu64
"]", Offset, Length);
1639 WLog_Print(context->priv->log, WLOG_WARN,
1640 "[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
1641 "[Lock=0x%08" PRIx32
"]"
1644 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1646 return CHANNEL_RC_OK;
1649static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
wStream* s,
1652 UINT32 DeviceId = 0;
1654 UINT32 CompletionId = 0;
1655 UINT32 MajorFunction = 0;
1656 UINT32 MinorFunction = 0;
1658 WINPR_ASSERT(context);
1659 WINPR_ASSERT(context->priv);
1660 WINPR_ASSERT(header);
1662 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
1663 return ERROR_INVALID_DATA;
1665 Stream_Read_UINT32(s, DeviceId);
1666 Stream_Read_UINT32(s, FileId);
1667 Stream_Read_UINT32(s, CompletionId);
1668 Stream_Read_UINT32(s, MajorFunction);
1669 Stream_Read_UINT32(s, MinorFunction);
1670 if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
1671 WLog_Print(context->priv->log, WLOG_WARN,
1672 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
1673 "MinorFunction=0x%08" PRIx32
" != 0",
1674 rdpdr_irp_string(MajorFunction), MinorFunction);
1676 switch (MajorFunction)
1679 return rdpdr_server_receive_io_create_request(context, s, DeviceId, FileId,
1682 return rdpdr_server_receive_io_close_request(context, s, DeviceId, FileId,
1685 return rdpdr_server_receive_io_read_request(context, s, DeviceId, FileId, CompletionId);
1687 return rdpdr_server_receive_io_write_request(context, s, DeviceId, FileId,
1689 case IRP_MJ_DEVICE_CONTROL:
1690 return rdpdr_server_receive_io_device_control_request(context, s, DeviceId, FileId,
1692 case IRP_MJ_QUERY_VOLUME_INFORMATION:
1693 return rdpdr_server_receive_io_query_volume_information_request(context, s, DeviceId,
1694 FileId, CompletionId);
1695 case IRP_MJ_QUERY_INFORMATION:
1696 return rdpdr_server_receive_io_query_information_request(context, s, DeviceId, FileId,
1698 case IRP_MJ_SET_INFORMATION:
1699 return rdpdr_server_receive_io_set_information_request(context, s, DeviceId, FileId,
1701 case IRP_MJ_DIRECTORY_CONTROL:
1702 return rdpdr_server_receive_io_directory_control_request(context, s, DeviceId, FileId,
1703 CompletionId, MinorFunction);
1704 case IRP_MJ_LOCK_CONTROL:
1705 return rdpdr_server_receive_io_lock_control_request(context, s, DeviceId, FileId,
1707 case IRP_MJ_SET_VOLUME_INFORMATION:
1708 return rdpdr_server_receive_io_set_volume_information_request(context, s, DeviceId,
1709 FileId, CompletionId);
1713 context->priv->log, WLOG_WARN,
1714 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
1715 WLog_Print(context->priv->log, WLOG_WARN,
1716 "got DeviceId=0x%08" PRIx32
", FileId=0x%08" PRIx32
1717 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
1718 ", MinorFunction=0x%08" PRIx32,
1719 DeviceId, FileId, CompletionId, MajorFunction, MinorFunction);
1720 return ERROR_INVALID_DATA;
1729static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context,
wStream* s,
1732 UINT32 deviceId = 0;
1733 UINT32 completionId = 0;
1734 UINT32 ioStatus = 0;
1736 UINT error = CHANNEL_RC_OK;
1737 WINPR_ASSERT(context);
1738 WINPR_ASSERT(context->priv);
1740 WINPR_ASSERT(header);
1742 WINPR_UNUSED(header);
1744 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
1745 return ERROR_INVALID_DATA;
1747 Stream_Read_UINT32(s, deviceId);
1748 Stream_Read_UINT32(s, completionId);
1749 Stream_Read_UINT32(s, ioStatus);
1750 WLog_Print(context->priv->log, WLOG_DEBUG,
1751 "deviceId=%" PRIu32
", completionId=0x%" PRIx32
", ioStatus=0x%" PRIx32
"", deviceId,
1752 completionId, ioStatus);
1753 irp = rdpdr_server_dequeue_irp(context, completionId);
1757 WLog_Print(context->priv->log, WLOG_ERROR,
"IRP not found for completionId=0x%" PRIx32
"",
1759 return CHANNEL_RC_OK;
1765 error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
1776static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
1781 WINPR_ASSERT(context);
1782 WINPR_ASSERT(context->priv);
1784 header.Component = RDPDR_CTYP_CORE;
1785 header.PacketId = PAKID_CORE_USER_LOGGEDON;
1786 s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
1790 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1791 return CHANNEL_RC_NO_MEMORY;
1794 Stream_Write_UINT16(s, header.Component);
1795 Stream_Write_UINT16(s, header.PacketId);
1796 return rdpdr_seal_send_free_request(context, s);
1799static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context,
wStream* s)
1801 char PortDosName[9] = { 0 };
1802 UINT32 PnPNameLen = 0;
1803 UINT32 DriverNameLen = 0;
1804 UINT32 PrinterNameLen = 0;
1805 UINT32 CachedFieldsLen = 0;
1806 const WCHAR* PnPName = NULL;
1807 const WCHAR* DriverName = NULL;
1808 const WCHAR* PrinterName = NULL;
1810 WINPR_ASSERT(context);
1811 WINPR_ASSERT(context->priv);
1813 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 24))
1814 return ERROR_INVALID_DATA;
1816 Stream_Read(s, PortDosName, 8);
1817 Stream_Read_UINT32(s, PnPNameLen);
1818 Stream_Read_UINT32(s, DriverNameLen);
1819 Stream_Read_UINT32(s, PrinterNameLen);
1820 Stream_Read_UINT32(s, CachedFieldsLen);
1822 PnPName = rdpdr_read_ustring(context->priv->log, s, PnPNameLen);
1823 if (!PnPName && (PnPNameLen > 0))
1824 return ERROR_INVALID_DATA;
1825 DriverName = rdpdr_read_ustring(context->priv->log, s, DriverNameLen);
1826 if (!DriverName && (DriverNameLen > 0))
1827 return ERROR_INVALID_DATA;
1828 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1829 if (!PrinterName && (PrinterNameLen > 0))
1830 return ERROR_INVALID_DATA;
1832 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1833 return ERROR_INVALID_DATA;
1834 Stream_Seek(s, CachedFieldsLen);
1836 WLog_Print(context->priv->log, WLOG_WARN,
1837 "[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
1838 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1839 return CHANNEL_RC_OK;
1842static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context,
wStream* s)
1844 UINT32 PrinterNameLen = 0;
1845 UINT32 CachedFieldsLen = 0;
1846 const WCHAR* PrinterName = NULL;
1848 WINPR_ASSERT(context);
1850 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1851 return ERROR_INVALID_DATA;
1853 Stream_Read_UINT32(s, PrinterNameLen);
1854 Stream_Read_UINT32(s, CachedFieldsLen);
1856 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1857 if (!PrinterName && (PrinterNameLen > 0))
1858 return ERROR_INVALID_DATA;
1860 const BYTE* config = Stream_ConstPointer(s);
1861 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1862 return ERROR_INVALID_DATA;
1863 Stream_Seek(s, CachedFieldsLen);
1866 context->priv->log, WLOG_WARN,
1867 "[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
1868 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", config);
1869 return CHANNEL_RC_OK;
1872static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context,
wStream* s)
1874 UINT32 PrinterNameLen = 0;
1875 const WCHAR* PrinterName = NULL;
1877 WINPR_ASSERT(context);
1878 WINPR_ASSERT(context->priv);
1880 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1881 return ERROR_INVALID_DATA;
1883 Stream_Read_UINT32(s, PrinterNameLen);
1885 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1886 if (!PrinterName && (PrinterNameLen > 0))
1887 return ERROR_INVALID_DATA;
1890 context->priv->log, WLOG_WARN,
1891 "[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
1892 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1893 return CHANNEL_RC_OK;
1896static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context,
wStream* s)
1898 UINT32 OldPrinterNameLen = 0;
1899 UINT32 NewPrinterNameLen = 0;
1900 const WCHAR* OldPrinterName = NULL;
1901 const WCHAR* NewPrinterName = NULL;
1903 WINPR_ASSERT(context);
1904 WINPR_ASSERT(context->priv);
1906 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1907 return ERROR_INVALID_DATA;
1909 Stream_Read_UINT32(s, OldPrinterNameLen);
1910 Stream_Read_UINT32(s, NewPrinterNameLen);
1912 OldPrinterName = rdpdr_read_ustring(context->priv->log, s, OldPrinterNameLen);
1913 if (!OldPrinterName && (OldPrinterNameLen > 0))
1914 return ERROR_INVALID_DATA;
1915 NewPrinterName = rdpdr_read_ustring(context->priv->log, s, NewPrinterNameLen);
1916 if (!NewPrinterName && (NewPrinterNameLen > 0))
1917 return ERROR_INVALID_DATA;
1920 context->priv->log, WLOG_WARN,
1921 "[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
1922 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1923 return CHANNEL_RC_OK;
1927rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context,
wStream* s,
1932 WINPR_ASSERT(context);
1933 WINPR_ASSERT(context->priv);
1934 WINPR_ASSERT(header);
1936 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1937 return ERROR_INVALID_DATA;
1939 Stream_Read_UINT32(s, EventId);
1942 case RDPDR_ADD_PRINTER_EVENT:
1943 return rdpdr_server_receive_prn_cache_add_printer(context, s);
1944 case RDPDR_UPDATE_PRINTER_EVENT:
1945 return rdpdr_server_receive_prn_cache_update_printer(context, s);
1946 case RDPDR_DELETE_PRINTER_EVENT:
1947 return rdpdr_server_receive_prn_cache_delete_printer(context, s);
1948 case RDPDR_RENAME_PRINTER_EVENT:
1949 return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
1951 WLog_Print(context->priv->log, WLOG_WARN,
1952 "[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
1953 return ERROR_INVALID_DATA;
1957static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context,
wStream* s,
1960 UINT32 PrinterId = 0;
1963 WINPR_ASSERT(context);
1964 WINPR_ASSERT(context->priv);
1965 WINPR_ASSERT(header);
1967 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1968 return ERROR_INVALID_DATA;
1970 Stream_Read_UINT32(s, PrinterId);
1971 Stream_Read_UINT32(s, Flags);
1974 context->priv->log, WLOG_WARN,
1975 "[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
1976 WLog_Print(context->priv->log, WLOG_WARN,
"PrinterId=0x%08" PRIx32
", Flags=0x%08" PRIx32,
1978 return CHANNEL_RC_OK;
1986static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context,
wStream* s,
1989 UINT error = ERROR_INVALID_DATA;
1990 WINPR_ASSERT(context);
1991 WINPR_ASSERT(context->priv);
1993 WINPR_ASSERT(header);
1995 WLog_Print(context->priv->log, WLOG_DEBUG,
1996 "receiving message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
1997 rdpdr_component_string(header->Component), header->Component,
1998 rdpdr_packetid_string(header->PacketId), header->PacketId);
2000 if (header->Component == RDPDR_CTYP_CORE)
2002 switch (header->PacketId)
2004 case PAKID_CORE_SERVER_ANNOUNCE:
2005 WLog_Print(context->priv->log, WLOG_ERROR,
2006 "[MS-RDPEFS] 2.2.2.2 Server Announce Request "
2007 "(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
2010 case PAKID_CORE_CLIENTID_CONFIRM:
2011 error = rdpdr_server_receive_announce_response(context, s, header);
2014 case PAKID_CORE_CLIENT_NAME:
2015 error = rdpdr_server_receive_client_name_request(context, s, header);
2016 if (error == CHANNEL_RC_OK)
2017 error = rdpdr_server_send_core_capability_request(context);
2018 if (error == CHANNEL_RC_OK)
2019 error = rdpdr_server_send_client_id_confirm(context);
2022 case PAKID_CORE_USER_LOGGEDON:
2023 WLog_Print(context->priv->log, WLOG_ERROR,
2024 "[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
2025 "must not be sent by a client!");
2028 case PAKID_CORE_SERVER_CAPABILITY:
2029 WLog_Print(context->priv->log, WLOG_ERROR,
2030 "[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
2031 "(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
2034 case PAKID_CORE_CLIENT_CAPABILITY:
2035 error = rdpdr_server_receive_core_capability_response(context, s, header);
2036 if (error == CHANNEL_RC_OK)
2038 if (context->priv->UserLoggedOnPdu)
2039 error = rdpdr_server_send_user_logged_on(context);
2044 case PAKID_CORE_DEVICELIST_ANNOUNCE:
2045 error = rdpdr_server_receive_device_list_announce_request(context, s, header);
2048 case PAKID_CORE_DEVICELIST_REMOVE:
2049 error = rdpdr_server_receive_device_list_remove_request(context, s, header);
2052 case PAKID_CORE_DEVICE_REPLY:
2053 WLog_Print(context->priv->log, WLOG_ERROR,
2054 "[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
2055 "(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
2058 case PAKID_CORE_DEVICE_IOREQUEST:
2059 error = rdpdr_server_receive_device_io_request(context, s, header);
2062 case PAKID_CORE_DEVICE_IOCOMPLETION:
2063 error = rdpdr_server_receive_device_io_completion(context, s, header);
2067 WLog_Print(context->priv->log, WLOG_WARN,
2068 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2069 rdpdr_component_string(header->Component), header->Component,
2070 rdpdr_packetid_string(header->PacketId));
2074 else if (header->Component == RDPDR_CTYP_PRN)
2076 switch (header->PacketId)
2078 case PAKID_PRN_CACHE_DATA:
2079 error = rdpdr_server_receive_prn_cache_data_request(context, s, header);
2082 case PAKID_PRN_USING_XPS:
2083 error = rdpdr_server_receive_prn_using_xps_request(context, s, header);
2087 WLog_Print(context->priv->log, WLOG_WARN,
2088 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2089 rdpdr_component_string(header->Component), header->Component,
2090 rdpdr_packetid_string(header->PacketId));
2096 WLog_Print(context->priv->log, WLOG_WARN,
2097 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
2098 rdpdr_component_string(header->Component), header->Component,
2099 rdpdr_packetid_string(header->PacketId));
2102 return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
2105static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
2109 void* buffer = NULL;
2110 HANDLE events[8] = { 0 };
2111 HANDLE ChannelEvent = NULL;
2112 DWORD BytesReturned = 0;
2114 RdpdrServerContext* context = (RdpdrServerContext*)arg;
2115 wStream* s = Stream_New(NULL, 4096);
2117 WINPR_ASSERT(context);
2118 WINPR_ASSERT(context->priv);
2122 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2123 error = CHANNEL_RC_NO_MEMORY;
2127 if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
2128 &BytesReturned) == TRUE)
2130 if (BytesReturned ==
sizeof(HANDLE))
2131 ChannelEvent = *(HANDLE*)buffer;
2133 WTSFreeMemory(buffer);
2137 events[nCount++] = ChannelEvent;
2138 events[nCount++] = context->priv->StopEvent;
2140 if ((error = rdpdr_server_send_announce_request(context)))
2142 WLog_Print(context->priv->log, WLOG_ERROR,
2143 "rdpdr_server_send_announce_request failed with error %" PRIu32
"!", error);
2149 size_t capacity = 0;
2151 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2153 if (status == WAIT_FAILED)
2155 error = GetLastError();
2156 WLog_Print(context->priv->log, WLOG_ERROR,
2157 "WaitForMultipleObjects failed with error %" PRIu32
"!", error);
2161 status = WaitForSingleObject(context->priv->StopEvent, 0);
2163 if (status == WAIT_FAILED)
2165 error = GetLastError();
2166 WLog_Print(context->priv->log, WLOG_ERROR,
2167 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2171 if (status == WAIT_OBJECT_0)
2174 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned))
2176 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2177 error = ERROR_INTERNAL_ERROR;
2180 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
2182 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_EnsureRemainingCapacity failed!");
2183 error = ERROR_INTERNAL_ERROR;
2187 capacity = MIN(Stream_Capacity(s), UINT32_MAX);
2188 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s,
char),
2189 (ULONG)capacity, &BytesReturned))
2191 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2192 error = ERROR_INTERNAL_ERROR;
2196 if (BytesReturned >= RDPDR_HEADER_LENGTH)
2198 Stream_SetPosition(s, 0);
2199 Stream_SetLength(s, BytesReturned);
2201 while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH)
2205 Stream_Read_UINT16(s, header.Component);
2206 Stream_Read_UINT16(s, header.PacketId);
2208 if ((error = rdpdr_server_receive_pdu(context, s, &header)))
2210 WLog_Print(context->priv->log, WLOG_ERROR,
2211 "rdpdr_server_receive_pdu failed with error %" PRIu32
"!", error);
2219 Stream_Free(s, TRUE);
2222 if (error && context->rdpcontext)
2223 setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
2234static UINT rdpdr_server_start(RdpdrServerContext* context)
2236 WINPR_ASSERT(context);
2237 WINPR_ASSERT(context->priv);
2238 context->priv->ChannelHandle =
2239 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPDR_SVC_CHANNEL_NAME);
2241 if (!context->priv->ChannelHandle)
2243 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelOpen failed!");
2244 return CHANNEL_RC_BAD_CHANNEL;
2247 if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
2249 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateEvent failed!");
2250 return ERROR_INTERNAL_ERROR;
2253 if (!(context->priv->Thread =
2254 CreateThread(NULL, 0, rdpdr_server_thread, (
void*)context, 0, NULL)))
2256 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateThread failed!");
2257 (void)CloseHandle(context->priv->StopEvent);
2258 context->priv->StopEvent = NULL;
2259 return ERROR_INTERNAL_ERROR;
2262 return CHANNEL_RC_OK;
2270static UINT rdpdr_server_stop(RdpdrServerContext* context)
2273 WINPR_ASSERT(context);
2274 WINPR_ASSERT(context->priv);
2276 if (context->priv->StopEvent)
2278 (void)SetEvent(context->priv->StopEvent);
2280 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
2282 error = GetLastError();
2283 WLog_Print(context->priv->log, WLOG_ERROR,
2284 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2288 (void)CloseHandle(context->priv->Thread);
2289 context->priv->Thread = NULL;
2290 (void)CloseHandle(context->priv->StopEvent);
2291 context->priv->StopEvent = NULL;
2294 if (context->priv->ChannelHandle)
2296 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
2297 context->priv->ChannelHandle = NULL;
2299 return CHANNEL_RC_OK;
2302static void rdpdr_server_write_device_iorequest(
wStream* s, UINT32 deviceId, UINT32 fileId,
2303 UINT32 completionId, UINT32 majorFunction,
2304 UINT32 minorFunction)
2306 Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
2307 Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST);
2308 Stream_Write_UINT32(s, deviceId);
2309 Stream_Write_UINT32(s, fileId);
2310 Stream_Write_UINT32(s, completionId);
2311 Stream_Write_UINT32(s, majorFunction);
2312 Stream_Write_UINT32(s, minorFunction);
2320static UINT rdpdr_server_read_file_directory_information(wLog* log,
wStream* s,
2323 UINT32 fileNameLength = 0;
2327 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
2328 return ERROR_INVALID_DATA;
2330 Stream_Read_UINT32(s, fdi->NextEntryOffset);
2331 Stream_Read_UINT32(s, fdi->FileIndex);
2332 Stream_Read_INT64(s, fdi->CreationTime.QuadPart);
2333 Stream_Read_INT64(s, fdi->LastAccessTime.QuadPart);
2334 Stream_Read_INT64(s, fdi->LastWriteTime.QuadPart);
2335 Stream_Read_INT64(s, fdi->ChangeTime.QuadPart);
2336 Stream_Read_INT64(s, fdi->EndOfFile.QuadPart);
2337 Stream_Read_INT64(s, fdi->AllocationSize.QuadPart);
2338 Stream_Read_UINT32(s, fdi->FileAttributes);
2339 Stream_Read_UINT32(s, fileNameLength);
2341 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
2342 return ERROR_INVALID_DATA;
2344 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, fileNameLength /
sizeof(WCHAR), fdi->FileName,
2345 ARRAYSIZE(fdi->FileName)) < 0)
2346 return ERROR_INVALID_DATA;
2347 return CHANNEL_RC_OK;
2355static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, UINT32 deviceId,
2356 UINT32 completionId,
const char* path,
2357 UINT32 desiredAccess, UINT32 createOptions,
2358 UINT32 createDisposition)
2360 size_t pathLength = 0;
2362 WINPR_ASSERT(context);
2363 WINPR_ASSERT(context->priv);
2365 WLog_Print(context->priv->log, WLOG_DEBUG,
2366 "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
2367 ", path=%s, desiredAccess=0x%" PRIx32
" createOptions=0x%" PRIx32
2368 " createDisposition=0x%" PRIx32
"",
2369 deviceId, path, desiredAccess, createOptions, createDisposition);
2371 pathLength = (strlen(path) + 1U) *
sizeof(WCHAR);
2372 s = Stream_New(NULL, 256U + pathLength);
2376 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2377 return CHANNEL_RC_NO_MEMORY;
2380 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
2381 Stream_Write_UINT32(s, desiredAccess);
2382 Stream_Write_UINT32(s, 0);
2383 Stream_Write_UINT32(s, 0);
2384 Stream_Write_UINT32(s, 0);
2385 Stream_Write_UINT32(s, 3);
2386 Stream_Write_UINT32(s, createDisposition);
2387 Stream_Write_UINT32(s, createOptions);
2388 WINPR_ASSERT(pathLength <= UINT32_MAX);
2389 Stream_Write_UINT32(s, (UINT32)pathLength);
2391 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2392 pathLength /
sizeof(WCHAR), TRUE) < 0)
2394 Stream_Free(s, TRUE);
2395 return ERROR_INTERNAL_ERROR;
2397 return rdpdr_seal_send_free_request(context, s);
2405static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId,
2406 UINT32 fileId, UINT32 completionId)
2409 WINPR_ASSERT(context);
2410 WINPR_ASSERT(context->priv);
2412 WLog_Print(context->priv->log, WLOG_DEBUG,
2413 "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
"",
2415 s = Stream_New(NULL, 128);
2419 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2420 return CHANNEL_RC_NO_MEMORY;
2423 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0);
2425 return rdpdr_seal_send_free_request(context, s);
2433static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, UINT32 deviceId,
2434 UINT32 fileId, UINT32 completionId, UINT32 length,
2438 WINPR_ASSERT(context);
2439 WINPR_ASSERT(context->priv);
2441 WLog_Print(context->priv->log, WLOG_DEBUG,
2442 "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2443 ", length=%" PRIu32
", offset=%" PRIu32
"",
2444 deviceId, fileId, length, offset);
2445 s = Stream_New(NULL, 128);
2449 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2450 return CHANNEL_RC_NO_MEMORY;
2453 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0);
2454 Stream_Write_UINT32(s, length);
2455 Stream_Write_UINT32(s, offset);
2456 Stream_Write_UINT32(s, 0);
2458 return rdpdr_seal_send_free_request(context, s);
2466static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, UINT32 deviceId,
2467 UINT32 fileId, UINT32 completionId,
2468 const char* data, UINT32 length, UINT32 offset)
2471 WINPR_ASSERT(context);
2472 WINPR_ASSERT(context->priv);
2474 WLog_Print(context->priv->log, WLOG_DEBUG,
2475 "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2476 ", length=%" PRIu32
", offset=%" PRIu32
"",
2477 deviceId, fileId, length, offset);
2478 s = Stream_New(NULL, 64 + length);
2482 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2483 return CHANNEL_RC_NO_MEMORY;
2486 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0);
2487 Stream_Write_UINT32(s, length);
2488 Stream_Write_UINT32(s, offset);
2489 Stream_Write_UINT32(s, 0);
2491 Stream_Write(s, data, length);
2492 return rdpdr_seal_send_free_request(context, s);
2500static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context,
2501 UINT32 deviceId, UINT32 fileId,
2502 UINT32 completionId,
const char* path)
2504 size_t pathLength = 0;
2506 WINPR_ASSERT(context);
2507 WINPR_ASSERT(context->priv);
2509 WLog_Print(context->priv->log, WLOG_DEBUG,
2510 "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2512 deviceId, fileId, path);
2514 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2515 s = Stream_New(NULL, 64 + pathLength);
2519 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2520 return CHANNEL_RC_NO_MEMORY;
2523 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_DIRECTORY_CONTROL,
2524 IRP_MN_QUERY_DIRECTORY);
2525 Stream_Write_UINT32(s, FileDirectoryInformation);
2526 Stream_Write_UINT8(s, path ? 1 : 0);
2527 WINPR_ASSERT(pathLength <= UINT32_MAX);
2528 Stream_Write_UINT32(s, (UINT32)pathLength);
2534 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2535 pathLength /
sizeof(WCHAR), TRUE) < 0)
2537 Stream_Free(s, TRUE);
2538 return ERROR_INTERNAL_ERROR;
2542 return rdpdr_seal_send_free_request(context, s);
2550static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context,
2551 UINT32 deviceId, UINT32 fileId,
2552 UINT32 completionId,
const char* path)
2554 size_t pathLength = 0;
2556 WINPR_ASSERT(context);
2557 WINPR_ASSERT(context->priv);
2559 WLog_Print(context->priv->log, WLOG_DEBUG,
2560 "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2562 deviceId, fileId, path);
2564 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2565 s = Stream_New(NULL, 64 + pathLength);
2569 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2570 return CHANNEL_RC_NO_MEMORY;
2573 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION,
2575 Stream_Write_UINT32(s, FileRenameInformation);
2576 WINPR_ASSERT(pathLength <= UINT32_MAX - 6U);
2577 Stream_Write_UINT32(s, (UINT32)pathLength + 6U);
2580 Stream_Write_UINT8(s, 0);
2581 Stream_Write_UINT8(s, 0);
2582 Stream_Write_UINT32(s, (UINT32)pathLength);
2587 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2588 pathLength /
sizeof(WCHAR), TRUE) < 0)
2590 Stream_Free(s, TRUE);
2591 return ERROR_INTERNAL_ERROR;
2595 return rdpdr_seal_send_free_request(context, s);
2598static void rdpdr_server_convert_slashes(
char* path,
int size)
2600 WINPR_ASSERT(path || (size <= 0));
2602 for (
int i = 0; (i < size) && (path[i] !=
'\0'); i++)
2618static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context,
wStream* s,
2620 UINT32 completionId, UINT32 ioStatus)
2622 WINPR_ASSERT(context);
2623 WINPR_ASSERT(context->priv);
2628 WLog_Print(context->priv->log, WLOG_DEBUG,
2629 "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
2630 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2631 deviceId, completionId, ioStatus);
2633 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2635 rdpdr_server_irp_free(irp);
2636 return CHANNEL_RC_OK;
2644static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context,
wStream* s,
2646 UINT32 completionId, UINT32 ioStatus)
2648 WINPR_ASSERT(context);
2649 WINPR_ASSERT(context->priv);
2652 WLog_Print(context->priv->log, WLOG_DEBUG,
2653 "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
2654 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2655 deviceId, completionId, ioStatus);
2657 if (ioStatus != STATUS_SUCCESS)
2660 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2662 rdpdr_server_irp_free(irp);
2663 return CHANNEL_RC_OK;
2666 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2667 return ERROR_INVALID_DATA;
2669 const uint32_t fileId = Stream_Get_UINT32(s);
2670 const uint8_t information = Stream_Get_UINT8(s);
2671 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2672 fileInformation2str(information));
2675 irp->CompletionId = context->priv->NextCompletionId++;
2676 irp->Callback = rdpdr_server_drive_create_directory_callback2;
2677 irp->DeviceId = deviceId;
2678 irp->FileId = fileId;
2680 if (!rdpdr_server_enqueue_irp(context, irp))
2682 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2683 rdpdr_server_irp_free(irp);
2684 return ERROR_INTERNAL_ERROR;
2688 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2696static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context,
void* callbackData,
2697 UINT32 deviceId,
const char* path)
2700 WINPR_ASSERT(context);
2701 WINPR_ASSERT(context->priv);
2702 WINPR_ASSERT(callbackData);
2704 irp = rdpdr_server_irp_new();
2708 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2709 return CHANNEL_RC_NO_MEMORY;
2712 irp->CompletionId = context->priv->NextCompletionId++;
2713 irp->Callback = rdpdr_server_drive_create_directory_callback1;
2714 irp->CallbackData = callbackData;
2715 irp->DeviceId = deviceId;
2716 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2717 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2719 if (!rdpdr_server_enqueue_irp(context, irp))
2721 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2722 rdpdr_server_irp_free(irp);
2723 return ERROR_INTERNAL_ERROR;
2727 return rdpdr_server_send_device_create_request(
2728 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
2729 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
2741static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context,
wStream* s,
2743 UINT32 completionId, UINT32 ioStatus)
2746 WINPR_ASSERT(context);
2747 WINPR_ASSERT(context->priv);
2750 WLog_Print(context->priv->log, WLOG_DEBUG,
2751 "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
2752 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2753 deviceId, completionId, ioStatus);
2755 context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
2757 rdpdr_server_irp_free(irp);
2758 return CHANNEL_RC_OK;
2766static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context,
wStream* s,
2768 UINT32 completionId, UINT32 ioStatus)
2770 WINPR_ASSERT(context);
2771 WINPR_ASSERT(context->priv);
2773 WLog_Print(context->priv->log, WLOG_DEBUG,
2774 "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
2775 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2776 deviceId, completionId, ioStatus);
2778 if (ioStatus != STATUS_SUCCESS)
2781 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
2783 rdpdr_server_irp_free(irp);
2784 return CHANNEL_RC_OK;
2787 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2788 return ERROR_INVALID_DATA;
2790 const uint32_t fileId = Stream_Get_UINT32(s);
2791 const uint8_t information = Stream_Get_UINT8(s);
2792 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
2793 fileInformation2str(information));
2796 irp->CompletionId = context->priv->NextCompletionId++;
2797 irp->Callback = rdpdr_server_drive_delete_directory_callback2;
2798 irp->DeviceId = deviceId;
2799 irp->FileId = fileId;
2801 if (!rdpdr_server_enqueue_irp(context, irp))
2803 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2804 rdpdr_server_irp_free(irp);
2805 return ERROR_INTERNAL_ERROR;
2809 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2817static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context,
void* callbackData,
2818 UINT32 deviceId,
const char* path)
2820 RDPDR_IRP* irp = rdpdr_server_irp_new();
2821 WINPR_ASSERT(context);
2822 WINPR_ASSERT(context->priv);
2827 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2828 return CHANNEL_RC_NO_MEMORY;
2831 irp->CompletionId = context->priv->NextCompletionId++;
2832 irp->Callback = rdpdr_server_drive_delete_directory_callback1;
2833 irp->CallbackData = callbackData;
2834 irp->DeviceId = deviceId;
2835 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2836 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2838 if (!rdpdr_server_enqueue_irp(context, irp))
2840 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2841 rdpdr_server_irp_free(irp);
2842 return ERROR_INTERNAL_ERROR;
2846 return rdpdr_server_send_device_create_request(
2847 context, deviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
2848 FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
2860static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context,
wStream* s,
2862 UINT32 completionId, UINT32 ioStatus)
2868 WINPR_ASSERT(context);
2869 WINPR_ASSERT(context->priv);
2871 WLog_Print(context->priv->log, WLOG_DEBUG,
2872 "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
2873 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2874 deviceId, completionId, ioStatus);
2876 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
2877 return ERROR_INVALID_DATA;
2879 Stream_Read_UINT32(s, length);
2883 if ((error = rdpdr_server_read_file_directory_information(context->priv->log, s, &fdi)))
2885 WLog_Print(context->priv->log, WLOG_ERROR,
2886 "rdpdr_server_read_file_directory_information failed with error %" PRIu32
2894 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 1))
2895 return ERROR_INVALID_DATA;
2900 if (ioStatus == STATUS_SUCCESS)
2903 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
2904 length > 0 ? &fdi : NULL);
2906 irp->CompletionId = context->priv->NextCompletionId++;
2907 irp->Callback = rdpdr_server_drive_query_directory_callback2;
2909 if (!rdpdr_server_enqueue_irp(context, irp))
2911 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2912 rdpdr_server_irp_free(irp);
2913 return ERROR_INTERNAL_ERROR;
2917 return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId,
2918 irp->CompletionId, NULL);
2923 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
2925 rdpdr_server_irp_free(irp);
2928 return CHANNEL_RC_OK;
2936static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context,
wStream* s,
2938 UINT32 completionId, UINT32 ioStatus)
2940 WINPR_ASSERT(context);
2941 WINPR_ASSERT(context->priv);
2943 WLog_Print(context->priv->log, WLOG_DEBUG,
2944 "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
2945 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2946 deviceId, completionId, ioStatus);
2948 if (ioStatus != STATUS_SUCCESS)
2951 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
2953 rdpdr_server_irp_free(irp);
2954 return CHANNEL_RC_OK;
2957 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
2958 return ERROR_INVALID_DATA;
2960 const uint32_t fileId = Stream_Get_UINT32(s);
2962 irp->CompletionId = context->priv->NextCompletionId++;
2963 irp->Callback = rdpdr_server_drive_query_directory_callback2;
2964 irp->DeviceId = deviceId;
2965 irp->FileId = fileId;
2966 winpr_str_append(
"\\*.*", irp->PathName, ARRAYSIZE(irp->PathName), NULL);
2968 if (!rdpdr_server_enqueue_irp(context, irp))
2970 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2971 rdpdr_server_irp_free(irp);
2972 return ERROR_INTERNAL_ERROR;
2976 return rdpdr_server_send_device_query_directory_request(context, deviceId, fileId,
2977 irp->CompletionId, irp->PathName);
2985static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context,
void* callbackData,
2986 UINT32 deviceId,
const char* path)
2988 RDPDR_IRP* irp = rdpdr_server_irp_new();
2989 WINPR_ASSERT(context);
2990 WINPR_ASSERT(context->priv);
2995 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2996 return CHANNEL_RC_NO_MEMORY;
2999 irp->CompletionId = context->priv->NextCompletionId++;
3000 irp->Callback = rdpdr_server_drive_query_directory_callback1;
3001 irp->CallbackData = callbackData;
3002 irp->DeviceId = deviceId;
3003 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3004 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3006 if (!rdpdr_server_enqueue_irp(context, irp))
3008 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3009 rdpdr_server_irp_free(irp);
3010 return ERROR_INTERNAL_ERROR;
3014 return rdpdr_server_send_device_create_request(
3015 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3016 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3028static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context,
wStream* s,
3030 UINT32 completionId, UINT32 ioStatus)
3032 WINPR_ASSERT(context);
3033 WINPR_ASSERT(context->priv);
3035 WLog_Print(context->priv->log, WLOG_DEBUG,
3036 "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3037 ", ioStatus=0x%" PRIx32
"",
3038 deviceId, completionId, ioStatus);
3040 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3041 return ERROR_INVALID_DATA;
3043 const uint32_t fileId = Stream_Get_UINT32(s);
3044 const uint8_t information = Stream_Get_UINT8(s);
3045 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3046 fileInformation2str(information));
3049 context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
3051 rdpdr_server_irp_free(irp);
3052 return CHANNEL_RC_OK;
3060static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context,
void* callbackData,
3061 UINT32 deviceId,
const char* path, UINT32 desiredAccess,
3062 UINT32 createDisposition)
3064 RDPDR_IRP* irp = rdpdr_server_irp_new();
3065 WINPR_ASSERT(context);
3066 WINPR_ASSERT(context->priv);
3071 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3072 return CHANNEL_RC_NO_MEMORY;
3075 irp->CompletionId = context->priv->NextCompletionId++;
3076 irp->Callback = rdpdr_server_drive_open_file_callback;
3077 irp->CallbackData = callbackData;
3078 irp->DeviceId = deviceId;
3079 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3080 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3082 if (!rdpdr_server_enqueue_irp(context, irp))
3084 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3085 rdpdr_server_irp_free(irp);
3086 return ERROR_INTERNAL_ERROR;
3090 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
3091 irp->PathName, desiredAccess | SYNCHRONIZE,
3092 FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
3104static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context,
wStream* s,
3106 UINT32 completionId, UINT32 ioStatus)
3109 char* buffer = NULL;
3110 WINPR_ASSERT(context);
3111 WINPR_ASSERT(context->priv);
3113 WLog_Print(context->priv->log, WLOG_DEBUG,
3114 "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3115 ", ioStatus=0x%" PRIx32
"",
3116 deviceId, completionId, ioStatus);
3118 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
3119 return ERROR_INVALID_DATA;
3121 Stream_Read_UINT32(s, length);
3123 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3124 return ERROR_INVALID_DATA;
3128 buffer = Stream_Pointer(s);
3129 Stream_Seek(s, length);
3133 context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
3135 rdpdr_server_irp_free(irp);
3136 return CHANNEL_RC_OK;
3144static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context,
void* callbackData,
3145 UINT32 deviceId, UINT32 fileId, UINT32 length,
3148 RDPDR_IRP* irp = rdpdr_server_irp_new();
3149 WINPR_ASSERT(context);
3150 WINPR_ASSERT(context->priv);
3155 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3156 return CHANNEL_RC_NO_MEMORY;
3159 irp->CompletionId = context->priv->NextCompletionId++;
3160 irp->Callback = rdpdr_server_drive_read_file_callback;
3161 irp->CallbackData = callbackData;
3162 irp->DeviceId = deviceId;
3163 irp->FileId = fileId;
3165 if (!rdpdr_server_enqueue_irp(context, irp))
3167 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3168 rdpdr_server_irp_free(irp);
3169 return ERROR_INTERNAL_ERROR;
3174 return rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId,
3187static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
wStream* s,
3189 UINT32 completionId, UINT32 ioStatus)
3192 WINPR_ASSERT(context);
3193 WINPR_ASSERT(context->priv);
3195 WLog_Print(context->priv->log, WLOG_DEBUG,
3196 "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3197 ", ioStatus=0x%" PRIx32
"",
3198 deviceId, completionId, ioStatus);
3200 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3201 return ERROR_INVALID_DATA;
3203 Stream_Read_UINT32(s, length);
3206 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3207 return ERROR_INVALID_DATA;
3210 context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
3212 rdpdr_server_irp_free(irp);
3213 return CHANNEL_RC_OK;
3221static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context,
void* callbackData,
3222 UINT32 deviceId, UINT32 fileId,
const char* buffer,
3223 UINT32 length, UINT32 offset)
3225 RDPDR_IRP* irp = rdpdr_server_irp_new();
3226 WINPR_ASSERT(context);
3227 WINPR_ASSERT(context->priv);
3232 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3233 return CHANNEL_RC_NO_MEMORY;
3236 irp->CompletionId = context->priv->NextCompletionId++;
3237 irp->Callback = rdpdr_server_drive_write_file_callback;
3238 irp->CallbackData = callbackData;
3239 irp->DeviceId = deviceId;
3240 irp->FileId = fileId;
3242 if (!rdpdr_server_enqueue_irp(context, irp))
3244 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3245 rdpdr_server_irp_free(irp);
3246 return ERROR_INTERNAL_ERROR;
3251 return rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId,
3252 buffer, length, offset);
3264static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
wStream* s,
3266 UINT32 completionId, UINT32 ioStatus)
3269 WINPR_ASSERT(context);
3270 WINPR_ASSERT(context->priv);
3273 WLog_Print(context->priv->log, WLOG_DEBUG,
3274 "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3275 ", ioStatus=0x%" PRIx32
"",
3276 deviceId, completionId, ioStatus);
3279 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3280 return ERROR_INVALID_DATA;
3285 context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
3287 rdpdr_server_irp_free(irp);
3288 return CHANNEL_RC_OK;
3296static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context,
void* callbackData,
3297 UINT32 deviceId, UINT32 fileId)
3299 RDPDR_IRP* irp = rdpdr_server_irp_new();
3300 WINPR_ASSERT(context);
3301 WINPR_ASSERT(context->priv);
3306 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3307 return CHANNEL_RC_NO_MEMORY;
3310 irp->CompletionId = context->priv->NextCompletionId++;
3311 irp->Callback = rdpdr_server_drive_close_file_callback;
3312 irp->CallbackData = callbackData;
3313 irp->DeviceId = deviceId;
3314 irp->FileId = fileId;
3316 if (!rdpdr_server_enqueue_irp(context, irp))
3318 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3319 rdpdr_server_irp_free(irp);
3320 return ERROR_INTERNAL_ERROR;
3325 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3337static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context,
wStream* s,
3339 UINT32 completionId, UINT32 ioStatus)
3342 WINPR_ASSERT(context);
3343 WINPR_ASSERT(context->priv);
3346 WLog_Print(context->priv->log, WLOG_DEBUG,
3347 "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3348 ", ioStatus=0x%" PRIx32
"",
3349 deviceId, completionId, ioStatus);
3351 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3353 rdpdr_server_irp_free(irp);
3354 return CHANNEL_RC_OK;
3362static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context,
wStream* s,
3364 UINT32 completionId, UINT32 ioStatus)
3366 WINPR_ASSERT(context);
3367 WINPR_ASSERT(context->priv);
3369 WLog_Print(context->priv->log, WLOG_DEBUG,
3370 "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3371 ", ioStatus=0x%" PRIx32
"",
3372 deviceId, completionId, ioStatus);
3374 if (ioStatus != STATUS_SUCCESS)
3377 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3379 rdpdr_server_irp_free(irp);
3380 return CHANNEL_RC_OK;
3383 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3384 return ERROR_INVALID_DATA;
3386 const uint32_t fileId = Stream_Get_UINT32(s);
3387 const uint8_t information = Stream_Get_UINT8(s);
3389 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3390 fileInformation2str(information));
3392 irp->CompletionId = context->priv->NextCompletionId++;
3393 irp->Callback = rdpdr_server_drive_delete_file_callback2;
3394 irp->DeviceId = deviceId;
3395 irp->FileId = fileId;
3397 if (!rdpdr_server_enqueue_irp(context, irp))
3399 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3400 rdpdr_server_irp_free(irp);
3401 return ERROR_INTERNAL_ERROR;
3405 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3413static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context,
void* callbackData,
3414 UINT32 deviceId,
const char* path)
3416 RDPDR_IRP* irp = rdpdr_server_irp_new();
3417 WINPR_ASSERT(context);
3418 WINPR_ASSERT(context->priv);
3423 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3424 return CHANNEL_RC_NO_MEMORY;
3427 irp->CompletionId = context->priv->NextCompletionId++;
3428 irp->Callback = rdpdr_server_drive_delete_file_callback1;
3429 irp->CallbackData = callbackData;
3430 irp->DeviceId = deviceId;
3431 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3432 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3434 if (!rdpdr_server_enqueue_irp(context, irp))
3436 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3437 rdpdr_server_irp_free(irp);
3438 return ERROR_INTERNAL_ERROR;
3442 return rdpdr_server_send_device_create_request(
3443 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3444 FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3456static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context,
wStream* s,
3458 UINT32 completionId, UINT32 ioStatus)
3460 WINPR_UNUSED(context);
3462 WINPR_ASSERT(context);
3463 WINPR_ASSERT(context->priv);
3466 WLog_Print(context->priv->log, WLOG_DEBUG,
3467 "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32
", completionId=%" PRIu32
3468 ", ioStatus=0x%" PRIx32
"",
3469 deviceId, completionId, ioStatus);
3471 rdpdr_server_irp_free(irp);
3472 return CHANNEL_RC_OK;
3480static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context,
wStream* s,
3482 UINT32 completionId, UINT32 ioStatus)
3485 WINPR_ASSERT(context);
3486 WINPR_ASSERT(context->priv);
3488 WLog_Print(context->priv->log, WLOG_DEBUG,
3489 "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3490 ", ioStatus=0x%" PRIx32
"",
3491 deviceId, completionId, ioStatus);
3493 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3494 return ERROR_INVALID_DATA;
3496 Stream_Read_UINT32(s, length);
3499 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3501 irp->CompletionId = context->priv->NextCompletionId++;
3502 irp->Callback = rdpdr_server_drive_rename_file_callback3;
3503 irp->DeviceId = deviceId;
3505 if (!rdpdr_server_enqueue_irp(context, irp))
3507 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3508 rdpdr_server_irp_free(irp);
3509 return ERROR_INTERNAL_ERROR;
3513 return rdpdr_server_send_device_close_request(context, deviceId, irp->FileId,
3522static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context,
wStream* s,
3524 UINT32 completionId, UINT32 ioStatus)
3526 WINPR_ASSERT(context);
3527 WINPR_ASSERT(context->priv);
3529 WLog_Print(context->priv->log, WLOG_DEBUG,
3530 "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3531 ", ioStatus=0x%" PRIx32
"",
3532 deviceId, completionId, ioStatus);
3534 if (ioStatus != STATUS_SUCCESS)
3537 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3539 rdpdr_server_irp_free(irp);
3540 return CHANNEL_RC_OK;
3543 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3544 return ERROR_INVALID_DATA;
3546 const uint32_t fileId = Stream_Get_UINT32(s);
3547 const uint8_t information = Stream_Get_UINT8(s);
3548 WLog_Print(context->priv->log, WLOG_DEBUG,
"fileId [0x%08" PRIx32
"], information %s", fileId,
3549 fileInformation2str(information));
3552 irp->CompletionId = context->priv->NextCompletionId++;
3553 irp->Callback = rdpdr_server_drive_rename_file_callback2;
3554 irp->DeviceId = deviceId;
3555 irp->FileId = fileId;
3557 if (!rdpdr_server_enqueue_irp(context, irp))
3559 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3560 rdpdr_server_irp_free(irp);
3561 return ERROR_INTERNAL_ERROR;
3565 return rdpdr_server_send_device_file_rename_request(context, deviceId, fileId,
3566 irp->CompletionId, irp->ExtraBuffer);
3574static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context,
void* callbackData,
3575 UINT32 deviceId,
const char* oldPath,
3576 const char* newPath)
3579 WINPR_ASSERT(context);
3580 WINPR_ASSERT(context->priv);
3581 irp = rdpdr_server_irp_new();
3585 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3586 return CHANNEL_RC_NO_MEMORY;
3589 irp->CompletionId = context->priv->NextCompletionId++;
3590 irp->Callback = rdpdr_server_drive_rename_file_callback1;
3591 irp->CallbackData = callbackData;
3592 irp->DeviceId = deviceId;
3593 strncpy(irp->PathName, oldPath,
sizeof(irp->PathName) - 1);
3594 strncpy(irp->ExtraBuffer, newPath,
sizeof(irp->ExtraBuffer) - 1);
3595 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3596 rdpdr_server_convert_slashes(irp->ExtraBuffer,
sizeof(irp->ExtraBuffer));
3598 if (!rdpdr_server_enqueue_irp(context, irp))
3600 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3601 rdpdr_server_irp_free(irp);
3602 return ERROR_INTERNAL_ERROR;
3607 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
3608 irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3609 FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3612static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
3616 ListDictionary_Free(ctx->IrpList);
3617 HashTable_Free(ctx->devicelist);
3618 free(ctx->ClientComputerName);
3622#define TAG CHANNELS_TAG("rdpdr.server")
3623static RdpdrServerPrivate* rdpdr_server_private_new(
void)
3625 RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1,
sizeof(RdpdrServerPrivate));
3630 priv->log = WLog_Get(TAG);
3631 priv->VersionMajor = RDPDR_VERSION_MAJOR;
3632 priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
3633 priv->ClientId = g_ClientId++;
3634 priv->UserLoggedOnPdu = TRUE;
3635 priv->NextCompletionId = 1;
3636 priv->IrpList = ListDictionary_New(TRUE);
3641 priv->devicelist = HashTable_New(FALSE);
3642 if (!priv->devicelist)
3645 HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash);
3646 wObject* obj = HashTable_ValueObject(priv->devicelist);
3648 obj->fnObjectFree = rdpdr_device_free_h;
3649 obj->fnObjectNew = rdpdr_device_clone;
3651 obj = HashTable_KeyObject(priv->devicelist);
3652 obj->fnObjectEquals = rdpdr_device_equal;
3653 obj->fnObjectFree = rdpdr_device_key_free;
3654 obj->fnObjectNew = rdpdr_device_key_clone;
3658 rdpdr_server_private_free(priv);
3662RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
3664 RdpdrServerContext* context = (RdpdrServerContext*)calloc(1,
sizeof(RdpdrServerContext));
3670 context->Start = rdpdr_server_start;
3671 context->Stop = rdpdr_server_stop;
3672 context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
3673 context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
3674 context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
3675 context->DriveOpenFile = rdpdr_server_drive_open_file;
3676 context->DriveReadFile = rdpdr_server_drive_read_file;
3677 context->DriveWriteFile = rdpdr_server_drive_write_file;
3678 context->DriveCloseFile = rdpdr_server_drive_close_file;
3679 context->DriveDeleteFile = rdpdr_server_drive_delete_file;
3680 context->DriveRenameFile = rdpdr_server_drive_rename_file;
3681 context->priv = rdpdr_server_private_new();
3686 context->supported = UINT16_MAX;
3690 WINPR_PRAGMA_DIAG_PUSH
3691 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3692 rdpdr_server_context_free(context);
3693 WINPR_PRAGMA_DIAG_POP
3697void rdpdr_server_context_free(RdpdrServerContext* context)
3702 rdpdr_server_private_free(context->priv);
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.