24 #include <freerdp/config.h>
25 #include <freerdp/freerdp.h>
26 #include <freerdp/utils/rdpdr_utils.h>
28 #include <winpr/crt.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
45 struct s_rdpdr_server_private
54 char* ClientComputerName;
58 wListDictionary* IrpList;
59 UINT32 NextCompletionId;
61 wHashTable* devicelist;
69 free(device->DeviceData);
73 static void rdpdr_device_free_h(
void* obj)
76 rdpdr_device_free(other);
79 static UINT32 rdpdr_deviceid_hash(
const void*
id)
82 return *((
const UINT32*)
id);
85 static BOOL rdpdr_device_equal(
const void* v1,
const void* v2)
87 const UINT32* p1 = (
const UINT32*)v1;
88 const UINT32* p2 = (
const UINT32*)v2;
97 static void* rdpdr_device_clone(
const void* val)
109 if (other->DeviceData)
111 tmp->DeviceData = malloc(other->DeviceDataLength);
112 if (!tmp->DeviceData)
114 memcpy(tmp->DeviceData, other->DeviceData, other->DeviceDataLength);
119 rdpdr_device_free(tmp);
123 static RdpdrDevice* rdpdr_get_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
127 return HashTable_GetItemValue(priv->devicelist, &DeviceId);
130 static BOOL rdpdr_remove_device_by_id(RdpdrServerPrivate* priv, UINT32 DeviceId)
132 const RdpdrDevice* device = rdpdr_get_device_by_id(priv, DeviceId);
137 WLog_Print(priv->log, WLOG_WARN,
"[del] Device Id: 0x%08" PRIX32
": no such device",
141 WLog_Print(priv->log, WLOG_DEBUG,
142 "[del] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
143 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
144 return HashTable_Remove(priv->devicelist, &DeviceId);
147 static BOOL rdpdr_add_device(RdpdrServerPrivate* priv,
const RdpdrDevice* device)
150 WINPR_ASSERT(device);
152 WLog_Print(priv->log, WLOG_DEBUG,
153 "[add] Device Name: %s Id: 0x%08" PRIX32
" DataLength: %" PRIu32
"",
154 device->PreferredDosName, device->DeviceId, device->DeviceDataLength);
156 return HashTable_Insert(priv->devicelist, &device->DeviceId, device);
159 static UINT32 g_ClientId = 0;
161 static const WCHAR* rdpdr_read_ustring(wLog* log,
wStream* s,
size_t bytelen)
163 const size_t charlen = (bytelen + 1) /
sizeof(WCHAR);
164 const WCHAR* str = Stream_ConstPointer(s);
165 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, bytelen))
167 if (_wcsnlen(str, charlen) == charlen)
169 WLog_Print(log, WLOG_WARN,
"[rdpdr] unicode string not '\0' terminated");
172 Stream_Seek(s, bytelen);
176 static RDPDR_IRP* rdpdr_server_irp_new(
void)
182 static void rdpdr_server_irp_free(
RDPDR_IRP* irp)
187 static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context,
RDPDR_IRP* irp)
189 WINPR_ASSERT(context);
190 WINPR_ASSERT(context->priv);
191 const uintptr_t key = irp->CompletionId + 1ull;
192 return ListDictionary_Add(context->priv->IrpList, (
void*)key, irp);
195 static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId)
198 WINPR_ASSERT(context);
199 WINPR_ASSERT(context->priv);
201 const uintptr_t key = completionId + 1ull;
202 irp = (
RDPDR_IRP*)ListDictionary_Take(context->priv->IrpList, (
void*)key);
206 static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context,
wStream* s)
211 WINPR_ASSERT(context);
212 WINPR_ASSERT(context->priv);
215 Stream_SealLength(s);
216 const size_t length = Stream_Length(s);
217 WINPR_ASSERT(length <= UINT32_MAX);
218 Stream_SetPosition(s, 0);
220 if (length >= RDPDR_HEADER_LENGTH)
223 Stream_Read_UINT16(s, header.Component);
224 Stream_Read_UINT16(s, header.PacketId);
226 WLog_Print(context->priv->log, WLOG_DEBUG,
227 "sending message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
228 rdpdr_component_string(header.Component), header.Component,
229 rdpdr_packetid_string(header.PacketId), header.PacketId);
231 winpr_HexLogDump(context->priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
232 status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s,
char),
233 (ULONG)length, &written);
234 Stream_Free(s, TRUE);
235 return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
243 static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context)
249 WINPR_ASSERT(context);
250 WINPR_ASSERT(context->priv);
252 header.Component = RDPDR_CTYP_CORE;
253 header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
255 error = IFCALLRESULT(CHANNEL_RC_OK, context->SendServerAnnounce, context);
256 if (error != CHANNEL_RC_OK)
259 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
263 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
264 return CHANNEL_RC_NO_MEMORY;
267 Stream_Write_UINT16(s, header.Component);
268 Stream_Write_UINT16(s, header.PacketId);
269 Stream_Write_UINT16(s, context->priv->VersionMajor);
270 Stream_Write_UINT16(s, context->priv->VersionMinor);
271 Stream_Write_UINT32(s, context->priv->ClientId);
272 return rdpdr_seal_send_free_request(context, s);
280 static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context,
wStream* s,
284 UINT16 VersionMajor = 0;
285 UINT16 VersionMinor = 0;
286 WINPR_ASSERT(context);
287 WINPR_ASSERT(context->priv);
288 WINPR_ASSERT(header);
290 WINPR_UNUSED(header);
292 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
293 return ERROR_INVALID_DATA;
295 Stream_Read_UINT16(s, VersionMajor);
296 Stream_Read_UINT16(s, VersionMinor);
297 Stream_Read_UINT32(s, ClientId);
298 WLog_Print(context->priv->log, WLOG_DEBUG,
299 "Client Announce Response: VersionMajor: 0x%08" PRIX16
" VersionMinor: 0x%04" PRIX16
300 " ClientId: 0x%08" PRIX32
"",
301 VersionMajor, VersionMinor, ClientId);
302 context->priv->ClientId = ClientId;
304 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveAnnounceResponse, context, VersionMajor,
305 VersionMinor, ClientId);
313 static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context,
wStream* s,
316 UINT32 UnicodeFlag = 0;
318 UINT32 ComputerNameLen = 0;
320 WINPR_ASSERT(context);
321 WINPR_ASSERT(context->priv);
323 WINPR_ASSERT(header);
324 WINPR_UNUSED(header);
326 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
327 return ERROR_INVALID_DATA;
329 Stream_Read_UINT32(s, UnicodeFlag);
330 Stream_Read_UINT32(s, CodePage);
331 Stream_Read_UINT32(s, ComputerNameLen);
334 UnicodeFlag = UnicodeFlag & 0x00000001;
337 WLog_Print(context->priv->log, WLOG_WARN,
338 "[MS-RDPEFS] 2.2.2.4 Client Name Request (DR_CORE_CLIENT_NAME_REQ)::CodePage "
339 "must be 0, but is 0x%08" PRIx32,
349 if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
351 WLog_Print(context->priv->log, WLOG_ERROR,
352 "invalid unicode computer name length: %" PRIu32
"", ComputerNameLen);
353 return ERROR_INVALID_DATA;
358 if (ComputerNameLen > 256 || ComputerNameLen < 1)
360 WLog_Print(context->priv->log, WLOG_ERROR,
361 "invalid ascii computer name length: %" PRIu32
"", ComputerNameLen);
362 return ERROR_INVALID_DATA;
366 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, ComputerNameLen))
367 return ERROR_INVALID_DATA;
370 const char* computerName = Stream_ConstPointer(s);
371 if (computerName[ComputerNameLen - 1] || (UnicodeFlag && computerName[ComputerNameLen - 2]))
373 WLog_Print(context->priv->log, WLOG_ERROR,
"computer name must be null terminated");
374 return ERROR_INVALID_DATA;
377 if (context->priv->ClientComputerName)
379 free(context->priv->ClientComputerName);
380 context->priv->ClientComputerName = NULL;
385 context->priv->ClientComputerName =
386 Stream_Read_UTF16_String_As_UTF8(s, ComputerNameLen /
sizeof(WCHAR), NULL);
387 if (!context->priv->ClientComputerName)
389 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to convert client computer name");
390 return ERROR_INVALID_DATA;
395 const char* name = Stream_ConstPointer(s);
396 context->priv->ClientComputerName = _strdup(name);
397 Stream_Seek(s, ComputerNameLen);
399 if (!context->priv->ClientComputerName)
401 WLog_Print(context->priv->log, WLOG_ERROR,
"failed to duplicate client computer name");
402 return CHANNEL_RC_NO_MEMORY;
406 WLog_Print(context->priv->log, WLOG_DEBUG,
"ClientComputerName: %s",
407 context->priv->ClientComputerName);
408 return IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveClientNameRequest, context, ComputerNameLen,
409 context->priv->ClientComputerName);
412 static UINT rdpdr_server_write_capability_set_header_cb(RdpdrServerContext* context,
wStream* s,
415 WINPR_ASSERT(context);
416 WINPR_ASSERT(context->priv);
417 UINT error = rdpdr_write_capset_header(context->priv->log, s, header);
418 if (error != CHANNEL_RC_OK)
421 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, header, 0, NULL);
429 static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context,
wStream* s,
433 UINT32 extraFlags1 = 0;
434 UINT32 extendedPdu = 0;
435 UINT16 VersionMajor = 0;
436 UINT16 VersionMinor = 0;
437 UINT32 SpecialTypeDeviceCap = 0;
438 WINPR_ASSERT(context);
439 WINPR_ASSERT(context->priv);
440 WINPR_ASSERT(header);
442 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
443 return ERROR_INVALID_DATA;
445 Stream_Seek_UINT32(s);
446 Stream_Seek_UINT32(s);
447 Stream_Read_UINT16(s, VersionMajor);
448 Stream_Read_UINT16(s, VersionMinor);
449 Stream_Read_UINT32(s, ioCode1);
450 Stream_Seek_UINT32(s);
451 Stream_Read_UINT32(s, extendedPdu);
452 Stream_Read_UINT32(s, extraFlags1);
453 Stream_Seek_UINT32(s);
455 if (VersionMajor != RDPDR_MAJOR_RDP_VERSION)
457 WLog_Print(context->priv->log, WLOG_ERROR,
"unsupported RDPDR version %" PRIu16
".%" PRIu16,
458 VersionMajor, VersionMinor);
459 return ERROR_INVALID_DATA;
462 switch (VersionMinor)
464 case RDPDR_MINOR_RDP_VERSION_13:
465 case RDPDR_MINOR_RDP_VERSION_6_X:
466 case RDPDR_MINOR_RDP_VERSION_5_2:
467 case RDPDR_MINOR_RDP_VERSION_5_1:
468 case RDPDR_MINOR_RDP_VERSION_5_0:
471 WLog_Print(context->priv->log, WLOG_WARN,
472 "unsupported RDPDR minor version %" PRIu16
".%" PRIu16, VersionMajor,
477 if (header->Version == GENERAL_CAPABILITY_VERSION_02)
479 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
480 return ERROR_INVALID_DATA;
482 Stream_Read_UINT32(s, SpecialTypeDeviceCap);
485 context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
486 return CHANNEL_RC_OK;
494 static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context,
wStream* s)
497 UINT32 extendedPdu = 0;
498 UINT32 extraFlags1 = 0;
499 UINT32 SpecialTypeDeviceCap = 0;
501 GENERAL_CAPABILITY_VERSION_02 };
503 WINPR_ASSERT(context);
504 WINPR_ASSERT(context->priv);
507 ioCode1 |= RDPDR_IRP_MJ_CREATE;
508 ioCode1 |= RDPDR_IRP_MJ_CLEANUP;
509 ioCode1 |= RDPDR_IRP_MJ_CLOSE;
510 ioCode1 |= RDPDR_IRP_MJ_READ;
511 ioCode1 |= RDPDR_IRP_MJ_WRITE;
512 ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS;
513 ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN;
514 ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL;
515 ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION;
516 ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION;
517 ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION;
518 ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION;
519 ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL;
520 ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL;
521 ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY;
522 ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY;
524 extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU;
525 extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS;
527 if (context->priv->UserLoggedOnPdu)
528 extendedPdu |= RDPDR_USER_LOGGEDON_PDU;
531 extraFlags1 |= ENABLE_ASYNCIO;
532 SpecialTypeDeviceCap = 0;
534 UINT error = rdpdr_write_capset_header(context->priv->log, s, &header);
535 if (error != CHANNEL_RC_OK)
538 const BYTE* data = Stream_ConstPointer(s);
539 const size_t start = Stream_GetPosition(s);
540 Stream_Write_UINT32(s, 0);
541 Stream_Write_UINT32(s, 0);
542 Stream_Write_UINT16(s, context->priv->VersionMajor);
543 Stream_Write_UINT16(s, context->priv->VersionMinor);
544 Stream_Write_UINT32(s, ioCode1);
545 Stream_Write_UINT32(s, 0);
546 Stream_Write_UINT32(s, extendedPdu);
547 Stream_Write_UINT32(s, extraFlags1);
550 Stream_Write_UINT32(s, SpecialTypeDeviceCap);
551 const size_t end = Stream_GetPosition(s);
552 return IFCALLRESULT(CHANNEL_RC_OK, context->SendCaps, context, &header, end - start, data);
560 static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context,
wStream* s,
563 WINPR_ASSERT(context);
564 WINPR_ASSERT(context->priv);
566 WINPR_ASSERT(header);
567 WINPR_UNUSED(context);
568 WINPR_UNUSED(header);
571 return CHANNEL_RC_OK;
579 static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context,
wStream* s)
582 PRINT_CAPABILITY_VERSION_01 };
583 WINPR_UNUSED(context);
584 WINPR_ASSERT(context);
585 WINPR_ASSERT(context->priv);
587 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
595 static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context,
wStream* s,
598 WINPR_UNUSED(context);
600 WINPR_UNUSED(header);
601 WINPR_ASSERT(context);
602 WINPR_ASSERT(context->priv);
604 return CHANNEL_RC_OK;
612 static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context,
wStream* s)
615 PORT_CAPABILITY_VERSION_01 };
616 WINPR_UNUSED(context);
617 WINPR_ASSERT(context);
618 WINPR_ASSERT(context->priv);
620 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
628 static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context,
wStream* s,
631 WINPR_ASSERT(context);
632 WINPR_ASSERT(context->priv);
633 WINPR_UNUSED(context);
634 WINPR_UNUSED(header);
637 return CHANNEL_RC_OK;
645 static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context,
wStream* s)
648 DRIVE_CAPABILITY_VERSION_02 };
650 WINPR_ASSERT(context);
651 WINPR_ASSERT(context->priv);
652 WINPR_UNUSED(context);
654 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
662 static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context,
wStream* s,
665 WINPR_ASSERT(context);
666 WINPR_ASSERT(context->priv);
667 WINPR_UNUSED(context);
668 WINPR_UNUSED(header);
671 return CHANNEL_RC_OK;
679 static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context,
wStream* s)
682 SMARTCARD_CAPABILITY_VERSION_01 };
683 WINPR_ASSERT(context);
684 WINPR_ASSERT(context->priv);
686 WINPR_UNUSED(context);
688 return rdpdr_server_write_capability_set_header_cb(context, s, &header);
696 static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
700 UINT16 numCapabilities = 0;
702 WINPR_ASSERT(context);
703 WINPR_ASSERT(context->priv);
705 header.Component = RDPDR_CTYP_CORE;
706 header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
709 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
712 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
713 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
716 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
719 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
722 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
726 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
727 return CHANNEL_RC_NO_MEMORY;
730 Stream_Write_UINT16(s, header.Component);
731 Stream_Write_UINT16(s, header.PacketId);
732 Stream_Write_UINT16(s, numCapabilities);
733 Stream_Write_UINT16(s, 0);
735 if ((error = rdpdr_server_write_general_capability_set(context, s)))
737 WLog_Print(context->priv->log, WLOG_ERROR,
738 "rdpdr_server_write_general_capability_set failed with error %" PRIu32
"!",
743 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
745 if ((error = rdpdr_server_write_drive_capability_set(context, s)))
747 WLog_Print(context->priv->log, WLOG_ERROR,
748 "rdpdr_server_write_drive_capability_set failed with error %" PRIu32
"!",
754 if (((context->supported & RDPDR_DTYP_PARALLEL) != 0) ||
755 ((context->supported & RDPDR_DTYP_SERIAL) != 0))
757 if ((error = rdpdr_server_write_port_capability_set(context, s)))
759 WLog_Print(context->priv->log, WLOG_ERROR,
760 "rdpdr_server_write_port_capability_set failed with error %" PRIu32
"!",
766 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
768 if ((error = rdpdr_server_write_printer_capability_set(context, s)))
770 WLog_Print(context->priv->log, WLOG_ERROR,
771 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
777 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
779 if ((error = rdpdr_server_write_smartcard_capability_set(context, s)))
781 WLog_Print(context->priv->log, WLOG_ERROR,
782 "rdpdr_server_write_printer_capability_set failed with error %" PRIu32
"!",
788 return rdpdr_seal_send_free_request(context, s);
790 Stream_Free(s, TRUE);
799 static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context,
wStream* s,
803 UINT16 numCapabilities = 0;
805 WINPR_ASSERT(context);
806 WINPR_ASSERT(context->priv);
808 WINPR_UNUSED(header);
810 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
811 return ERROR_INVALID_DATA;
813 Stream_Read_UINT16(s, numCapabilities);
814 Stream_Seek_UINT16(s);
817 for (UINT16 i = 0; i < numCapabilities; i++)
820 const size_t start = Stream_GetPosition(s);
822 if ((status = rdpdr_read_capset_header(context->priv->log, s, &capabilityHeader)))
824 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!", status);
828 status = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveCaps, context, &capabilityHeader,
829 Stream_GetRemainingLength(s), Stream_ConstPointer(s));
830 if (status != CHANNEL_RC_OK)
833 caps |= capabilityHeader.CapabilityType;
834 switch (capabilityHeader.CapabilityType)
836 case CAP_GENERAL_TYPE:
838 rdpdr_server_read_general_capability_set(context, s, &capabilityHeader)))
840 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
847 case CAP_PRINTER_TYPE:
849 rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader)))
851 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
859 if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader)))
861 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
870 rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader)))
872 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
879 case CAP_SMARTCARD_TYPE:
881 rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader)))
883 WLog_Print(context->priv->log, WLOG_ERROR,
"failed with error %" PRIu32
"!",
891 WLog_Print(context->priv->log, WLOG_WARN,
"Unknown capabilityType %" PRIu16
"",
892 capabilityHeader.CapabilityType);
893 Stream_Seek(s, capabilityHeader.CapabilityLength);
894 return ERROR_INVALID_DATA;
897 for (UINT16 x = 0; x < 16; x++)
899 const UINT16 mask = (UINT16)(1 << x);
900 if (((caps & mask) != 0) && ((context->supported & mask) == 0))
902 WLog_Print(context->priv->log, WLOG_WARN,
903 "client sent capability %s we did not announce!",
909 if ((caps & mask) == 0)
910 context->supported &= ~mask;
913 const size_t end = Stream_GetPosition(s);
914 const size_t diff = end - start;
915 if (diff != capabilityHeader.CapabilityLength + RDPDR_CAPABILITY_HEADER_LENGTH)
917 WLog_Print(context->priv->log, WLOG_WARN,
918 "{capability %s[0x%04" PRIx16
"]} processed %" PRIuz
919 " bytes, but expected to be %" PRIu16,
920 rdpdr_cap_type_string(capabilityHeader.CapabilityType),
921 capabilityHeader.CapabilityType, diff, capabilityHeader.CapabilityLength);
925 return CHANNEL_RC_OK;
933 static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
938 WINPR_ASSERT(context);
939 WINPR_ASSERT(context->priv);
941 header.Component = RDPDR_CTYP_CORE;
942 header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
943 s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
947 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
948 return CHANNEL_RC_NO_MEMORY;
951 Stream_Write_UINT16(s, header.Component);
952 Stream_Write_UINT16(s, header.PacketId);
953 Stream_Write_UINT16(s, context->priv->VersionMajor);
954 Stream_Write_UINT16(s, context->priv->VersionMinor);
955 Stream_Write_UINT32(s, context->priv->ClientId);
956 return rdpdr_seal_send_free_request(context, s);
964 static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context,
968 UINT32 DeviceCount = 0;
970 WINPR_ASSERT(context);
971 WINPR_ASSERT(context->priv);
973 WINPR_UNUSED(header);
975 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
976 return ERROR_INVALID_DATA;
978 Stream_Read_UINT32(s, DeviceCount);
979 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
981 for (UINT32 i = 0; i < DeviceCount; i++)
986 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
987 return ERROR_INVALID_DATA;
989 Stream_Read_UINT32(s, device.DeviceType);
990 Stream_Read_UINT32(s, device.DeviceId);
991 Stream_Read(s, device.PreferredDosName, 8);
992 Stream_Read_UINT32(s, device.DeviceDataLength);
993 device.DeviceData = Stream_Pointer(s);
995 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, device.DeviceDataLength))
996 return ERROR_INVALID_DATA;
998 if (!rdpdr_add_device(context->priv, &device))
999 return ERROR_INTERNAL_ERROR;
1001 error = IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceAnnounce, context, &device);
1002 if (error != CHANNEL_RC_OK)
1005 switch (device.DeviceType)
1007 case RDPDR_DTYP_FILESYSTEM:
1008 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1009 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveCreate, context, &device);
1012 case RDPDR_DTYP_PRINT:
1013 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1014 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterCreate, context, &device);
1017 case RDPDR_DTYP_SERIAL:
1018 if (device.DeviceDataLength != 0)
1020 WLog_Print(context->priv->log, WLOG_WARN,
1021 "[rdpdr] RDPDR_DTYP_SERIAL::DeviceDataLength != 0 [%" PRIu32
"]",
1022 device.DeviceDataLength);
1023 error = ERROR_INVALID_DATA;
1025 else if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1027 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortCreate, context, &device);
1030 case RDPDR_DTYP_PARALLEL:
1031 if (device.DeviceDataLength != 0)
1033 WLog_Print(context->priv->log, WLOG_WARN,
1034 "[rdpdr] RDPDR_DTYP_PARALLEL::DeviceDataLength != 0 [%" PRIu32
"]",
1035 device.DeviceDataLength);
1036 error = ERROR_INVALID_DATA;
1038 else if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1039 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortCreate, context,
1043 case RDPDR_DTYP_SMARTCARD:
1044 if (device.DeviceDataLength != 0)
1046 WLog_Print(context->priv->log, WLOG_WARN,
1047 "[rdpdr] RDPDR_DTYP_SMARTCARD::DeviceDataLength != 0 [%" PRIu32
"]",
1048 device.DeviceDataLength);
1049 error = ERROR_INVALID_DATA;
1051 else if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1053 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardCreate, context, &device);
1057 WLog_Print(context->priv->log, WLOG_WARN,
1058 "[MS-RDPEFS] 2.2.2.9 Client Device List Announce Request "
1059 "(DR_CORE_DEVICELIST_ANNOUNCE_REQ) unknown device type %04" PRIx16
1060 " at position %" PRIu32,
1061 device.DeviceType, i);
1062 error = ERROR_INVALID_DATA;
1066 if (error != CHANNEL_RC_OK)
1069 Stream_Seek(s, device.DeviceDataLength);
1072 return CHANNEL_RC_OK;
1080 static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context,
wStream* s,
1083 UINT32 DeviceCount = 0;
1084 UINT32 DeviceType = 0;
1085 UINT32 DeviceId = 0;
1086 WINPR_ASSERT(context);
1087 WINPR_ASSERT(context->priv);
1089 WINPR_UNUSED(header);
1091 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1092 return ERROR_INVALID_DATA;
1094 Stream_Read_UINT32(s, DeviceCount);
1095 WLog_Print(context->priv->log, WLOG_DEBUG,
"DeviceCount: %" PRIu32
"", DeviceCount);
1097 for (UINT32 i = 0; i < DeviceCount; i++)
1102 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1103 return ERROR_INVALID_DATA;
1105 Stream_Read_UINT32(s, DeviceId);
1106 device = rdpdr_get_device_by_id(context->priv, DeviceId);
1107 WLog_Print(context->priv->log, WLOG_DEBUG,
"Device %" PRIu32
" Id: 0x%08" PRIX32
"", i,
1111 DeviceType = device->DeviceType;
1114 IFCALLRESULT(CHANNEL_RC_OK, context->ReceiveDeviceRemove, context, DeviceId, device);
1115 if (error != CHANNEL_RC_OK)
1120 case RDPDR_DTYP_FILESYSTEM:
1121 if ((context->supported & RDPDR_DTYP_FILESYSTEM) != 0)
1122 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnDriveDelete, context, DeviceId);
1125 case RDPDR_DTYP_PRINT:
1126 if ((context->supported & RDPDR_DTYP_PRINT) != 0)
1128 IFCALLRESULT(CHANNEL_RC_OK, context->OnPrinterDelete, context, DeviceId);
1131 case RDPDR_DTYP_SERIAL:
1132 if ((context->supported & RDPDR_DTYP_SERIAL) != 0)
1134 IFCALLRESULT(CHANNEL_RC_OK, context->OnSerialPortDelete, context, DeviceId);
1137 case RDPDR_DTYP_PARALLEL:
1138 if ((context->supported & RDPDR_DTYP_PARALLEL) != 0)
1139 error = IFCALLRESULT(CHANNEL_RC_OK, context->OnParallelPortDelete, context,
1143 case RDPDR_DTYP_SMARTCARD:
1144 if ((context->supported & RDPDR_DTYP_SMARTCARD) != 0)
1146 IFCALLRESULT(CHANNEL_RC_OK, context->OnSmartcardDelete, context, DeviceId);
1153 if (error != CHANNEL_RC_OK)
1156 if (!rdpdr_remove_device_by_id(context->priv, DeviceId))
1157 return ERROR_INVALID_DATA;
1160 return CHANNEL_RC_OK;
1163 static UINT rdpdr_server_receive_io_create_request(RdpdrServerContext* context,
wStream* s,
1164 UINT32 DeviceId, UINT32 FileId,
1165 UINT32 CompletionId)
1167 const WCHAR* path = NULL;
1168 UINT32 DesiredAccess = 0;
1169 UINT32 AllocationSize = 0;
1170 UINT32 FileAttributes = 0;
1171 UINT32 SharedAccess = 0;
1172 UINT32 CreateDisposition = 0;
1173 UINT32 CreateOptions = 0;
1174 UINT32 PathLength = 0;
1176 WINPR_ASSERT(context);
1177 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1178 return ERROR_INVALID_DATA;
1180 Stream_Read_UINT32(s, DesiredAccess);
1181 Stream_Read_UINT32(s, AllocationSize);
1182 Stream_Read_UINT32(s, FileAttributes);
1183 Stream_Read_UINT32(s, SharedAccess);
1184 Stream_Read_UINT32(s, CreateDisposition);
1185 Stream_Read_UINT32(s, CreateOptions);
1186 Stream_Read_UINT32(s, PathLength);
1188 path = rdpdr_read_ustring(context->priv->log, s, PathLength);
1189 if (!path && (PathLength > 0))
1190 return ERROR_INVALID_DATA;
1192 WLog_Print(context->priv->log, WLOG_WARN,
1193 "[MS-RDPEFS] 2.2.1.4.1 Device Create Request (DR_CREATE_REQ) not implemented");
1194 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1196 return CHANNEL_RC_OK;
1199 static UINT rdpdr_server_receive_io_close_request(RdpdrServerContext* context,
wStream* s,
1200 UINT32 DeviceId, UINT32 FileId,
1201 UINT32 CompletionId)
1203 WINPR_ASSERT(context);
1204 WINPR_ASSERT(context->priv);
1206 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1207 return ERROR_INVALID_DATA;
1211 WLog_Print(context->priv->log, WLOG_WARN,
1212 "[MS-RDPEFS] 2.2.1.4.2 Device Close Request (DR_CLOSE_REQ) not implemented");
1213 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1215 return CHANNEL_RC_OK;
1218 static UINT rdpdr_server_receive_io_read_request(RdpdrServerContext* context,
wStream* s,
1219 UINT32 DeviceId, UINT32 FileId,
1220 UINT32 CompletionId)
1225 WINPR_ASSERT(context);
1226 WINPR_ASSERT(context->priv);
1227 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1228 return ERROR_INVALID_DATA;
1230 Stream_Read_UINT32(s, Length);
1231 Stream_Read_UINT64(s, Offset);
1234 WLog_Print(context->priv->log, WLOG_WARN,
1235 "[MS-RDPEFS] 2.2.1.4.3 Device Read Request (DR_READ_REQ) not implemented");
1236 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1238 return CHANNEL_RC_OK;
1241 static UINT rdpdr_server_receive_io_write_request(RdpdrServerContext* context,
wStream* s,
1242 UINT32 DeviceId, UINT32 FileId,
1243 UINT32 CompletionId)
1248 WINPR_ASSERT(context);
1249 WINPR_ASSERT(context->priv);
1251 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1252 return ERROR_INVALID_DATA;
1254 Stream_Read_UINT32(s, Length);
1255 Stream_Read_UINT64(s, Offset);
1258 const BYTE* data = Stream_ConstPointer(s);
1259 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1260 return ERROR_INVALID_DATA;
1261 Stream_Seek(s, Length);
1263 WLog_Print(context->priv->log, WLOG_WARN,
1264 "[MS-RDPEFS] 2.2.1.4.4 Device Write Request (DR_WRITE_REQ) not implemented");
1265 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", data);
1267 return CHANNEL_RC_OK;
1270 static UINT rdpdr_server_receive_io_device_control_request(RdpdrServerContext* context,
wStream* s,
1271 UINT32 DeviceId, UINT32 FileId,
1272 UINT32 CompletionId)
1274 UINT32 OutputBufferLength = 0;
1275 UINT32 InputBufferLength = 0;
1276 UINT32 IoControlCode = 0;
1278 WINPR_ASSERT(context);
1279 WINPR_ASSERT(context->priv);
1281 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1282 return ERROR_INVALID_DATA;
1284 Stream_Read_UINT32(s, OutputBufferLength);
1285 Stream_Read_UINT32(s, InputBufferLength);
1286 Stream_Read_UINT32(s, IoControlCode);
1289 const BYTE* InputBuffer = Stream_ConstPointer(s);
1290 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, InputBufferLength))
1291 return ERROR_INVALID_DATA;
1292 Stream_Seek(s, InputBufferLength);
1294 WLog_Print(context->priv->log, WLOG_WARN,
1295 "[MS-RDPEFS] 2.2.1.4.5 Device Control Request (DR_CONTROL_REQ) not implemented");
1296 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", InputBuffer);
1298 return CHANNEL_RC_OK;
1301 static UINT rdpdr_server_receive_io_query_volume_information_request(RdpdrServerContext* context,
1304 UINT32 CompletionId)
1306 UINT32 FsInformationClass = 0;
1309 WINPR_ASSERT(context);
1310 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1311 return ERROR_INVALID_DATA;
1313 Stream_Read_UINT32(s, FsInformationClass);
1314 Stream_Read_UINT32(s, Length);
1317 const BYTE* QueryVolumeBuffer = Stream_ConstPointer(s);
1318 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1319 return ERROR_INVALID_DATA;
1320 Stream_Seek(s, Length);
1322 WLog_Print(context->priv->log, WLOG_WARN,
1323 "[MS-RDPEFS] 2.2.3.3.6 Server Drive Query Volume Information Request "
1324 "(DR_DRIVE_QUERY_VOLUME_INFORMATION_REQ) not implemented");
1325 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", QueryVolumeBuffer);
1327 return CHANNEL_RC_OK;
1330 static UINT rdpdr_server_receive_io_set_volume_information_request(RdpdrServerContext* context,
1333 UINT32 CompletionId)
1335 UINT32 FsInformationClass = 0;
1338 WINPR_ASSERT(context);
1339 WINPR_ASSERT(context->priv);
1341 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1342 return ERROR_INVALID_DATA;
1344 Stream_Read_UINT32(s, FsInformationClass);
1345 Stream_Read_UINT32(s, Length);
1348 const BYTE* SetVolumeBuffer = Stream_ConstPointer(s);
1349 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1350 return ERROR_INVALID_DATA;
1351 Stream_Seek(s, Length);
1353 WLog_Print(context->priv->log, WLOG_WARN,
1354 "[MS-RDPEFS] 2.2.3.3.7 Server Drive Set Volume Information Request "
1355 "(DR_DRIVE_SET_VOLUME_INFORMATION_REQ) not implemented");
1356 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", SetVolumeBuffer);
1358 return CHANNEL_RC_OK;
1361 static UINT rdpdr_server_receive_io_query_information_request(RdpdrServerContext* context,
1363 UINT32 FileId, UINT32 CompletionId)
1365 UINT32 FsInformationClass = 0;
1368 WINPR_ASSERT(context);
1369 WINPR_ASSERT(context->priv);
1371 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1372 return ERROR_INVALID_DATA;
1374 Stream_Read_UINT32(s, FsInformationClass);
1375 Stream_Read_UINT32(s, Length);
1378 const BYTE* QueryBuffer = Stream_ConstPointer(s);
1379 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1380 return ERROR_INVALID_DATA;
1381 Stream_Seek(s, Length);
1383 WLog_Print(context->priv->log, WLOG_WARN,
1384 "[MS-RDPEFS] 2.2.3.3.8 Server Drive Query Information Request "
1385 "(DR_DRIVE_QUERY_INFORMATION_REQ) not implemented");
1386 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", QueryBuffer);
1388 return CHANNEL_RC_OK;
1391 static UINT rdpdr_server_receive_io_set_information_request(RdpdrServerContext* context,
wStream* s,
1392 UINT32 DeviceId, UINT32 FileId,
1393 UINT32 CompletionId)
1395 UINT32 FsInformationClass = 0;
1398 WINPR_ASSERT(context);
1399 WINPR_ASSERT(context->priv);
1401 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1402 return ERROR_INVALID_DATA;
1404 Stream_Read_UINT32(s, FsInformationClass);
1405 Stream_Read_UINT32(s, Length);
1408 const BYTE* SetBuffer = Stream_ConstPointer(s);
1409 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, Length))
1410 return ERROR_INVALID_DATA;
1411 Stream_Seek(s, Length);
1413 WLog_Print(context->priv->log, WLOG_WARN,
1414 "[MS-RDPEFS] 2.2.3.3.9 Server Drive Set Information Request "
1415 "(DR_DRIVE_SET_INFORMATION_REQ) not implemented");
1416 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", SetBuffer);
1418 return CHANNEL_RC_OK;
1421 static UINT rdpdr_server_receive_io_query_directory_request(RdpdrServerContext* context,
wStream* s,
1422 UINT32 DeviceId, UINT32 FileId,
1423 UINT32 CompletionId)
1425 BYTE InitialQuery = 0;
1426 UINT32 FsInformationClass = 0;
1427 UINT32 PathLength = 0;
1428 const WCHAR* Path = NULL;
1430 WINPR_ASSERT(context);
1431 WINPR_ASSERT(context->priv);
1433 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1434 return ERROR_INVALID_DATA;
1436 Stream_Read_UINT32(s, FsInformationClass);
1437 Stream_Read_UINT8(s, InitialQuery);
1438 Stream_Read_UINT32(s, PathLength);
1441 Path = rdpdr_read_ustring(context->priv->log, s, PathLength);
1442 if (!Path && (PathLength > 0))
1443 return ERROR_INVALID_DATA;
1445 WLog_Print(context->priv->log, WLOG_WARN,
1446 "[MS-RDPEFS] 2.2.3.3.10 Server Drive Query Directory Request "
1447 "(DR_DRIVE_QUERY_DIRECTORY_REQ) not implemented");
1448 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1450 return CHANNEL_RC_OK;
1453 static UINT rdpdr_server_receive_io_change_directory_request(RdpdrServerContext* context,
1455 UINT32 FileId, UINT32 CompletionId)
1458 UINT32 CompletionFilter = 0;
1460 WINPR_ASSERT(context);
1461 WINPR_ASSERT(context->priv);
1463 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1464 return ERROR_INVALID_DATA;
1466 Stream_Read_UINT8(s, WatchTree);
1467 Stream_Read_UINT32(s, CompletionFilter);
1470 WLog_Print(context->priv->log, WLOG_WARN,
1471 "[MS-RDPEFS] 2.2.3.3.11 Server Drive NotifyChange Directory Request "
1472 "(DR_DRIVE_NOTIFY_CHANGE_DIRECTORY_REQ) not implemented");
1473 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1475 return CHANNEL_RC_OK;
1478 static UINT rdpdr_server_receive_io_directory_control_request(RdpdrServerContext* context,
1480 UINT32 FileId, UINT32 CompletionId,
1481 UINT32 MinorFunction)
1483 WINPR_ASSERT(context);
1484 WINPR_ASSERT(context->priv);
1486 switch (MinorFunction)
1488 case IRP_MN_QUERY_DIRECTORY:
1489 return rdpdr_server_receive_io_query_directory_request(context, s, DeviceId, FileId,
1491 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
1492 return rdpdr_server_receive_io_change_directory_request(context, s, DeviceId, FileId,
1495 WLog_Print(context->priv->log, WLOG_WARN,
1496 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) "
1497 "MajorFunction=%s, MinorFunction=%08" PRIx32
" is not supported",
1498 rdpdr_irp_string(IRP_MJ_DIRECTORY_CONTROL), MinorFunction);
1499 return ERROR_INVALID_DATA;
1503 static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* context,
wStream* s,
1504 UINT32 DeviceId, UINT32 FileId,
1505 UINT32 CompletionId)
1507 UINT32 Operation = 0;
1509 UINT32 NumLocks = 0;
1511 WINPR_ASSERT(context);
1512 WINPR_ASSERT(context->priv);
1514 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 32))
1515 return ERROR_INVALID_DATA;
1517 Stream_Read_UINT32(s, Operation);
1518 Stream_Read_UINT32(s, Lock);
1519 Stream_Read_UINT32(s, NumLocks);
1524 for (UINT32 x = 0; x < NumLocks; x++)
1529 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 16))
1530 return ERROR_INVALID_DATA;
1532 Stream_Read_UINT64(s, Length);
1533 Stream_Read_UINT64(s, Offset);
1536 WLog_Print(context->priv->log, WLOG_WARN,
1537 "[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
1538 "[Lock=0x%08" PRIx32
"]"
1541 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1543 return CHANNEL_RC_OK;
1546 static UINT rdpdr_server_receive_device_io_request(RdpdrServerContext* context,
wStream* s,
1549 UINT32 DeviceId = 0;
1551 UINT32 CompletionId = 0;
1552 UINT32 MajorFunction = 0;
1553 UINT32 MinorFunction = 0;
1555 WINPR_ASSERT(context);
1556 WINPR_ASSERT(context->priv);
1557 WINPR_ASSERT(header);
1559 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 20))
1560 return ERROR_INVALID_DATA;
1562 Stream_Read_UINT32(s, DeviceId);
1563 Stream_Read_UINT32(s, FileId);
1564 Stream_Read_UINT32(s, CompletionId);
1565 Stream_Read_UINT32(s, MajorFunction);
1566 Stream_Read_UINT32(s, MinorFunction);
1567 if ((MinorFunction != 0) && (MajorFunction != IRP_MJ_DIRECTORY_CONTROL))
1568 WLog_Print(context->priv->log, WLOG_WARN,
1569 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) MajorFunction=%s, "
1570 "MinorFunction=0x%08" PRIx32
" != 0",
1571 rdpdr_irp_string(MajorFunction), MinorFunction);
1573 switch (MajorFunction)
1576 return rdpdr_server_receive_io_create_request(context, s, DeviceId, FileId,
1579 return rdpdr_server_receive_io_close_request(context, s, DeviceId, FileId,
1582 return rdpdr_server_receive_io_read_request(context, s, DeviceId, FileId, CompletionId);
1584 return rdpdr_server_receive_io_write_request(context, s, DeviceId, FileId,
1586 case IRP_MJ_DEVICE_CONTROL:
1587 return rdpdr_server_receive_io_device_control_request(context, s, DeviceId, FileId,
1589 case IRP_MJ_QUERY_VOLUME_INFORMATION:
1590 return rdpdr_server_receive_io_query_volume_information_request(context, s, DeviceId,
1591 FileId, CompletionId);
1592 case IRP_MJ_QUERY_INFORMATION:
1593 return rdpdr_server_receive_io_query_information_request(context, s, DeviceId, FileId,
1595 case IRP_MJ_SET_INFORMATION:
1596 return rdpdr_server_receive_io_set_information_request(context, s, DeviceId, FileId,
1598 case IRP_MJ_DIRECTORY_CONTROL:
1599 return rdpdr_server_receive_io_directory_control_request(context, s, DeviceId, FileId,
1600 CompletionId, MinorFunction);
1601 case IRP_MJ_LOCK_CONTROL:
1602 return rdpdr_server_receive_io_lock_control_request(context, s, DeviceId, FileId,
1606 context->priv->log, WLOG_WARN,
1607 "[MS-RDPEFS] 2.2.1.4 Device I/O Request (DR_DEVICE_IOREQUEST) not implemented");
1608 WLog_Print(context->priv->log, WLOG_WARN,
1609 "got DeviceId=0x%08" PRIx32
", FileId=0x%08" PRIx32
1610 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
1611 ", MinorFunction=0x%08" PRIx32,
1612 DeviceId, FileId, CompletionId, MajorFunction, MinorFunction);
1613 return ERROR_INVALID_DATA;
1622 static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context,
wStream* s,
1625 UINT32 deviceId = 0;
1626 UINT32 completionId = 0;
1627 UINT32 ioStatus = 0;
1629 UINT error = CHANNEL_RC_OK;
1630 WINPR_ASSERT(context);
1631 WINPR_ASSERT(context->priv);
1633 WINPR_ASSERT(header);
1635 WINPR_UNUSED(header);
1637 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 12))
1638 return ERROR_INVALID_DATA;
1640 Stream_Read_UINT32(s, deviceId);
1641 Stream_Read_UINT32(s, completionId);
1642 Stream_Read_UINT32(s, ioStatus);
1643 WLog_Print(context->priv->log, WLOG_DEBUG,
1644 "deviceId=%" PRIu32
", completionId=0x%" PRIx32
", ioStatus=0x%" PRIx32
"", deviceId,
1645 completionId, ioStatus);
1646 irp = rdpdr_server_dequeue_irp(context, completionId);
1650 WLog_Print(context->priv->log, WLOG_ERROR,
"IRP not found for completionId=0x%" PRIx32
"",
1652 return CHANNEL_RC_OK;
1658 error = (*irp->Callback)(context, s, irp, deviceId, completionId, ioStatus);
1669 static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
1674 WINPR_ASSERT(context);
1675 WINPR_ASSERT(context->priv);
1677 header.Component = RDPDR_CTYP_CORE;
1678 header.PacketId = PAKID_CORE_USER_LOGGEDON;
1679 s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
1683 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
1684 return CHANNEL_RC_NO_MEMORY;
1687 Stream_Write_UINT16(s, header.Component);
1688 Stream_Write_UINT16(s, header.PacketId);
1689 return rdpdr_seal_send_free_request(context, s);
1692 static UINT rdpdr_server_receive_prn_cache_add_printer(RdpdrServerContext* context,
wStream* s)
1694 char PortDosName[9] = { 0 };
1695 UINT32 PnPNameLen = 0;
1696 UINT32 DriverNameLen = 0;
1697 UINT32 PrinterNameLen = 0;
1698 UINT32 CachedFieldsLen = 0;
1699 const WCHAR* PnPName = NULL;
1700 const WCHAR* DriverName = NULL;
1701 const WCHAR* PrinterName = NULL;
1703 WINPR_ASSERT(context);
1704 WINPR_ASSERT(context->priv);
1706 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 24))
1707 return ERROR_INVALID_DATA;
1709 Stream_Read(s, PortDosName, 8);
1710 Stream_Read_UINT32(s, PnPNameLen);
1711 Stream_Read_UINT32(s, DriverNameLen);
1712 Stream_Read_UINT32(s, PrinterNameLen);
1713 Stream_Read_UINT32(s, CachedFieldsLen);
1715 PnPName = rdpdr_read_ustring(context->priv->log, s, PnPNameLen);
1716 if (!PnPName && (PnPNameLen > 0))
1717 return ERROR_INVALID_DATA;
1718 DriverName = rdpdr_read_ustring(context->priv->log, s, DriverNameLen);
1719 if (!DriverName && (DriverNameLen > 0))
1720 return ERROR_INVALID_DATA;
1721 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1722 if (!PrinterName && (PrinterNameLen > 0))
1723 return ERROR_INVALID_DATA;
1725 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1726 return ERROR_INVALID_DATA;
1727 Stream_Seek(s, CachedFieldsLen);
1729 WLog_Print(context->priv->log, WLOG_WARN,
1730 "[MS-RDPEPC] 2.2.2.3 Add Printer Cachedata (DR_PRN_ADD_CACHEDATA) not implemented");
1731 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1732 return CHANNEL_RC_OK;
1735 static UINT rdpdr_server_receive_prn_cache_update_printer(RdpdrServerContext* context,
wStream* s)
1737 UINT32 PrinterNameLen = 0;
1738 UINT32 CachedFieldsLen = 0;
1739 const WCHAR* PrinterName = NULL;
1741 WINPR_ASSERT(context);
1743 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1744 return ERROR_INVALID_DATA;
1746 Stream_Read_UINT32(s, PrinterNameLen);
1747 Stream_Read_UINT32(s, CachedFieldsLen);
1749 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1750 if (!PrinterName && (PrinterNameLen > 0))
1751 return ERROR_INVALID_DATA;
1753 const BYTE* config = Stream_ConstPointer(s);
1754 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, CachedFieldsLen))
1755 return ERROR_INVALID_DATA;
1756 Stream_Seek(s, CachedFieldsLen);
1759 context->priv->log, WLOG_WARN,
1760 "[MS-RDPEPC] 2.2.2.4 Update Printer Cachedata (DR_PRN_UPDATE_CACHEDATA) not implemented");
1761 WLog_Print(context->priv->log, WLOG_WARN,
"TODO: parse %p", config);
1762 return CHANNEL_RC_OK;
1765 static UINT rdpdr_server_receive_prn_cache_delete_printer(RdpdrServerContext* context,
wStream* s)
1767 UINT32 PrinterNameLen = 0;
1768 const WCHAR* PrinterName = NULL;
1770 WINPR_ASSERT(context);
1771 WINPR_ASSERT(context->priv);
1773 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1774 return ERROR_INVALID_DATA;
1776 Stream_Read_UINT32(s, PrinterNameLen);
1778 PrinterName = rdpdr_read_ustring(context->priv->log, s, PrinterNameLen);
1779 if (!PrinterName && (PrinterNameLen > 0))
1780 return ERROR_INVALID_DATA;
1783 context->priv->log, WLOG_WARN,
1784 "[MS-RDPEPC] 2.2.2.5 Delete Printer Cachedata (DR_PRN_DELETE_CACHEDATA) not implemented");
1785 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1786 return CHANNEL_RC_OK;
1789 static UINT rdpdr_server_receive_prn_cache_rename_cachedata(RdpdrServerContext* context,
wStream* s)
1791 UINT32 OldPrinterNameLen = 0;
1792 UINT32 NewPrinterNameLen = 0;
1793 const WCHAR* OldPrinterName = NULL;
1794 const WCHAR* NewPrinterName = NULL;
1796 WINPR_ASSERT(context);
1797 WINPR_ASSERT(context->priv);
1799 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1800 return ERROR_INVALID_DATA;
1802 Stream_Read_UINT32(s, OldPrinterNameLen);
1803 Stream_Read_UINT32(s, NewPrinterNameLen);
1805 OldPrinterName = rdpdr_read_ustring(context->priv->log, s, OldPrinterNameLen);
1806 if (!OldPrinterName && (OldPrinterNameLen > 0))
1807 return ERROR_INVALID_DATA;
1808 NewPrinterName = rdpdr_read_ustring(context->priv->log, s, NewPrinterNameLen);
1809 if (!NewPrinterName && (NewPrinterNameLen > 0))
1810 return ERROR_INVALID_DATA;
1813 context->priv->log, WLOG_WARN,
1814 "[MS-RDPEPC] 2.2.2.6 Rename Printer Cachedata (DR_PRN_RENAME_CACHEDATA) not implemented");
1815 WLog_Print(context->priv->log, WLOG_WARN,
"TODO");
1816 return CHANNEL_RC_OK;
1819 static UINT rdpdr_server_receive_prn_cache_data_request(RdpdrServerContext* context,
wStream* s,
1824 WINPR_ASSERT(context);
1825 WINPR_ASSERT(context->priv);
1826 WINPR_ASSERT(header);
1828 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
1829 return ERROR_INVALID_DATA;
1831 Stream_Read_UINT32(s, EventId);
1834 case RDPDR_ADD_PRINTER_EVENT:
1835 return rdpdr_server_receive_prn_cache_add_printer(context, s);
1836 case RDPDR_UPDATE_PRINTER_EVENT:
1837 return rdpdr_server_receive_prn_cache_update_printer(context, s);
1838 case RDPDR_DELETE_PRINTER_EVENT:
1839 return rdpdr_server_receive_prn_cache_delete_printer(context, s);
1840 case RDPDR_RENAME_PRINTER_EVENT:
1841 return rdpdr_server_receive_prn_cache_rename_cachedata(context, s);
1843 WLog_Print(context->priv->log, WLOG_WARN,
1844 "[MS-RDPEPC] PAKID_PRN_CACHE_DATA unknown EventId=0x%08" PRIx32, EventId);
1845 return ERROR_INVALID_DATA;
1849 static UINT rdpdr_server_receive_prn_using_xps_request(RdpdrServerContext* context,
wStream* s,
1852 UINT32 PrinterId = 0;
1855 WINPR_ASSERT(context);
1856 WINPR_ASSERT(context->priv);
1857 WINPR_ASSERT(header);
1859 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 8))
1860 return ERROR_INVALID_DATA;
1862 Stream_Read_UINT32(s, PrinterId);
1863 Stream_Read_UINT32(s, Flags);
1866 context->priv->log, WLOG_WARN,
1867 "[MS-RDPEPC] 2.2.2.2 Server Printer Set XPS Mode (DR_PRN_USING_XPS) not implemented");
1868 WLog_Print(context->priv->log, WLOG_WARN,
"PrinterId=0x%08" PRIx32
", Flags=0x%08" PRIx32,
1870 return CHANNEL_RC_OK;
1878 static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context,
wStream* s,
1881 UINT error = ERROR_INVALID_DATA;
1882 WINPR_ASSERT(context);
1883 WINPR_ASSERT(context->priv);
1885 WINPR_ASSERT(header);
1887 WLog_Print(context->priv->log, WLOG_DEBUG,
1888 "receiving message {Component %s[%04" PRIx16
"], PacketId %s[%04" PRIx16
"]",
1889 rdpdr_component_string(header->Component), header->Component,
1890 rdpdr_packetid_string(header->PacketId), header->PacketId);
1892 if (header->Component == RDPDR_CTYP_CORE)
1894 switch (header->PacketId)
1896 case PAKID_CORE_SERVER_ANNOUNCE:
1897 WLog_Print(context->priv->log, WLOG_ERROR,
1898 "[MS-RDPEFS] 2.2.2.2 Server Announce Request "
1899 "(DR_CORE_SERVER_ANNOUNCE_REQ) must not be sent by a client!");
1902 case PAKID_CORE_CLIENTID_CONFIRM:
1903 error = rdpdr_server_receive_announce_response(context, s, header);
1906 case PAKID_CORE_CLIENT_NAME:
1907 error = rdpdr_server_receive_client_name_request(context, s, header);
1908 if (error == CHANNEL_RC_OK)
1909 error = rdpdr_server_send_core_capability_request(context);
1910 if (error == CHANNEL_RC_OK)
1911 error = rdpdr_server_send_client_id_confirm(context);
1914 case PAKID_CORE_USER_LOGGEDON:
1915 WLog_Print(context->priv->log, WLOG_ERROR,
1916 "[MS-RDPEFS] 2.2.2.5 Server User Logged On (DR_CORE_USER_LOGGEDON) "
1917 "must not be sent by a client!");
1920 case PAKID_CORE_SERVER_CAPABILITY:
1921 WLog_Print(context->priv->log, WLOG_ERROR,
1922 "[MS-RDPEFS] 2.2.2.7 Server Core Capability Request "
1923 "(DR_CORE_CAPABILITY_REQ) must not be sent by a client!");
1926 case PAKID_CORE_CLIENT_CAPABILITY:
1927 error = rdpdr_server_receive_core_capability_response(context, s, header);
1928 if (error == CHANNEL_RC_OK)
1930 if (context->priv->UserLoggedOnPdu)
1931 error = rdpdr_server_send_user_logged_on(context);
1936 case PAKID_CORE_DEVICELIST_ANNOUNCE:
1937 error = rdpdr_server_receive_device_list_announce_request(context, s, header);
1940 case PAKID_CORE_DEVICELIST_REMOVE:
1941 error = rdpdr_server_receive_device_list_remove_request(context, s, header);
1944 case PAKID_CORE_DEVICE_REPLY:
1945 WLog_Print(context->priv->log, WLOG_ERROR,
1946 "[MS-RDPEFS] 2.2.2.1 Server Device Announce Response "
1947 "(DR_CORE_DEVICE_ANNOUNCE_RSP) must not be sent by a client!");
1950 case PAKID_CORE_DEVICE_IOREQUEST:
1951 error = rdpdr_server_receive_device_io_request(context, s, header);
1954 case PAKID_CORE_DEVICE_IOCOMPLETION:
1955 error = rdpdr_server_receive_device_io_completion(context, s, header);
1959 WLog_Print(context->priv->log, WLOG_WARN,
1960 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
1961 rdpdr_component_string(header->Component), header->Component,
1962 rdpdr_packetid_string(header->PacketId));
1966 else if (header->Component == RDPDR_CTYP_PRN)
1968 switch (header->PacketId)
1970 case PAKID_PRN_CACHE_DATA:
1971 error = rdpdr_server_receive_prn_cache_data_request(context, s, header);
1974 case PAKID_PRN_USING_XPS:
1975 error = rdpdr_server_receive_prn_using_xps_request(context, s, header);
1979 WLog_Print(context->priv->log, WLOG_WARN,
1980 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
1981 rdpdr_component_string(header->Component), header->Component,
1982 rdpdr_packetid_string(header->PacketId));
1988 WLog_Print(context->priv->log, WLOG_WARN,
1989 "Unknown RDPDR_HEADER.Component: %s [0x%04" PRIx16
"], PacketId: %s",
1990 rdpdr_component_string(header->Component), header->Component,
1991 rdpdr_packetid_string(header->PacketId));
1994 return IFCALLRESULT(error, context->ReceivePDU, context, header, error);
1997 static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
2001 void* buffer = NULL;
2002 HANDLE events[8] = { 0 };
2003 HANDLE ChannelEvent = NULL;
2004 DWORD BytesReturned = 0;
2006 RdpdrServerContext* context = (RdpdrServerContext*)arg;
2007 wStream* s = Stream_New(NULL, 4096);
2009 WINPR_ASSERT(context);
2010 WINPR_ASSERT(context->priv);
2014 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2015 error = CHANNEL_RC_NO_MEMORY;
2019 if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer,
2020 &BytesReturned) == TRUE)
2022 if (BytesReturned ==
sizeof(HANDLE))
2023 CopyMemory(&ChannelEvent, buffer,
sizeof(HANDLE));
2025 WTSFreeMemory(buffer);
2029 events[nCount++] = ChannelEvent;
2030 events[nCount++] = context->priv->StopEvent;
2032 if ((error = rdpdr_server_send_announce_request(context)))
2034 WLog_Print(context->priv->log, WLOG_ERROR,
2035 "rdpdr_server_send_announce_request failed with error %" PRIu32
"!", error);
2041 size_t capacity = 0;
2043 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
2045 if (status == WAIT_FAILED)
2047 error = GetLastError();
2048 WLog_Print(context->priv->log, WLOG_ERROR,
2049 "WaitForMultipleObjects failed with error %" PRIu32
"!", error);
2053 status = WaitForSingleObject(context->priv->StopEvent, 0);
2055 if (status == WAIT_FAILED)
2057 error = GetLastError();
2058 WLog_Print(context->priv->log, WLOG_ERROR,
2059 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2063 if (status == WAIT_OBJECT_0)
2066 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned))
2068 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2069 error = ERROR_INTERNAL_ERROR;
2072 if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
2074 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_EnsureRemainingCapacity failed!");
2075 error = ERROR_INTERNAL_ERROR;
2079 capacity = MIN(Stream_Capacity(s), UINT32_MAX);
2080 if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s,
char),
2081 (ULONG)capacity, &BytesReturned))
2083 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelRead failed!");
2084 error = ERROR_INTERNAL_ERROR;
2088 if (BytesReturned >= RDPDR_HEADER_LENGTH)
2090 Stream_SetPosition(s, 0);
2091 Stream_SetLength(s, BytesReturned);
2093 while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH)
2097 Stream_Read_UINT16(s, header.Component);
2098 Stream_Read_UINT16(s, header.PacketId);
2100 if ((error = rdpdr_server_receive_pdu(context, s, &header)))
2102 WLog_Print(context->priv->log, WLOG_ERROR,
2103 "rdpdr_server_receive_pdu failed with error %" PRIu32
"!", error);
2111 Stream_Free(s, TRUE);
2114 if (error && context->rdpcontext)
2115 setChannelError(context->rdpcontext, error,
"rdpdr_server_thread reported an error");
2126 static UINT rdpdr_server_start(RdpdrServerContext* context)
2128 WINPR_ASSERT(context);
2129 WINPR_ASSERT(context->priv);
2130 context->priv->ChannelHandle =
2131 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPDR_SVC_CHANNEL_NAME);
2133 if (!context->priv->ChannelHandle)
2135 WLog_Print(context->priv->log, WLOG_ERROR,
"WTSVirtualChannelOpen failed!");
2136 return CHANNEL_RC_BAD_CHANNEL;
2139 if (!(context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
2141 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateEvent failed!");
2142 return ERROR_INTERNAL_ERROR;
2145 if (!(context->priv->Thread =
2146 CreateThread(NULL, 0, rdpdr_server_thread, (
void*)context, 0, NULL)))
2148 WLog_Print(context->priv->log, WLOG_ERROR,
"CreateThread failed!");
2149 (void)CloseHandle(context->priv->StopEvent);
2150 context->priv->StopEvent = NULL;
2151 return ERROR_INTERNAL_ERROR;
2154 return CHANNEL_RC_OK;
2162 static UINT rdpdr_server_stop(RdpdrServerContext* context)
2165 WINPR_ASSERT(context);
2166 WINPR_ASSERT(context->priv);
2168 if (context->priv->StopEvent)
2170 (void)SetEvent(context->priv->StopEvent);
2172 if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
2174 error = GetLastError();
2175 WLog_Print(context->priv->log, WLOG_ERROR,
2176 "WaitForSingleObject failed with error %" PRIu32
"!", error);
2180 (void)CloseHandle(context->priv->Thread);
2181 context->priv->Thread = NULL;
2182 (void)CloseHandle(context->priv->StopEvent);
2183 context->priv->StopEvent = NULL;
2186 if (context->priv->ChannelHandle)
2188 (void)WTSVirtualChannelClose(context->priv->ChannelHandle);
2189 context->priv->ChannelHandle = NULL;
2191 return CHANNEL_RC_OK;
2194 static void rdpdr_server_write_device_iorequest(
wStream* s, UINT32 deviceId, UINT32 fileId,
2195 UINT32 completionId, UINT32 majorFunction,
2196 UINT32 minorFunction)
2198 Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
2199 Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST);
2200 Stream_Write_UINT32(s, deviceId);
2201 Stream_Write_UINT32(s, fileId);
2202 Stream_Write_UINT32(s, completionId);
2203 Stream_Write_UINT32(s, majorFunction);
2204 Stream_Write_UINT32(s, minorFunction);
2212 static UINT rdpdr_server_read_file_directory_information(wLog* log,
wStream* s,
2215 UINT32 fileNameLength = 0;
2219 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 64))
2220 return ERROR_INVALID_DATA;
2222 Stream_Read_UINT32(s, fdi->NextEntryOffset);
2223 Stream_Read_UINT32(s, fdi->FileIndex);
2224 Stream_Read_INT64(s, fdi->CreationTime.QuadPart);
2225 Stream_Read_INT64(s, fdi->LastAccessTime.QuadPart);
2226 Stream_Read_INT64(s, fdi->LastWriteTime.QuadPart);
2227 Stream_Read_INT64(s, fdi->ChangeTime.QuadPart);
2228 Stream_Read_INT64(s, fdi->EndOfFile.QuadPart);
2229 Stream_Read_INT64(s, fdi->AllocationSize.QuadPart);
2230 Stream_Read_UINT32(s, fdi->FileAttributes);
2231 Stream_Read_UINT32(s, fileNameLength);
2233 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, fileNameLength))
2234 return ERROR_INVALID_DATA;
2236 if (Stream_Read_UTF16_String_As_UTF8_Buffer(s, fileNameLength /
sizeof(WCHAR), fdi->FileName,
2237 ARRAYSIZE(fdi->FileName)) < 0)
2238 return ERROR_INVALID_DATA;
2239 return CHANNEL_RC_OK;
2247 static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, UINT32 deviceId,
2248 UINT32 completionId,
const char* path,
2249 UINT32 desiredAccess, UINT32 createOptions,
2250 UINT32 createDisposition)
2252 size_t pathLength = 0;
2254 WINPR_ASSERT(context);
2255 WINPR_ASSERT(context->priv);
2257 WLog_Print(context->priv->log, WLOG_DEBUG,
2258 "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32
2259 ", path=%s, desiredAccess=0x%" PRIx32
" createOptions=0x%" PRIx32
2260 " createDisposition=0x%" PRIx32
"",
2261 deviceId, path, desiredAccess, createOptions, createDisposition);
2263 pathLength = (strlen(path) + 1U) *
sizeof(WCHAR);
2264 s = Stream_New(NULL, 256U + pathLength);
2268 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2269 return CHANNEL_RC_NO_MEMORY;
2272 rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0);
2273 Stream_Write_UINT32(s, desiredAccess);
2274 Stream_Write_UINT32(s, 0);
2275 Stream_Write_UINT32(s, 0);
2276 Stream_Write_UINT32(s, 0);
2277 Stream_Write_UINT32(s, 3);
2278 Stream_Write_UINT32(s, createDisposition);
2279 Stream_Write_UINT32(s, createOptions);
2280 WINPR_ASSERT(pathLength <= UINT32_MAX);
2281 Stream_Write_UINT32(s, (UINT32)pathLength);
2283 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2284 pathLength /
sizeof(WCHAR), TRUE) < 0)
2286 Stream_Free(s, TRUE);
2287 return ERROR_INTERNAL_ERROR;
2289 return rdpdr_seal_send_free_request(context, s);
2297 static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId,
2298 UINT32 fileId, UINT32 completionId)
2301 WINPR_ASSERT(context);
2302 WINPR_ASSERT(context->priv);
2304 WLog_Print(context->priv->log, WLOG_DEBUG,
2305 "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
"",
2307 s = Stream_New(NULL, 128);
2311 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2312 return CHANNEL_RC_NO_MEMORY;
2315 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0);
2317 return rdpdr_seal_send_free_request(context, s);
2325 static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, UINT32 deviceId,
2326 UINT32 fileId, UINT32 completionId, UINT32 length,
2330 WINPR_ASSERT(context);
2331 WINPR_ASSERT(context->priv);
2333 WLog_Print(context->priv->log, WLOG_DEBUG,
2334 "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2335 ", length=%" PRIu32
", offset=%" PRIu32
"",
2336 deviceId, fileId, length, offset);
2337 s = Stream_New(NULL, 128);
2341 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2342 return CHANNEL_RC_NO_MEMORY;
2345 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0);
2346 Stream_Write_UINT32(s, length);
2347 Stream_Write_UINT32(s, offset);
2348 Stream_Write_UINT32(s, 0);
2350 return rdpdr_seal_send_free_request(context, s);
2358 static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, UINT32 deviceId,
2359 UINT32 fileId, UINT32 completionId,
2360 const char* data, UINT32 length, UINT32 offset)
2363 WINPR_ASSERT(context);
2364 WINPR_ASSERT(context->priv);
2366 WLog_Print(context->priv->log, WLOG_DEBUG,
2367 "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2368 ", length=%" PRIu32
", offset=%" PRIu32
"",
2369 deviceId, fileId, length, offset);
2370 s = Stream_New(NULL, 64 + length);
2374 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2375 return CHANNEL_RC_NO_MEMORY;
2378 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0);
2379 Stream_Write_UINT32(s, length);
2380 Stream_Write_UINT32(s, offset);
2381 Stream_Write_UINT32(s, 0);
2383 Stream_Write(s, data, length);
2384 return rdpdr_seal_send_free_request(context, s);
2392 static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context,
2393 UINT32 deviceId, UINT32 fileId,
2394 UINT32 completionId,
const char* path)
2396 size_t pathLength = 0;
2398 WINPR_ASSERT(context);
2399 WINPR_ASSERT(context->priv);
2401 WLog_Print(context->priv->log, WLOG_DEBUG,
2402 "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2404 deviceId, fileId, path);
2406 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2407 s = Stream_New(NULL, 64 + pathLength);
2411 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2412 return CHANNEL_RC_NO_MEMORY;
2415 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_DIRECTORY_CONTROL,
2416 IRP_MN_QUERY_DIRECTORY);
2417 Stream_Write_UINT32(s, FileDirectoryInformation);
2418 Stream_Write_UINT8(s, path ? 1 : 0);
2419 WINPR_ASSERT(pathLength <= UINT32_MAX);
2420 Stream_Write_UINT32(s, (UINT32)pathLength);
2426 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2427 pathLength /
sizeof(WCHAR), TRUE) < 0)
2429 Stream_Free(s, TRUE);
2430 return ERROR_INTERNAL_ERROR;
2434 return rdpdr_seal_send_free_request(context, s);
2442 static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context,
2443 UINT32 deviceId, UINT32 fileId,
2444 UINT32 completionId,
const char* path)
2446 size_t pathLength = 0;
2448 WINPR_ASSERT(context);
2449 WINPR_ASSERT(context->priv);
2451 WLog_Print(context->priv->log, WLOG_DEBUG,
2452 "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32
", fileId=%" PRIu32
2454 deviceId, fileId, path);
2456 pathLength = path ? (strlen(path) + 1) *
sizeof(WCHAR) : 0;
2457 s = Stream_New(NULL, 64 + pathLength);
2461 WLog_Print(context->priv->log, WLOG_ERROR,
"Stream_New failed!");
2462 return CHANNEL_RC_NO_MEMORY;
2465 rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION,
2467 Stream_Write_UINT32(s, FileRenameInformation);
2468 WINPR_ASSERT(pathLength <= UINT32_MAX - 6U);
2469 Stream_Write_UINT32(s, (UINT32)pathLength + 6U);
2472 Stream_Write_UINT8(s, 0);
2473 Stream_Write_UINT8(s, 0);
2474 Stream_Write_UINT32(s, (UINT32)pathLength);
2479 if (Stream_Write_UTF16_String_From_UTF8(s, pathLength /
sizeof(WCHAR), path,
2480 pathLength /
sizeof(WCHAR), TRUE) < 0)
2482 Stream_Free(s, TRUE);
2483 return ERROR_INTERNAL_ERROR;
2487 return rdpdr_seal_send_free_request(context, s);
2490 static void rdpdr_server_convert_slashes(
char* path,
int size)
2492 WINPR_ASSERT(path || (size <= 0));
2494 for (
int i = 0; (i < size) && (path[i] !=
'\0'); i++)
2510 static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context,
wStream* s,
2512 UINT32 completionId, UINT32 ioStatus)
2514 WINPR_ASSERT(context);
2515 WINPR_ASSERT(context->priv);
2520 WLog_Print(context->priv->log, WLOG_DEBUG,
2521 "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32
2522 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2523 deviceId, completionId, ioStatus);
2525 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2527 rdpdr_server_irp_free(irp);
2528 return CHANNEL_RC_OK;
2536 static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context,
wStream* s,
2538 UINT32 completionId, UINT32 ioStatus)
2541 UINT8 information = 0;
2542 WINPR_ASSERT(context);
2543 WINPR_ASSERT(context->priv);
2546 WLog_Print(context->priv->log, WLOG_DEBUG,
2547 "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32
2548 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2549 deviceId, completionId, ioStatus);
2551 if (ioStatus != STATUS_SUCCESS)
2554 context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus);
2556 rdpdr_server_irp_free(irp);
2557 return CHANNEL_RC_OK;
2560 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2561 return ERROR_INVALID_DATA;
2563 Stream_Read_UINT32(s, fileId);
2564 Stream_Read_UINT8(s, information);
2566 irp->CompletionId = context->priv->NextCompletionId++;
2567 irp->Callback = rdpdr_server_drive_create_directory_callback2;
2568 irp->DeviceId = deviceId;
2569 irp->FileId = fileId;
2571 if (!rdpdr_server_enqueue_irp(context, irp))
2573 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2574 rdpdr_server_irp_free(irp);
2575 return ERROR_INTERNAL_ERROR;
2579 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2587 static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context,
void* callbackData,
2588 UINT32 deviceId,
const char* path)
2591 WINPR_ASSERT(context);
2592 WINPR_ASSERT(context->priv);
2593 WINPR_ASSERT(callbackData);
2595 irp = rdpdr_server_irp_new();
2599 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2600 return CHANNEL_RC_NO_MEMORY;
2603 irp->CompletionId = context->priv->NextCompletionId++;
2604 irp->Callback = rdpdr_server_drive_create_directory_callback1;
2605 irp->CallbackData = callbackData;
2606 irp->DeviceId = deviceId;
2607 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2608 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2610 if (!rdpdr_server_enqueue_irp(context, irp))
2612 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2613 rdpdr_server_irp_free(irp);
2614 return ERROR_INTERNAL_ERROR;
2618 return rdpdr_server_send_device_create_request(
2619 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
2620 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE);
2632 static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context,
wStream* s,
2634 UINT32 completionId, UINT32 ioStatus)
2637 WINPR_ASSERT(context);
2638 WINPR_ASSERT(context->priv);
2641 WLog_Print(context->priv->log, WLOG_DEBUG,
2642 "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32
2643 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2644 deviceId, completionId, ioStatus);
2646 context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus);
2648 rdpdr_server_irp_free(irp);
2649 return CHANNEL_RC_OK;
2657 static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context,
wStream* s,
2659 UINT32 completionId, UINT32 ioStatus)
2662 UINT8 information = 0;
2663 WINPR_ASSERT(context);
2664 WINPR_ASSERT(context->priv);
2666 WLog_Print(context->priv->log, WLOG_DEBUG,
2667 "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32
2668 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2669 deviceId, completionId, ioStatus);
2671 if (ioStatus != STATUS_SUCCESS)
2674 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
2676 rdpdr_server_irp_free(irp);
2677 return CHANNEL_RC_OK;
2680 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2681 return ERROR_INVALID_DATA;
2683 Stream_Read_UINT32(s, fileId);
2684 Stream_Read_UINT8(s, information);
2686 irp->CompletionId = context->priv->NextCompletionId++;
2687 irp->Callback = rdpdr_server_drive_delete_directory_callback2;
2688 irp->DeviceId = deviceId;
2689 irp->FileId = fileId;
2691 if (!rdpdr_server_enqueue_irp(context, irp))
2693 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2694 rdpdr_server_irp_free(irp);
2695 return ERROR_INTERNAL_ERROR;
2699 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
2707 static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context,
void* callbackData,
2708 UINT32 deviceId,
const char* path)
2710 RDPDR_IRP* irp = rdpdr_server_irp_new();
2711 WINPR_ASSERT(context);
2712 WINPR_ASSERT(context->priv);
2717 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2718 return CHANNEL_RC_NO_MEMORY;
2721 irp->CompletionId = context->priv->NextCompletionId++;
2722 irp->Callback = rdpdr_server_drive_delete_directory_callback1;
2723 irp->CallbackData = callbackData;
2724 irp->DeviceId = deviceId;
2725 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2726 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2728 if (!rdpdr_server_enqueue_irp(context, irp))
2730 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2731 rdpdr_server_irp_free(irp);
2732 return ERROR_INTERNAL_ERROR;
2736 return rdpdr_server_send_device_create_request(
2737 context, deviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE,
2738 FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
2750 static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context,
wStream* s,
2752 UINT32 completionId, UINT32 ioStatus)
2758 WINPR_ASSERT(context);
2759 WINPR_ASSERT(context->priv);
2761 WLog_Print(context->priv->log, WLOG_DEBUG,
2762 "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32
2763 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2764 deviceId, completionId, ioStatus);
2766 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
2767 return ERROR_INVALID_DATA;
2769 Stream_Read_UINT32(s, length);
2773 if ((error = rdpdr_server_read_file_directory_information(context->priv->log, s, &fdi)))
2775 WLog_Print(context->priv->log, WLOG_ERROR,
2776 "rdpdr_server_read_file_directory_information failed with error %" PRIu32
2784 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 1))
2785 return ERROR_INVALID_DATA;
2790 if (ioStatus == STATUS_SUCCESS)
2793 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus,
2794 length > 0 ? &fdi : NULL);
2796 irp->CompletionId = context->priv->NextCompletionId++;
2797 irp->Callback = rdpdr_server_drive_query_directory_callback2;
2799 if (!rdpdr_server_enqueue_irp(context, irp))
2801 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2802 rdpdr_server_irp_free(irp);
2803 return ERROR_INTERNAL_ERROR;
2807 return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId,
2808 irp->CompletionId, NULL);
2813 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
2815 rdpdr_server_irp_free(irp);
2818 return CHANNEL_RC_OK;
2826 static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context,
wStream* s,
2828 UINT32 completionId, UINT32 ioStatus)
2831 WINPR_ASSERT(context);
2832 WINPR_ASSERT(context->priv);
2834 WLog_Print(context->priv->log, WLOG_DEBUG,
2835 "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32
2836 ", completionId=%" PRIu32
", ioStatus=0x%" PRIx32
"",
2837 deviceId, completionId, ioStatus);
2839 if (ioStatus != STATUS_SUCCESS)
2842 context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL);
2844 rdpdr_server_irp_free(irp);
2845 return CHANNEL_RC_OK;
2848 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
2849 return ERROR_INVALID_DATA;
2851 Stream_Read_UINT32(s, fileId);
2853 irp->CompletionId = context->priv->NextCompletionId++;
2854 irp->Callback = rdpdr_server_drive_query_directory_callback2;
2855 irp->DeviceId = deviceId;
2856 irp->FileId = fileId;
2857 winpr_str_append(
"\\*.*", irp->PathName, ARRAYSIZE(irp->PathName), NULL);
2859 if (!rdpdr_server_enqueue_irp(context, irp))
2861 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2862 rdpdr_server_irp_free(irp);
2863 return ERROR_INTERNAL_ERROR;
2867 return rdpdr_server_send_device_query_directory_request(context, deviceId, fileId,
2868 irp->CompletionId, irp->PathName);
2876 static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context,
void* callbackData,
2877 UINT32 deviceId,
const char* path)
2879 RDPDR_IRP* irp = rdpdr_server_irp_new();
2880 WINPR_ASSERT(context);
2881 WINPR_ASSERT(context->priv);
2886 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2887 return CHANNEL_RC_NO_MEMORY;
2890 irp->CompletionId = context->priv->NextCompletionId++;
2891 irp->Callback = rdpdr_server_drive_query_directory_callback1;
2892 irp->CallbackData = callbackData;
2893 irp->DeviceId = deviceId;
2894 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2895 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2897 if (!rdpdr_server_enqueue_irp(context, irp))
2899 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2900 rdpdr_server_irp_free(irp);
2901 return ERROR_INTERNAL_ERROR;
2905 return rdpdr_server_send_device_create_request(
2906 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
2907 FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
2919 static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context,
wStream* s,
2921 UINT32 completionId, UINT32 ioStatus)
2924 UINT8 information = 0;
2925 WINPR_ASSERT(context);
2926 WINPR_ASSERT(context->priv);
2928 WLog_Print(context->priv->log, WLOG_DEBUG,
2929 "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
2930 ", ioStatus=0x%" PRIx32
"",
2931 deviceId, completionId, ioStatus);
2933 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
2934 return ERROR_INVALID_DATA;
2936 Stream_Read_UINT32(s, fileId);
2937 Stream_Read_UINT8(s, information);
2939 context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId);
2941 rdpdr_server_irp_free(irp);
2942 return CHANNEL_RC_OK;
2950 static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context,
void* callbackData,
2951 UINT32 deviceId,
const char* path, UINT32 desiredAccess,
2952 UINT32 createDisposition)
2954 RDPDR_IRP* irp = rdpdr_server_irp_new();
2955 WINPR_ASSERT(context);
2956 WINPR_ASSERT(context->priv);
2961 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
2962 return CHANNEL_RC_NO_MEMORY;
2965 irp->CompletionId = context->priv->NextCompletionId++;
2966 irp->Callback = rdpdr_server_drive_open_file_callback;
2967 irp->CallbackData = callbackData;
2968 irp->DeviceId = deviceId;
2969 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
2970 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
2972 if (!rdpdr_server_enqueue_irp(context, irp))
2974 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
2975 rdpdr_server_irp_free(irp);
2976 return ERROR_INTERNAL_ERROR;
2980 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
2981 irp->PathName, desiredAccess | SYNCHRONIZE,
2982 FILE_SYNCHRONOUS_IO_NONALERT, createDisposition);
2994 static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context,
wStream* s,
2996 UINT32 completionId, UINT32 ioStatus)
2999 char* buffer = NULL;
3000 WINPR_ASSERT(context);
3001 WINPR_ASSERT(context->priv);
3003 WLog_Print(context->priv->log, WLOG_DEBUG,
3004 "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3005 ", ioStatus=0x%" PRIx32
"",
3006 deviceId, completionId, ioStatus);
3008 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 4))
3009 return ERROR_INVALID_DATA;
3011 Stream_Read_UINT32(s, length);
3013 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3014 return ERROR_INVALID_DATA;
3018 buffer = Stream_Pointer(s);
3019 Stream_Seek(s, length);
3023 context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length);
3025 rdpdr_server_irp_free(irp);
3026 return CHANNEL_RC_OK;
3034 static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context,
void* callbackData,
3035 UINT32 deviceId, UINT32 fileId, UINT32 length,
3038 RDPDR_IRP* irp = rdpdr_server_irp_new();
3039 WINPR_ASSERT(context);
3040 WINPR_ASSERT(context->priv);
3045 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3046 return CHANNEL_RC_NO_MEMORY;
3049 irp->CompletionId = context->priv->NextCompletionId++;
3050 irp->Callback = rdpdr_server_drive_read_file_callback;
3051 irp->CallbackData = callbackData;
3052 irp->DeviceId = deviceId;
3053 irp->FileId = fileId;
3055 if (!rdpdr_server_enqueue_irp(context, irp))
3057 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3058 rdpdr_server_irp_free(irp);
3059 return ERROR_INTERNAL_ERROR;
3064 return rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId,
3077 static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context,
wStream* s,
3079 UINT32 completionId, UINT32 ioStatus)
3082 WINPR_ASSERT(context);
3083 WINPR_ASSERT(context->priv);
3085 WLog_Print(context->priv->log, WLOG_DEBUG,
3086 "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3087 ", ioStatus=0x%" PRIx32
"",
3088 deviceId, completionId, ioStatus);
3090 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3091 return ERROR_INVALID_DATA;
3093 Stream_Read_UINT32(s, length);
3096 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, length))
3097 return ERROR_INVALID_DATA;
3100 context->OnDriveWriteFileComplete(context, irp->CallbackData, ioStatus, length);
3102 rdpdr_server_irp_free(irp);
3103 return CHANNEL_RC_OK;
3111 static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context,
void* callbackData,
3112 UINT32 deviceId, UINT32 fileId,
const char* buffer,
3113 UINT32 length, UINT32 offset)
3115 RDPDR_IRP* irp = rdpdr_server_irp_new();
3116 WINPR_ASSERT(context);
3117 WINPR_ASSERT(context->priv);
3122 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3123 return CHANNEL_RC_NO_MEMORY;
3126 irp->CompletionId = context->priv->NextCompletionId++;
3127 irp->Callback = rdpdr_server_drive_write_file_callback;
3128 irp->CallbackData = callbackData;
3129 irp->DeviceId = deviceId;
3130 irp->FileId = fileId;
3132 if (!rdpdr_server_enqueue_irp(context, irp))
3134 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3135 rdpdr_server_irp_free(irp);
3136 return ERROR_INTERNAL_ERROR;
3141 return rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId,
3142 buffer, length, offset);
3154 static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context,
wStream* s,
3156 UINT32 completionId, UINT32 ioStatus)
3159 WINPR_ASSERT(context);
3160 WINPR_ASSERT(context->priv);
3163 WLog_Print(context->priv->log, WLOG_DEBUG,
3164 "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32
", completionId=%" PRIu32
3165 ", ioStatus=0x%" PRIx32
"",
3166 deviceId, completionId, ioStatus);
3169 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3170 return ERROR_INVALID_DATA;
3175 context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus);
3177 rdpdr_server_irp_free(irp);
3178 return CHANNEL_RC_OK;
3186 static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context,
void* callbackData,
3187 UINT32 deviceId, UINT32 fileId)
3189 RDPDR_IRP* irp = rdpdr_server_irp_new();
3190 WINPR_ASSERT(context);
3191 WINPR_ASSERT(context->priv);
3196 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3197 return CHANNEL_RC_NO_MEMORY;
3200 irp->CompletionId = context->priv->NextCompletionId++;
3201 irp->Callback = rdpdr_server_drive_close_file_callback;
3202 irp->CallbackData = callbackData;
3203 irp->DeviceId = deviceId;
3204 irp->FileId = fileId;
3206 if (!rdpdr_server_enqueue_irp(context, irp))
3208 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3209 rdpdr_server_irp_free(irp);
3210 return ERROR_INTERNAL_ERROR;
3215 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3227 static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context,
wStream* s,
3229 UINT32 completionId, UINT32 ioStatus)
3232 WINPR_ASSERT(context);
3233 WINPR_ASSERT(context->priv);
3236 WLog_Print(context->priv->log, WLOG_DEBUG,
3237 "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3238 ", ioStatus=0x%" PRIx32
"",
3239 deviceId, completionId, ioStatus);
3241 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3243 rdpdr_server_irp_free(irp);
3244 return CHANNEL_RC_OK;
3252 static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context,
wStream* s,
3254 UINT32 completionId, UINT32 ioStatus)
3257 UINT8 information = 0;
3258 WINPR_ASSERT(context);
3259 WINPR_ASSERT(context->priv);
3261 WLog_Print(context->priv->log, WLOG_DEBUG,
3262 "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3263 ", ioStatus=0x%" PRIx32
"",
3264 deviceId, completionId, ioStatus);
3266 if (ioStatus != STATUS_SUCCESS)
3269 context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus);
3271 rdpdr_server_irp_free(irp);
3272 return CHANNEL_RC_OK;
3275 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3276 return ERROR_INVALID_DATA;
3278 Stream_Read_UINT32(s, fileId);
3279 Stream_Read_UINT8(s, information);
3281 irp->CompletionId = context->priv->NextCompletionId++;
3282 irp->Callback = rdpdr_server_drive_delete_file_callback2;
3283 irp->DeviceId = deviceId;
3284 irp->FileId = fileId;
3286 if (!rdpdr_server_enqueue_irp(context, irp))
3288 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3289 rdpdr_server_irp_free(irp);
3290 return ERROR_INTERNAL_ERROR;
3294 return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId);
3302 static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context,
void* callbackData,
3303 UINT32 deviceId,
const char* path)
3305 RDPDR_IRP* irp = rdpdr_server_irp_new();
3306 WINPR_ASSERT(context);
3307 WINPR_ASSERT(context->priv);
3312 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3313 return CHANNEL_RC_NO_MEMORY;
3316 irp->CompletionId = context->priv->NextCompletionId++;
3317 irp->Callback = rdpdr_server_drive_delete_file_callback1;
3318 irp->CallbackData = callbackData;
3319 irp->DeviceId = deviceId;
3320 strncpy(irp->PathName, path,
sizeof(irp->PathName) - 1);
3321 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3323 if (!rdpdr_server_enqueue_irp(context, irp))
3325 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3326 rdpdr_server_irp_free(irp);
3327 return ERROR_INTERNAL_ERROR;
3331 return rdpdr_server_send_device_create_request(
3332 context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3333 FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3345 static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context,
wStream* s,
3347 UINT32 completionId, UINT32 ioStatus)
3349 WINPR_UNUSED(context);
3351 WINPR_ASSERT(context);
3352 WINPR_ASSERT(context->priv);
3355 WLog_Print(context->priv->log, WLOG_DEBUG,
3356 "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32
", completionId=%" PRIu32
3357 ", ioStatus=0x%" PRIx32
"",
3358 deviceId, completionId, ioStatus);
3360 rdpdr_server_irp_free(irp);
3361 return CHANNEL_RC_OK;
3369 static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context,
wStream* s,
3371 UINT32 completionId, UINT32 ioStatus)
3374 WINPR_ASSERT(context);
3375 WINPR_ASSERT(context->priv);
3377 WLog_Print(context->priv->log, WLOG_DEBUG,
3378 "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32
", completionId=%" PRIu32
3379 ", ioStatus=0x%" PRIx32
"",
3380 deviceId, completionId, ioStatus);
3382 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3383 return ERROR_INVALID_DATA;
3385 Stream_Read_UINT32(s, length);
3388 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3390 irp->CompletionId = context->priv->NextCompletionId++;
3391 irp->Callback = rdpdr_server_drive_rename_file_callback3;
3392 irp->DeviceId = deviceId;
3394 if (!rdpdr_server_enqueue_irp(context, irp))
3396 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3397 rdpdr_server_irp_free(irp);
3398 return ERROR_INTERNAL_ERROR;
3402 return rdpdr_server_send_device_close_request(context, deviceId, irp->FileId,
3411 static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context,
wStream* s,
3413 UINT32 completionId, UINT32 ioStatus)
3416 UINT8 information = 0;
3417 WINPR_ASSERT(context);
3418 WINPR_ASSERT(context->priv);
3420 WLog_Print(context->priv->log, WLOG_DEBUG,
3421 "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32
", completionId=%" PRIu32
3422 ", ioStatus=0x%" PRIx32
"",
3423 deviceId, completionId, ioStatus);
3425 if (ioStatus != STATUS_SUCCESS)
3428 context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus);
3430 rdpdr_server_irp_free(irp);
3431 return CHANNEL_RC_OK;
3434 if (!Stream_CheckAndLogRequiredLengthWLog(context->priv->log, s, 5))
3435 return ERROR_INVALID_DATA;
3437 Stream_Read_UINT32(s, fileId);
3438 Stream_Read_UINT8(s, information);
3440 irp->CompletionId = context->priv->NextCompletionId++;
3441 irp->Callback = rdpdr_server_drive_rename_file_callback2;
3442 irp->DeviceId = deviceId;
3443 irp->FileId = fileId;
3445 if (!rdpdr_server_enqueue_irp(context, irp))
3447 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3448 rdpdr_server_irp_free(irp);
3449 return ERROR_INTERNAL_ERROR;
3453 return rdpdr_server_send_device_file_rename_request(context, deviceId, fileId,
3454 irp->CompletionId, irp->ExtraBuffer);
3462 static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context,
void* callbackData,
3463 UINT32 deviceId,
const char* oldPath,
3464 const char* newPath)
3467 WINPR_ASSERT(context);
3468 WINPR_ASSERT(context->priv);
3469 irp = rdpdr_server_irp_new();
3473 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_irp_new failed!");
3474 return CHANNEL_RC_NO_MEMORY;
3477 irp->CompletionId = context->priv->NextCompletionId++;
3478 irp->Callback = rdpdr_server_drive_rename_file_callback1;
3479 irp->CallbackData = callbackData;
3480 irp->DeviceId = deviceId;
3481 strncpy(irp->PathName, oldPath,
sizeof(irp->PathName) - 1);
3482 strncpy(irp->ExtraBuffer, newPath,
sizeof(irp->ExtraBuffer) - 1);
3483 rdpdr_server_convert_slashes(irp->PathName,
sizeof(irp->PathName));
3484 rdpdr_server_convert_slashes(irp->ExtraBuffer,
sizeof(irp->ExtraBuffer));
3486 if (!rdpdr_server_enqueue_irp(context, irp))
3488 WLog_Print(context->priv->log, WLOG_ERROR,
"rdpdr_server_enqueue_irp failed!");
3489 rdpdr_server_irp_free(irp);
3490 return ERROR_INTERNAL_ERROR;
3495 return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId,
3496 irp->PathName, FILE_READ_DATA | SYNCHRONIZE,
3497 FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN);
3500 static void rdpdr_server_private_free(RdpdrServerPrivate* ctx)
3504 ListDictionary_Free(ctx->IrpList);
3505 HashTable_Free(ctx->devicelist);
3506 free(ctx->ClientComputerName);
3510 #define TAG CHANNELS_TAG("rdpdr.server")
3511 static RdpdrServerPrivate* rdpdr_server_private_new(
void)
3513 RdpdrServerPrivate* priv = (RdpdrServerPrivate*)calloc(1,
sizeof(RdpdrServerPrivate));
3518 priv->log = WLog_Get(TAG);
3519 priv->VersionMajor = RDPDR_VERSION_MAJOR;
3520 priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
3521 priv->ClientId = g_ClientId++;
3522 priv->UserLoggedOnPdu = TRUE;
3523 priv->NextCompletionId = 1;
3524 priv->IrpList = ListDictionary_New(TRUE);
3529 priv->devicelist = HashTable_New(FALSE);
3530 if (!priv->devicelist)
3533 HashTable_SetHashFunction(priv->devicelist, rdpdr_deviceid_hash);
3534 wObject* obj = HashTable_ValueObject(priv->devicelist);
3536 obj->fnObjectFree = rdpdr_device_free_h;
3537 obj->fnObjectNew = rdpdr_device_clone;
3539 obj = HashTable_KeyObject(priv->devicelist);
3540 obj->fnObjectEquals = rdpdr_device_equal;
3544 rdpdr_server_private_free(priv);
3548 RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm)
3550 RdpdrServerContext* context = (RdpdrServerContext*)calloc(1,
sizeof(RdpdrServerContext));
3556 context->Start = rdpdr_server_start;
3557 context->Stop = rdpdr_server_stop;
3558 context->DriveCreateDirectory = rdpdr_server_drive_create_directory;
3559 context->DriveDeleteDirectory = rdpdr_server_drive_delete_directory;
3560 context->DriveQueryDirectory = rdpdr_server_drive_query_directory;
3561 context->DriveOpenFile = rdpdr_server_drive_open_file;
3562 context->DriveReadFile = rdpdr_server_drive_read_file;
3563 context->DriveWriteFile = rdpdr_server_drive_write_file;
3564 context->DriveCloseFile = rdpdr_server_drive_close_file;
3565 context->DriveDeleteFile = rdpdr_server_drive_delete_file;
3566 context->DriveRenameFile = rdpdr_server_drive_rename_file;
3567 context->priv = rdpdr_server_private_new();
3572 context->supported = UINT16_MAX;
3576 WINPR_PRAGMA_DIAG_PUSH
3577 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
3578 rdpdr_server_context_free(context);
3579 WINPR_PRAGMA_DIAG_POP
3583 void rdpdr_server_context_free(RdpdrServerContext* context)
3588 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.