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, what, status);
37LONG scard_log_status_error_wlog(wLog* log,
const char* what, LONG status)
39 if (status != SCARD_S_SUCCESS)
41 DWORD level = WLOG_ERROR;
47 case SCARD_E_NO_READERS_AVAILABLE:
53 WLog_Print(log, level,
"%s failed with error %s [%" PRId32
"]", what,
54 SCardGetErrorString(status), status);
59const char* scard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
61 switch (ioControlCode)
63 case SCARD_IOCTL_ESTABLISHCONTEXT:
64 return funcName ?
"SCardEstablishContext" :
"SCARD_IOCTL_ESTABLISHCONTEXT";
66 case SCARD_IOCTL_RELEASECONTEXT:
67 return funcName ?
"SCardReleaseContext" :
"SCARD_IOCTL_RELEASECONTEXT";
69 case SCARD_IOCTL_ISVALIDCONTEXT:
70 return funcName ?
"SCardIsValidContext" :
"SCARD_IOCTL_ISVALIDCONTEXT";
72 case SCARD_IOCTL_LISTREADERGROUPSA:
73 return funcName ?
"SCardListReaderGroupsA" :
"SCARD_IOCTL_LISTREADERGROUPSA";
75 case SCARD_IOCTL_LISTREADERGROUPSW:
76 return funcName ?
"SCardListReaderGroupsW" :
"SCARD_IOCTL_LISTREADERGROUPSW";
78 case SCARD_IOCTL_LISTREADERSA:
79 return funcName ?
"SCardListReadersA" :
"SCARD_IOCTL_LISTREADERSA";
81 case SCARD_IOCTL_LISTREADERSW:
82 return funcName ?
"SCardListReadersW" :
"SCARD_IOCTL_LISTREADERSW";
84 case SCARD_IOCTL_INTRODUCEREADERGROUPA:
85 return funcName ?
"SCardIntroduceReaderGroupA" :
"SCARD_IOCTL_INTRODUCEREADERGROUPA";
87 case SCARD_IOCTL_INTRODUCEREADERGROUPW:
88 return funcName ?
"SCardIntroduceReaderGroupW" :
"SCARD_IOCTL_INTRODUCEREADERGROUPW";
90 case SCARD_IOCTL_FORGETREADERGROUPA:
91 return funcName ?
"SCardForgetReaderGroupA" :
"SCARD_IOCTL_FORGETREADERGROUPA";
93 case SCARD_IOCTL_FORGETREADERGROUPW:
94 return funcName ?
"SCardForgetReaderGroupW" :
"SCARD_IOCTL_FORGETREADERGROUPW";
96 case SCARD_IOCTL_INTRODUCEREADERA:
97 return funcName ?
"SCardIntroduceReaderA" :
"SCARD_IOCTL_INTRODUCEREADERA";
99 case SCARD_IOCTL_INTRODUCEREADERW:
100 return funcName ?
"SCardIntroduceReaderW" :
"SCARD_IOCTL_INTRODUCEREADERW";
102 case SCARD_IOCTL_FORGETREADERA:
103 return funcName ?
"SCardForgetReaderA" :
"SCARD_IOCTL_FORGETREADERA";
105 case SCARD_IOCTL_FORGETREADERW:
106 return funcName ?
"SCardForgetReaderW" :
"SCARD_IOCTL_FORGETREADERW";
108 case SCARD_IOCTL_ADDREADERTOGROUPA:
109 return funcName ?
"SCardAddReaderToGroupA" :
"SCARD_IOCTL_ADDREADERTOGROUPA";
111 case SCARD_IOCTL_ADDREADERTOGROUPW:
112 return funcName ?
"SCardAddReaderToGroupW" :
"SCARD_IOCTL_ADDREADERTOGROUPW";
114 case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
115 return funcName ?
"SCardRemoveReaderFromGroupA" :
"SCARD_IOCTL_REMOVEREADERFROMGROUPA";
117 case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
118 return funcName ?
"SCardRemoveReaderFromGroupW" :
"SCARD_IOCTL_REMOVEREADERFROMGROUPW";
120 case SCARD_IOCTL_LOCATECARDSA:
121 return funcName ?
"SCardLocateCardsA" :
"SCARD_IOCTL_LOCATECARDSA";
123 case SCARD_IOCTL_LOCATECARDSW:
124 return funcName ?
"SCardLocateCardsW" :
"SCARD_IOCTL_LOCATECARDSW";
126 case SCARD_IOCTL_GETSTATUSCHANGEA:
127 return funcName ?
"SCardGetStatusChangeA" :
"SCARD_IOCTL_GETSTATUSCHANGEA";
129 case SCARD_IOCTL_GETSTATUSCHANGEW:
130 return funcName ?
"SCardGetStatusChangeW" :
"SCARD_IOCTL_GETSTATUSCHANGEW";
132 case SCARD_IOCTL_CANCEL:
133 return funcName ?
"SCardCancel" :
"SCARD_IOCTL_CANCEL";
135 case SCARD_IOCTL_CONNECTA:
136 return funcName ?
"SCardConnectA" :
"SCARD_IOCTL_CONNECTA";
138 case SCARD_IOCTL_CONNECTW:
139 return funcName ?
"SCardConnectW" :
"SCARD_IOCTL_CONNECTW";
141 case SCARD_IOCTL_RECONNECT:
142 return funcName ?
"SCardReconnect" :
"SCARD_IOCTL_RECONNECT";
144 case SCARD_IOCTL_DISCONNECT:
145 return funcName ?
"SCardDisconnect" :
"SCARD_IOCTL_DISCONNECT";
147 case SCARD_IOCTL_BEGINTRANSACTION:
148 return funcName ?
"SCardBeginTransaction" :
"SCARD_IOCTL_BEGINTRANSACTION";
150 case SCARD_IOCTL_ENDTRANSACTION:
151 return funcName ?
"SCardEndTransaction" :
"SCARD_IOCTL_ENDTRANSACTION";
153 case SCARD_IOCTL_STATE:
154 return funcName ?
"SCardState" :
"SCARD_IOCTL_STATE";
156 case SCARD_IOCTL_STATUSA:
157 return funcName ?
"SCardStatusA" :
"SCARD_IOCTL_STATUSA";
159 case SCARD_IOCTL_STATUSW:
160 return funcName ?
"SCardStatusW" :
"SCARD_IOCTL_STATUSW";
162 case SCARD_IOCTL_TRANSMIT:
163 return funcName ?
"SCardTransmit" :
"SCARD_IOCTL_TRANSMIT";
165 case SCARD_IOCTL_CONTROL:
166 return funcName ?
"SCardControl" :
"SCARD_IOCTL_CONTROL";
168 case SCARD_IOCTL_GETATTRIB:
169 return funcName ?
"SCardGetAttrib" :
"SCARD_IOCTL_GETATTRIB";
171 case SCARD_IOCTL_SETATTRIB:
172 return funcName ?
"SCardSetAttrib" :
"SCARD_IOCTL_SETATTRIB";
174 case SCARD_IOCTL_ACCESSSTARTEDEVENT:
175 return funcName ?
"SCardAccessStartedEvent" :
"SCARD_IOCTL_ACCESSSTARTEDEVENT";
177 case SCARD_IOCTL_LOCATECARDSBYATRA:
178 return funcName ?
"SCardLocateCardsByATRA" :
"SCARD_IOCTL_LOCATECARDSBYATRA";
180 case SCARD_IOCTL_LOCATECARDSBYATRW:
181 return funcName ?
"SCardLocateCardsByATRB" :
"SCARD_IOCTL_LOCATECARDSBYATRW";
183 case SCARD_IOCTL_READCACHEA:
184 return funcName ?
"SCardReadCacheA" :
"SCARD_IOCTL_READCACHEA";
186 case SCARD_IOCTL_READCACHEW:
187 return funcName ?
"SCardReadCacheW" :
"SCARD_IOCTL_READCACHEW";
189 case SCARD_IOCTL_WRITECACHEA:
190 return funcName ?
"SCardWriteCacheA" :
"SCARD_IOCTL_WRITECACHEA";
192 case SCARD_IOCTL_WRITECACHEW:
193 return funcName ?
"SCardWriteCacheW" :
"SCARD_IOCTL_WRITECACHEW";
195 case SCARD_IOCTL_GETTRANSMITCOUNT:
196 return funcName ?
"SCardGetTransmitCount" :
"SCARD_IOCTL_GETTRANSMITCOUNT";
198 case SCARD_IOCTL_RELEASETARTEDEVENT:
199 return funcName ?
"SCardReleaseStartedEvent" :
"SCARD_IOCTL_RELEASETARTEDEVENT";
201 case SCARD_IOCTL_GETREADERICON:
202 return funcName ?
"SCardGetReaderIcon" :
"SCARD_IOCTL_GETREADERICON";
204 case SCARD_IOCTL_GETDEVICETYPEID:
205 return funcName ?
"SCardGetDeviceTypeId" :
"SCARD_IOCTL_GETDEVICETYPEID";
208 return funcName ?
"SCardUnknown" :
"SCARD_IOCTL_UNKNOWN";
212const char* rdpdr_component_string(UINT16 component)
217 return "RDPDR_CTYP_PRN";
218 case RDPDR_CTYP_CORE:
219 return "RDPDR_CTYP_CORE";
225const char* rdpdr_packetid_string(UINT16 packetid)
229 case PAKID_CORE_SERVER_ANNOUNCE:
230 return "PAKID_CORE_SERVER_ANNOUNCE";
231 case PAKID_CORE_CLIENTID_CONFIRM:
232 return "PAKID_CORE_CLIENTID_CONFIRM";
233 case PAKID_CORE_CLIENT_NAME:
234 return "PAKID_CORE_CLIENT_NAME";
235 case PAKID_CORE_DEVICELIST_ANNOUNCE:
236 return "PAKID_CORE_DEVICELIST_ANNOUNCE";
237 case PAKID_CORE_DEVICE_REPLY:
238 return "PAKID_CORE_DEVICE_REPLY";
239 case PAKID_CORE_DEVICE_IOREQUEST:
240 return "PAKID_CORE_DEVICE_IOREQUEST";
241 case PAKID_CORE_DEVICE_IOCOMPLETION:
242 return "PAKID_CORE_DEVICE_IOCOMPLETION";
243 case PAKID_CORE_SERVER_CAPABILITY:
244 return "PAKID_CORE_SERVER_CAPABILITY";
245 case PAKID_CORE_CLIENT_CAPABILITY:
246 return "PAKID_CORE_CLIENT_CAPABILITY";
247 case PAKID_CORE_DEVICELIST_REMOVE:
248 return "PAKID_CORE_DEVICELIST_REMOVE";
249 case PAKID_CORE_USER_LOGGEDON:
250 return "PAKID_CORE_USER_LOGGEDON";
251 case PAKID_PRN_CACHE_DATA:
252 return "PAKID_PRN_CACHE_DATA";
253 case PAKID_PRN_USING_XPS:
254 return "PAKID_PRN_USING_XPS";
260BOOL rdpdr_write_iocompletion_header(
wStream* out, UINT32 DeviceId, UINT32 CompletionId,
264 Stream_SetPosition(out, 0);
265 if (!Stream_EnsureRemainingCapacity(out, 16))
267 Stream_Write_UINT16(out, RDPDR_CTYP_CORE);
268 Stream_Write_UINT16(out, PAKID_CORE_DEVICE_IOCOMPLETION);
269 Stream_Write_UINT32(out, DeviceId);
270 Stream_Write_UINT32(out, CompletionId);
271 Stream_Write_INT32(out, ioStatus);
276static void rdpdr_dump_packet(wLog* log, DWORD lvl,
wStream* s,
const char* custom, BOOL send)
278 if (!WLog_IsLevelActive(log, lvl))
281 const size_t gpos = Stream_GetPosition(s);
282 const size_t pos = send ? Stream_GetPosition(s) : Stream_Length(s);
284 UINT16 component = 0;
287 Stream_SetPosition(s, 0);
290 Stream_Read_UINT16(s, component);
292 Stream_Read_UINT16(s, packetid);
296 case PAKID_CORE_SERVER_ANNOUNCE:
297 case PAKID_CORE_CLIENTID_CONFIRM:
299 UINT16 versionMajor = 0;
300 UINT16 versionMinor = 0;
304 Stream_Read_UINT16(s, versionMajor);
306 Stream_Read_UINT16(s, versionMinor);
308 Stream_Read_UINT32(s, clientID);
310 "%s [%s | %s] [version:%" PRIu16
".%" PRIu16
"][id:0x%08" PRIx32
312 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
313 versionMajor, versionMinor, clientID, pos);
316 case PAKID_CORE_CLIENT_NAME:
318 char name[256] = { 0 };
319 UINT32 unicodeFlag = 0;
321 UINT32 computerNameLen = 0;
323 Stream_Read_UINT32(s, unicodeFlag);
325 Stream_Read_UINT32(s, codePage);
327 Stream_Read_UINT32(s, computerNameLen);
328 if (pos >= 16 + computerNameLen)
330 if (unicodeFlag == 0)
331 Stream_Read(s, name, MIN(
sizeof(name), computerNameLen));
333 (
void)ConvertWCharNToUtf8(Stream_ConstPointer(s),
334 computerNameLen /
sizeof(WCHAR), name,
sizeof(name));
337 "%s [%s | %s] [ucs:%" PRIu32
"|cp:%" PRIu32
"][len:0x%08" PRIx32
339 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
340 unicodeFlag, codePage, computerNameLen, name, pos);
344 case PAKID_CORE_DEVICE_IOREQUEST:
346 UINT32 CompletionId = 0;
349 UINT32 MajorFunction = 0;
350 UINT32 MinorFunction = 0;
353 Stream_Read_UINT32(s, deviceID);
355 Stream_Read_UINT32(s, FileId);
357 Stream_Read_UINT32(s, CompletionId);
359 Stream_Read_UINT32(s, MajorFunction);
361 Stream_Read_UINT32(s, MinorFunction);
363 "%s [%s | %s] [0x%08" PRIx32
"] FileId=0x%08" PRIx32
364 ", CompletionId=0x%08" PRIx32
", MajorFunction=0x%08" PRIx32
365 ", MinorFunction=0x%08" PRIx32
" -> %" PRIuz,
366 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
367 deviceID, FileId, CompletionId, MajorFunction, MinorFunction, pos);
370 case PAKID_CORE_DEVICE_IOCOMPLETION:
372 UINT32 completionID = 0;
376 Stream_Read_UINT32(s, deviceID);
378 Stream_Read_UINT32(s, completionID);
380 Stream_Read_UINT32(s, ioStatus);
383 "%s [%s | %s] [0x%08" PRIx32
"] completionID=0x%08" PRIx32
384 ", ioStatus=0x%08" PRIx32
" -> %" PRIuz,
385 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
386 deviceID, completionID, ioStatus, pos);
389 case PAKID_CORE_DEVICE_REPLY:
395 Stream_Read_UINT32(s, deviceID);
397 Stream_Read_UINT32(s, status);
399 "%s [%s | %s] [id:0x%08" PRIx32
",status=0x%08" PRIx32
"] -> %" PRIuz,
400 custom, rdpdr_component_string(component), rdpdr_packetid_string(packetid),
401 deviceID, status, pos);
404 case PAKID_CORE_CLIENT_CAPABILITY:
405 case PAKID_CORE_SERVER_CAPABILITY:
407 UINT16 numCapabilities = 0;
409 Stream_Read_UINT16(s, numCapabilities);
411 Stream_Seek_UINT16(s);
412 WLog_Print(log, lvl,
"%s [%s | %s] [caps:%" PRIu16
"] -> %" PRIuz, custom,
413 rdpdr_component_string(component), rdpdr_packetid_string(packetid),
414 numCapabilities, pos);
415 for (UINT16 x = 0; x < numCapabilities; x++)
418 const UINT error = rdpdr_read_capset_header(log, s, &header);
419 if (error == CHANNEL_RC_OK)
420 Stream_Seek(s, header.CapabilityLength);
424 case PAKID_CORE_DEVICELIST_ANNOUNCE:
430 Stream_Read_UINT32(s, count);
432 WLog_Print(log, lvl,
"%s [%s | %s] [%" PRIu32
"] -> %" PRIuz, custom,
433 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
436 for (UINT32 x = 0; x < count; x++)
443 Stream_Read_UINT32(s, device.DeviceType);
444 Stream_Read_UINT32(s, device.DeviceId);
445 Stream_Read(s, device.PreferredDosName, 8);
446 Stream_Read_UINT32(s, device.DeviceDataLength);
447 device.DeviceData = Stream_Pointer(s);
449 offset += device.DeviceDataLength;
452 "%s [announce][%" PRIu32
"] %s [0x%08" PRIx32
453 "] '%s' [DeviceDataLength=%" PRIu32
"]",
455 device.PreferredDosName, device.DeviceDataLength);
459 case PAKID_CORE_DEVICELIST_REMOVE:
465 Stream_Read_UINT32(s, count);
467 WLog_Print(log, lvl,
"%s [%s | %s] [%" PRIu32
"] -> %" PRIuz, custom,
468 rdpdr_component_string(component), rdpdr_packetid_string(packetid), count,
471 for (UINT32 x = 0; x < count; x++)
477 Stream_Read_UINT32(s,
id);
479 WLog_Print(log, lvl,
"%s [remove][%" PRIu32
"] id=%" PRIu32, custom, x,
id);
483 case PAKID_CORE_USER_LOGGEDON:
484 WLog_Print(log, lvl,
"%s [%s | %s] -> %" PRIuz, custom,
485 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
489 WLog_Print(log, lvl,
"%s [%s | %s] -> %" PRIuz, custom,
490 rdpdr_component_string(component), rdpdr_packetid_string(packetid), pos);
496 Stream_SetPosition(s, gpos);
499void rdpdr_dump_received_packet(wLog* log, DWORD lvl,
wStream* s,
const char* custom)
501 rdpdr_dump_packet(log, lvl, s, custom, FALSE);
504void rdpdr_dump_send_packet(wLog* log, DWORD lvl,
wStream* s,
const char* custom)
506 rdpdr_dump_packet(log, lvl, s, custom, TRUE);
509const char* rdpdr_irp_string(UINT32 major)
514 return "IRP_MJ_CREATE";
516 return "IRP_MJ_CLOSE";
518 return "IRP_MJ_READ";
520 return "IRP_MJ_WRITE";
521 case IRP_MJ_DEVICE_CONTROL:
522 return "IRP_MJ_DEVICE_CONTROL";
523 case IRP_MJ_QUERY_VOLUME_INFORMATION:
524 return "IRP_MJ_QUERY_VOLUME_INFORMATION";
525 case IRP_MJ_SET_VOLUME_INFORMATION:
526 return "IRP_MJ_SET_VOLUME_INFORMATION";
527 case IRP_MJ_QUERY_INFORMATION:
528 return "IRP_MJ_QUERY_INFORMATION";
529 case IRP_MJ_SET_INFORMATION:
530 return "IRP_MJ_SET_INFORMATION";
531 case IRP_MJ_DIRECTORY_CONTROL:
532 return "IRP_MJ_DIRECTORY_CONTROL";
533 case IRP_MJ_LOCK_CONTROL:
534 return "IRP_MJ_LOCK_CONTROL";
536 return "IRP_UNKNOWN";
540const char* rdpdr_cap_type_string(UINT16 capability)
544 case CAP_GENERAL_TYPE:
545 return "CAP_GENERAL_TYPE";
546 case CAP_PRINTER_TYPE:
547 return "CAP_PRINTER_TYPE";
549 return "CAP_PORT_TYPE";
551 return "CAP_DRIVE_TYPE";
552 case CAP_SMARTCARD_TYPE:
553 return "CAP_SMARTCARD_TYPE";
555 return "CAP_UNKNOWN";
561 WINPR_ASSERT(header);
562 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
563 return ERROR_INVALID_DATA;
565 Stream_Read_UINT16(s, header->CapabilityType);
566 Stream_Read_UINT16(s, header->CapabilityLength);
567 Stream_Read_UINT32(s, header->Version);
569 WLog_Print(log, WLOG_TRACE,
570 "capability %s [0x%04" PRIx16
"] got version %" PRIu32
", length %" PRIu16,
571 rdpdr_cap_type_string(header->CapabilityType), header->CapabilityType,
572 header->Version, header->CapabilityLength);
573 if (header->CapabilityLength < 8)
575 WLog_Print(log, WLOG_ERROR,
"capability %s got short length %" PRIu32,
576 rdpdr_cap_type_string(header->CapabilityType), header->CapabilityLength);
577 return ERROR_INVALID_DATA;
579 header->CapabilityLength -= 8;
580 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, header->CapabilityLength))
581 return ERROR_INVALID_DATA;
582 return CHANNEL_RC_OK;
587 WINPR_ASSERT(header);
588 WINPR_ASSERT(header->CapabilityLength >= 8);
590 if (!Stream_EnsureRemainingCapacity(s, header->CapabilityLength))
592 WLog_Print(log, WLOG_ERROR,
"not enough data in stream!");
593 return ERROR_INVALID_DATA;
596 WLog_Print(log, WLOG_TRACE,
"writing capability %s version %" PRIu32
", length %" PRIu16,
597 rdpdr_cap_type_string(header->CapabilityType), header->Version,
598 header->CapabilityLength);
599 Stream_Write_UINT16(s, header->CapabilityType);
600 Stream_Write_UINT16(s, header->CapabilityLength);
601 Stream_Write_UINT32(s, header->Version);
602 return CHANNEL_RC_OK;
FREERDP_API const char * freerdp_rdpdr_dtyp_string(UINT32 type)
Returns a string representation of RDPDR_DTYP_*.