21#include <winpr/wlog.h>
22#include <winpr/print.h>
23#include <winpr/smartcard.h>
25#include <freerdp/utils/rdpdr_utils.h>
26#include <freerdp/channels/scard.h>
27#include <freerdp/channels/rdpdr.h>
29#include <freerdp/log.h>
31LONG scard_log_status_error(
const char* tag,
const char* what, LONG status)
33 wLog* log = WLog_Get(tag);
34 return scard_log_status_error_wlog(log,
"%s", status, what);
37LONG scard_log_status_error_wlog(wLog* log,
const char* what, LONG status, ...)
39 if (status != SCARD_S_SUCCESS)
41 DWORD level = WLOG_ERROR;
44 case SCARD_W_RESET_CARD:
45 case SCARD_E_NOT_TRANSACTED:
46 case SCARD_E_CANCELLED:
47 case SCARD_E_UNSUPPORTED_FEATURE:
51 case SCARD_E_NO_READERS_AVAILABLE:
60 va_list ap = WINPR_C_ARRAY_INIT;
62 winpr_vasprintf(&str, &slen, what, ap);
64 WLog_Print(log, level,
"%s failed with error %s [%" PRId32
"]", str,
65 SCardGetErrorString(status), status);
71const char* scard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
73 switch (ioControlCode)
75 case SCARD_IOCTL_ESTABLISHCONTEXT:
76 return funcName ?
"SCardEstablishContext" :
"SCARD_IOCTL_ESTABLISHCONTEXT";
78 case SCARD_IOCTL_RELEASECONTEXT:
79 return funcName ?
"SCardReleaseContext" :
"SCARD_IOCTL_RELEASECONTEXT";
81 case SCARD_IOCTL_ISVALIDCONTEXT:
82 return funcName ?
"SCardIsValidContext" :
"SCARD_IOCTL_ISVALIDCONTEXT";
84 case SCARD_IOCTL_LISTREADERGROUPSA:
85 return funcName ?
"SCardListReaderGroupsA" :
"SCARD_IOCTL_LISTREADERGROUPSA";
87 case SCARD_IOCTL_LISTREADERGROUPSW:
88 return funcName ?
"SCardListReaderGroupsW" :
"SCARD_IOCTL_LISTREADERGROUPSW";
90 case SCARD_IOCTL_LISTREADERSA:
91 return funcName ?
"SCardListReadersA" :
"SCARD_IOCTL_LISTREADERSA";
93 case SCARD_IOCTL_LISTREADERSW:
94 return funcName ?
"SCardListReadersW" :
"SCARD_IOCTL_LISTREADERSW";
96 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
97 return funcName ?
"SCardIntroduceReaderGroupA" :
"SCARD_IOCTL_INTRODUCEREADERGROUPA";
99 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
100 return funcName ?
"SCardIntroduceReaderGroupW" :
"SCARD_IOCTL_INTRODUCEREADERGROUPW";
102 case SCARD_IOCTL_FORGETREADERGROUPA:
103 return funcName ?
"SCardForgetReaderGroupA" :
"SCARD_IOCTL_FORGETREADERGROUPA";
105 case SCARD_IOCTL_FORGETREADERGROUPW:
106 return funcName ?
"SCardForgetReaderGroupW" :
"SCARD_IOCTL_FORGETREADERGROUPW";
108 case SCARD_IOCTL_INTRODUCEREADERA:
109 return funcName ?
"SCardIntroduceReaderA" :
"SCARD_IOCTL_INTRODUCEREADERA";
111 case SCARD_IOCTL_INTRODUCEREADERW:
112 return funcName ?
"SCardIntroduceReaderW" :
"SCARD_IOCTL_INTRODUCEREADERW";
114 case SCARD_IOCTL_FORGETREADERA:
115 return funcName ?
"SCardForgetReaderA" :
"SCARD_IOCTL_FORGETREADERA";
117 case SCARD_IOCTL_FORGETREADERW:
118 return funcName ?
"SCardForgetReaderW" :
"SCARD_IOCTL_FORGETREADERW";
120 case SCARD_IOCTL_ADDREADERTOGROUPA:
121 return funcName ?
"SCardAddReaderToGroupA" :
"SCARD_IOCTL_ADDREADERTOGROUPA";
123 case SCARD_IOCTL_ADDREADERTOGROUPW:
124 return funcName ?
"SCardAddReaderToGroupW" :
"SCARD_IOCTL_ADDREADERTOGROUPW";
126 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
127 return funcName ?
"SCardRemoveReaderFromGroupA" :
"SCARD_IOCTL_REMOVEREADERFROMGROUPA";
129 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
130 return funcName ?
"SCardRemoveReaderFromGroupW" :
"SCARD_IOCTL_REMOVEREADERFROMGROUPW";
132 case SCARD_IOCTL_LOCATECARDSA:
133 return funcName ?
"SCardLocateCardsA" :
"SCARD_IOCTL_LOCATECARDSA";
135 case SCARD_IOCTL_LOCATECARDSW:
136 return funcName ?
"SCardLocateCardsW" :
"SCARD_IOCTL_LOCATECARDSW";
138 case SCARD_IOCTL_GETSTATUSCHANGEA:
139 return funcName ?
"SCardGetStatusChangeA" :
"SCARD_IOCTL_GETSTATUSCHANGEA";
141 case SCARD_IOCTL_GETSTATUSCHANGEW:
142 return funcName ?
"SCardGetStatusChangeW" :
"SCARD_IOCTL_GETSTATUSCHANGEW";
144 case SCARD_IOCTL_CANCEL:
145 return funcName ?
"SCardCancel" :
"SCARD_IOCTL_CANCEL";
147 case SCARD_IOCTL_CONNECTA:
148 return funcName ?
"SCardConnectA" :
"SCARD_IOCTL_CONNECTA";
150 case SCARD_IOCTL_CONNECTW:
151 return funcName ?
"SCardConnectW" :
"SCARD_IOCTL_CONNECTW";
153 case SCARD_IOCTL_RECONNECT:
154 return funcName ?
"SCardReconnect" :
"SCARD_IOCTL_RECONNECT";
156 case SCARD_IOCTL_DISCONNECT:
157 return funcName ?
"SCardDisconnect" :
"SCARD_IOCTL_DISCONNECT";
159 case SCARD_IOCTL_BEGINTRANSACTION:
160 return funcName ?
"SCardBeginTransaction" :
"SCARD_IOCTL_BEGINTRANSACTION";
162 case SCARD_IOCTL_ENDTRANSACTION:
163 return funcName ?
"SCardEndTransaction" :
"SCARD_IOCTL_ENDTRANSACTION";
165 case SCARD_IOCTL_STATE:
166 return funcName ?
"SCardState" :
"SCARD_IOCTL_STATE";
168 case SCARD_IOCTL_STATUSA:
169 return funcName ?
"SCardStatusA" :
"SCARD_IOCTL_STATUSA";
171 case SCARD_IOCTL_STATUSW:
172 return funcName ?
"SCardStatusW" :
"SCARD_IOCTL_STATUSW";
174 case SCARD_IOCTL_TRANSMIT:
175 return funcName ?
"SCardTransmit" :
"SCARD_IOCTL_TRANSMIT";
177 case SCARD_IOCTL_CONTROL:
178 return funcName ?
"SCardControl" :
"SCARD_IOCTL_CONTROL";
180 case SCARD_IOCTL_GETATTRIB:
181 return funcName ?
"SCardGetAttrib" :
"SCARD_IOCTL_GETATTRIB";
183 case SCARD_IOCTL_SETATTRIB:
184 return funcName ?
"SCardSetAttrib" :
"SCARD_IOCTL_SETATTRIB";
186 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
187 return funcName ?
"SCardAccessStartedEvent" :
"SCARD_IOCTL_ACCESSSTARTEDEVENT";
189 case SCARD_IOCTL_LOCATECARDSBYATRA:
190 return funcName ?
"SCardLocateCardsByATRA" :
"SCARD_IOCTL_LOCATECARDSBYATRA";
192 case SCARD_IOCTL_LOCATECARDSBYATRW:
193 return funcName ?
"SCardLocateCardsByATRB" :
"SCARD_IOCTL_LOCATECARDSBYATRW";
195 case SCARD_IOCTL_READCACHEA:
196 return funcName ?
"SCardReadCacheA" :
"SCARD_IOCTL_READCACHEA";
198 case SCARD_IOCTL_READCACHEW:
199 return funcName ?
"SCardReadCacheW" :
"SCARD_IOCTL_READCACHEW";
201 case SCARD_IOCTL_WRITECACHEA:
202 return funcName ?
"SCardWriteCacheA" :
"SCARD_IOCTL_WRITECACHEA";
204 case SCARD_IOCTL_WRITECACHEW:
205 return funcName ?
"SCardWriteCacheW" :
"SCARD_IOCTL_WRITECACHEW";
207 case SCARD_IOCTL_GETTRANSMITCOUNT:
208 return funcName ?
"SCardGetTransmitCount" :
"SCARD_IOCTL_GETTRANSMITCOUNT";
210 case SCARD_IOCTL_RELEASETARTEDEVENT:
211 return funcName ?
"SCardReleaseStartedEvent" :
"SCARD_IOCTL_RELEASETARTEDEVENT";
213 case SCARD_IOCTL_GETREADERICON:
214 return funcName ?
"SCardGetReaderIcon" :
"SCARD_IOCTL_GETREADERICON";
216 case SCARD_IOCTL_GETDEVICETYPEID:
217 return funcName ?
"SCardGetDeviceTypeId" :
"SCARD_IOCTL_GETDEVICETYPEID";
220 return funcName ?
"SCardUnknown" :
"SCARD_IOCTL_UNKNOWN";
224const char* rdpdr_component_string(UINT16 component)
229 return "RDPDR_CTYP_PRN";
230 case RDPDR_CTYP_CORE:
231 return "RDPDR_CTYP_CORE";
237const char* rdpdr_packetid_string(UINT16 packetid)
241 case PAKID_CORE_SERVER_ANNOUNCE:
242 return "PAKID_CORE_SERVER_ANNOUNCE";
243 case PAKID_CORE_CLIENTID_CONFIRM:
244 return "PAKID_CORE_CLIENTID_CONFIRM";
245 case PAKID_CORE_CLIENT_NAME:
246 return "PAKID_CORE_CLIENT_NAME";
247 case PAKID_CORE_DEVICELIST_ANNOUNCE:
248 return "PAKID_CORE_DEVICELIST_ANNOUNCE";
249 case PAKID_CORE_DEVICE_REPLY:
250 return "PAKID_CORE_DEVICE_REPLY";
251 case PAKID_CORE_DEVICE_IOREQUEST:
252 return "PAKID_CORE_DEVICE_IOREQUEST";
253 case PAKID_CORE_DEVICE_IOCOMPLETION:
254 return "PAKID_CORE_DEVICE_IOCOMPLETION";
255 case PAKID_CORE_SERVER_CAPABILITY:
256 return "PAKID_CORE_SERVER_CAPABILITY";
257 case PAKID_CORE_CLIENT_CAPABILITY:
258 return "PAKID_CORE_CLIENT_CAPABILITY";
259 case PAKID_CORE_DEVICELIST_REMOVE:
260 return "PAKID_CORE_DEVICELIST_REMOVE";
261 case PAKID_CORE_USER_LOGGEDON:
262 return "PAKID_CORE_USER_LOGGEDON";
263 case PAKID_PRN_CACHE_DATA:
264 return "PAKID_PRN_CACHE_DATA";
265 case PAKID_PRN_USING_XPS:
266 return "PAKID_PRN_USING_XPS";
272BOOL rdpdr_write_iocompletion_header(
wStream* out, UINT32 DeviceId, UINT32 CompletionId,
276 Stream_ResetPosition(out);
277 if (!Stream_EnsureRemainingCapacity(out, 16))
280 Stream_Write_UINT16(out, RDPDR_CTYP_CORE);
281 Stream_Write_UINT16(out, PAKID_CORE_DEVICE_IOCOMPLETION);
282 Stream_Write_UINT32(out, DeviceId);
283 Stream_Write_UINT32(out, CompletionId);
284 Stream_Write_INT32(out, ioStatus);
289static void rdpdr_dump_packet(wLog* log, DWORD lvl,
wStream* s,
const char* custom, BOOL send)
291 if (!WLog_IsLevelActive(log, lvl))
294 const size_t gpos = Stream_GetPosition(s);
295 const size_t pos = send ? Stream_GetPosition(s) : Stream_Length(s);
297 UINT16 component = 0;
300 Stream_ResetPosition(s);
303 Stream_Read_UINT16(s, component);
305 Stream_Read_UINT16(s, packetid);
309 case PAKID_CORE_SERVER_ANNOUNCE:
310 case PAKID_CORE_CLIENTID_CONFIRM:
312 UINT16 versionMajor = 0;
313 UINT16 versionMinor = 0;
317 Stream_Read_UINT16(s, versionMajor);
319 Stream_Read_UINT16(s, versionMinor);
321 Stream_Read_UINT32(s, clientID);
323 "%s [%s | %s] [version:%" PRIu16
".%" PRIu16
"][id:0x%08" PRIx32
325 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
326 versionMajor, versionMinor, clientID, pos);
329 case PAKID_CORE_CLIENT_NAME:
331 char name[256] = WINPR_C_ARRAY_INIT;
332 UINT32 unicodeFlag = 0;
334 UINT32 computerNameLen = 0;
336 Stream_Read_UINT32(s, unicodeFlag);
338 Stream_Read_UINT32(s, codePage);
340 Stream_Read_UINT32(s, computerNameLen);
341 if (pos >= 16 + computerNameLen)
343 if (unicodeFlag == 0)
344 Stream_Read(s, name, MIN(
sizeof(name), computerNameLen));
346 (
void)ConvertWCharNToUtf8(Stream_ConstPointer(s),
347 computerNameLen /
sizeof(WCHAR), name,
sizeof(name));
350 "%s [%s | %s] [ucs:%" PRIu32
"|cp:%" PRIu32
"][len:0x%08" PRIx32
352 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
353 unicodeFlag, codePage, computerNameLen, name, pos);
357 case PAKID_CORE_DEVICE_IOREQUEST:
359 UINT32 CompletionId = 0;
362 UINT32 MajorFunction = 0;
363 UINT32 MinorFunction = 0;
366 Stream_Read_UINT32(s, deviceID);
368 Stream_Read_UINT32(s, FileId);
370 Stream_Read_UINT32(s, CompletionId);
372 Stream_Read_UINT32(s, MajorFunction);
374 Stream_Read_UINT32(s, MinorFunction);
376 "%s [%s | %s] [0x%08" PRIx32
"] FileId=0x%08" PRIx32
377 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
378 ", MinorFunction=0x%08" PRIx32
" -> %" PRIuz,
379 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
380 deviceID, FileId, CompletionId, MajorFunction, MinorFunction, pos);
383 case PAKID_CORE_DEVICE_IOCOMPLETION:
385 UINT32 completionID = 0;
389 Stream_Read_UINT32(s, deviceID);
391 Stream_Read_UINT32(s, completionID);
393 Stream_Read_UINT32(s, ioStatus);
396 "%s [%s | %s] [0x%08" PRIx32
"] completionID=0x%08" PRIx32
397 ", ioStatus=0x%08" PRIx32
" -> %" PRIuz,
398 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
399 deviceID, completionID, ioStatus, pos);
402 case PAKID_CORE_DEVICE_REPLY:
408 Stream_Read_UINT32(s, deviceID);
410 Stream_Read_UINT32(s, status);
412 "%s [%s | %s] [id:0x%08" PRIx32
",status=0x%08" PRIx32
"] -> %" PRIuz,
413 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
414 deviceID, status, pos);
417 case PAKID_CORE_CLIENT_CAPABILITY:
418 case PAKID_CORE_SERVER_CAPABILITY:
420 UINT16 numCapabilities = 0;
422 Stream_Read_UINT16(s, numCapabilities);
424 Stream_Seek_UINT16(s);
425 WLog_Print(log, lvl,
"%s [%s | %s] [caps:%" PRIu16
"] -> %" PRIuz, custom,
426 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
427 numCapabilities, pos);
428 for (UINT16 x = 0; x < numCapabilities; x++)
431 const UINT error = rdpdr_read_capset_header(log, s, &header);
432 if (error == CHANNEL_RC_OK)
433 Stream_Seek(s, header.CapabilityLength);
437 case PAKID_CORE_DEVICELIST_ANNOUNCE:
443 Stream_Read_UINT32(s, count);
445 WLog_Print(log, lvl,
"%s [%s | %s] [%" PRIu32
"] -> %" PRIuz, custom,
446 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
449 for (UINT32 x = 0; x < count; x++)
456 Stream_Read_UINT32(s, device.DeviceType);
457 Stream_Read_UINT32(s, device.DeviceId);
458 Stream_Read(s, device.PreferredDosName, 8);
459 Stream_Read_UINT32(s, device.DeviceDataLength);
460 device.DeviceData = Stream_Pointer(s);
462 offset += device.DeviceDataLength;
465 "%s [announce][%" PRIu32
"] %s [0x%08" PRIx32
466 "] '%s' [DeviceDataLength=%" PRIu32
"]",
468 device.PreferredDosName, device.DeviceDataLength);
472 case PAKID_CORE_DEVICELIST_REMOVE:
478 Stream_Read_UINT32(s, count);
480 WLog_Print(log, lvl,
"%s [%s | %s] [%" PRIu32
"] -> %" PRIuz, custom,
481 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
484 for (UINT32 x = 0; x < count; x++)
490 Stream_Read_UINT32(s,
id);
492 WLog_Print(log, lvl,
"%s [remove][%" PRIu32
"] id=%" PRIu32, custom, x,
id);
496 case PAKID_CORE_USER_LOGGEDON:
497 WLog_Print(log, lvl,
"%s [%s | %s] -> %" PRIuz, custom,
498 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
502 WLog_Print(log, lvl,
"%s [%s | %s] -> %" PRIuz, custom,
503 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
509 if (!Stream_SetPosition(s, gpos))
510 WLog_Print(log, WLOG_ERROR,
"Stream_SetPosition(%" PRIuz
") failed", gpos);
513void rdpdr_dump_received_packet(wLog* log, DWORD lvl,
wStream* out,
const char* custom)
515 rdpdr_dump_packet(log, lvl, out, custom, FALSE);
518void rdpdr_dump_send_packet(wLog* log, DWORD lvl,
wStream* out,
const char* custom)
520 rdpdr_dump_packet(log, lvl, out, custom, TRUE);
523const char* rdpdr_irp_string(UINT32 major)
528 return "IRP_MJ_CREATE";
530 return "IRP_MJ_CLOSE";
532 return "IRP_MJ_READ";
534 return "IRP_MJ_WRITE";
535 case IRP_MJ_DEVICE_CONTROL:
536 return "IRP_MJ_DEVICE_CONTROL";
537 case IRP_MJ_QUERY_VOLUME_INFORMATION:
538 return "IRP_MJ_QUERY_VOLUME_INFORMATION";
539 case IRP_MJ_SET_VOLUME_INFORMATION:
540 return "IRP_MJ_SET_VOLUME_INFORMATION";
541 case IRP_MJ_QUERY_INFORMATION:
542 return "IRP_MJ_QUERY_INFORMATION";
543 case IRP_MJ_SET_INFORMATION:
544 return "IRP_MJ_SET_INFORMATION";
545 case IRP_MJ_DIRECTORY_CONTROL:
546 return "IRP_MJ_DIRECTORY_CONTROL";
547 case IRP_MJ_LOCK_CONTROL:
548 return "IRP_MJ_LOCK_CONTROL";
550 return "IRP_UNKNOWN";
554const char* rdpdr_cap_type_string(UINT16 capability)
558 case CAP_GENERAL_TYPE:
559 return "CAP_GENERAL_TYPE";
560 case CAP_PRINTER_TYPE:
561 return "CAP_PRINTER_TYPE";
563 return "CAP_PORT_TYPE";
565 return "CAP_DRIVE_TYPE";
566 case CAP_SMARTCARD_TYPE:
567 return "CAP_SMARTCARD_TYPE";
569 return "CAP_UNKNOWN";
575 WINPR_ASSERT(header);
576 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
577 return ERROR_INVALID_DATA;
579 Stream_Read_UINT16(s, header->CapabilityType);
580 Stream_Read_UINT16(s, header->CapabilityLength);
581 Stream_Read_UINT32(s, header->Version);
583 WLog_Print(log, WLOG_TRACE,
584 "capability %s [0x%04" PRIx16
"] got version %" PRIu32
", length %" PRIu16,
585 rdpdr_cap_type_string(header->CapabilityType), header->CapabilityType,
586 header->Version, header->CapabilityLength);
587 if (header->CapabilityLength < 8)
589 WLog_Print(log, WLOG_ERROR,
"capability %s got short length %" PRIu32,
590 rdpdr_cap_type_string(header->CapabilityType), header->CapabilityLength);
591 return ERROR_INVALID_DATA;
593 header->CapabilityLength -= 8;
594 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, header->CapabilityLength))
595 return ERROR_INVALID_DATA;
596 return CHANNEL_RC_OK;
601 WINPR_ASSERT(header);
602 WINPR_ASSERT(header->CapabilityLength >= 8);
604 if (!Stream_EnsureRemainingCapacity(s, header->CapabilityLength))
606 WLog_Print(log, WLOG_ERROR,
"not enough data in stream!");
607 return ERROR_INVALID_DATA;
610 WLog_Print(log, WLOG_TRACE,
"writing capability %s version %" PRIu32
", length %" PRIu16,
611 rdpdr_cap_type_string(header->CapabilityType), header->Version,
612 header->CapabilityLength);
613 Stream_Write_UINT16(s, header->CapabilityType);
614 Stream_Write_UINT16(s, header->CapabilityLength);
615 Stream_Write_UINT32(s, header->Version);
616 return CHANNEL_RC_OK;
619const char* rdpdr_irp_val2str(UINT32 ioCode1)
623 case RDPDR_IRP_MJ_CREATE:
625 case RDPDR_IRP_MJ_CLEANUP:
627 case RDPDR_IRP_MJ_CLOSE:
629 case RDPDR_IRP_MJ_READ:
631 case RDPDR_IRP_MJ_WRITE:
633 case RDPDR_IRP_MJ_FLUSH_BUFFERS:
634 return "MJ_FLUSH_BUFFERS";
635 case RDPDR_IRP_MJ_SHUTDOWN:
636 return "MJ_SHUTDOWN";
637 case RDPDR_IRP_MJ_DEVICE_CONTROL:
638 return "MJ_DEVICE_CONTROL";
639 case RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION:
640 return "MJ_QUERY_VOLUME_INFORMATION";
641 case RDPDR_IRP_MJ_SET_VOLUME_INFORMATION:
642 return "MJ_SET_VOLUME_INFORMATION";
643 case RDPDR_IRP_MJ_QUERY_INFORMATION:
644 return "MJ_QUERY_INFORMATION";
645 case RDPDR_IRP_MJ_SET_INFORMATION:
646 return "MJ_SET_INFORMATION";
647 case RDPDR_IRP_MJ_DIRECTORY_CONTROL:
648 return "MJ_DIRECTORY_CONTROL";
649 case RDPDR_IRP_MJ_LOCK_CONTROL:
650 return "MJ_LOCK_CONTROL";
651 case RDPDR_IRP_MJ_QUERY_SECURITY:
652 return "MJ_QUERY_SECURITY";
653 case RDPDR_IRP_MJ_SET_SECURITY:
654 return "MJ_SET_SECURITY";
656 return "IRP_MJ_UNKNOWN";
660const char* rdpdr_irp_mask2str(UINT32 ioCode1Mask,
char* buffer,
size_t len)
665 if (!winpr_str_append(
"{", buffer, len,
nullptr))
668 for (
size_t x = 0; x < 32; x++)
670 const UINT32 mask = (1u << x);
671 if (ioCode1Mask & mask)
673 if (!winpr_str_append(rdpdr_irp_val2str(mask), &buffer[1], len - 1,
"|"))
678 char number[16] = WINPR_C_ARRAY_INIT;
679 (void)_snprintf(number,
sizeof(number),
"}[0x%08" PRIx32
"]", ioCode1Mask);
680 if (!winpr_str_append(number, buffer, len,
nullptr))
685const char* rdpdr_device_type_string(UINT32 type)
689 case RDPDR_DTYP_SERIAL:
691 case RDPDR_DTYP_PRINT:
693 case RDPDR_DTYP_FILESYSTEM:
695 case RDPDR_DTYP_SMARTCARD:
697 case RDPDR_DTYP_PARALLEL:
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_rdpdr_dtyp_string(UINT32 type)
Returns a string representation of RDPDR_DTYP_*.