FreeRDP
Loading...
Searching...
No Matches
smartcard_pack.c
1
24#include <freerdp/config.h>
25
26#include <winpr/crt.h>
27#include <winpr/print.h>
28
29#include <freerdp/channels/scard.h>
30#include <freerdp/utils/smartcard_pack.h>
31#include "smartcard_pack.h"
32
33#include <freerdp/log.h>
34#define SCARD_TAG FREERDP_TAG("scard.pack")
35
36static const DWORD g_LogLevel = WLOG_DEBUG;
37
38static wLog* scard_log(void)
39{
40 static wLog* log = nullptr;
41 if (!log)
42 log = WLog_Get(SCARD_TAG);
43 return log;
44}
45
46#define smartcard_unpack_redir_scard_context(log, s, context, index, ndr) \
47 smartcard_unpack_redir_scard_context_((log), (s), (context), (index), (ndr), __FILE__, \
48 __func__, __LINE__)
49#define smartcard_unpack_redir_scard_handle(log, s, context, index) \
50 smartcard_unpack_redir_scard_handle_((log), (s), (context), (index), __FILE__, __func__, \
51 __LINE__)
52
53WINPR_ATTR_NODISCARD static LONG
54smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
55 UINT32* index, UINT32* ppbContextNdrPtr, const char* file,
56 const char* function, size_t line);
57WINPR_ATTR_NODISCARD static LONG
58smartcard_pack_redir_scard_context(wLog* log, wStream* s, const REDIR_SCARDCONTEXT* context,
59 UINT32* index);
60WINPR_ATTR_NODISCARD static LONG
61smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
62 UINT32* index, const char* file, const char* function,
63 size_t line);
64WINPR_ATTR_NODISCARD static LONG smartcard_pack_redir_scard_handle(wLog* log, wStream* s,
65 const REDIR_SCARDHANDLE* handle,
66 UINT32* index);
67WINPR_ATTR_NODISCARD static LONG
68smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s, UINT32 pbContextNdrPtr,
69 REDIR_SCARDCONTEXT* context);
70WINPR_ATTR_NODISCARD static LONG
71smartcard_pack_redir_scard_context_ref(wLog* log, wStream* s, const REDIR_SCARDCONTEXT* context);
72
73WINPR_ATTR_NODISCARD static LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s,
74 REDIR_SCARDHANDLE* handle);
75WINPR_ATTR_NODISCARD static LONG
76smartcard_pack_redir_scard_handle_ref(wLog* log, wStream* s, const REDIR_SCARDHANDLE* handle);
77
78typedef enum
79{
80 NDR_PTR_FULL,
81 NDR_PTR_SIMPLE,
82 NDR_PTR_FIXED
83} ndr_ptr_t;
84
85/* Reads a NDR pointer and checks if the value read has the expected relative
86 * addressing */
87#define smartcard_ndr_pointer_read(log, s, index, ptr) \
88 smartcard_ndr_pointer_read_((log), (s), (index), (ptr), __FILE__, __func__, __LINE__)
89static BOOL smartcard_ndr_pointer_read_(wLog* log, wStream* s, UINT32* index, UINT32* ptr,
90 const char* file, const char* fkt, size_t line)
91{
92 const UINT32 expect = 0x20000 + (*index) * 4;
93 UINT32 ndrPtr = 0;
94 WINPR_UNUSED(file);
95 if (!s)
96 return FALSE;
97 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
98 return FALSE;
99
100 Stream_Read_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
101 if (ptr)
102 *ptr = ndrPtr;
103 if (expect != ndrPtr)
104 {
105 /* Allow nullptr pointer if we read the result */
106 if (ptr && (ndrPtr == 0))
107 return TRUE;
108 WLog_Print(log, WLOG_WARN,
109 "[%s:%" PRIuz "] Read context pointer 0x%08" PRIx32 ", expected 0x%08" PRIx32,
110 fkt, line, ndrPtr, expect);
111 return FALSE;
112 }
113
114 (*index) = (*index) + 1;
115 return TRUE;
116}
117
118WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_ex(wLog* log, wStream* s, BYTE** data,
119 size_t min, size_t elementSize,
120 const ndr_ptr_t type, size_t* plen)
121{
122 size_t len = 0;
123 size_t offset = 0;
124 size_t len2 = 0;
125 void* r = nullptr;
126 size_t required = 0;
127
128 *data = nullptr;
129 if (plen)
130 *plen = 0;
131
132 switch (type)
133 {
134 case NDR_PTR_FULL:
135 required = 12;
136 break;
137 case NDR_PTR_SIMPLE:
138 required = 4;
139 break;
140 case NDR_PTR_FIXED:
141 required = min;
142 break;
143 default:
144 return STATUS_INVALID_PARAMETER;
145 }
146
147 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, required))
148 return STATUS_BUFFER_TOO_SMALL;
149
150 switch (type)
151 {
152 case NDR_PTR_FULL:
153 Stream_Read_UINT32(s, len);
154 Stream_Read_UINT32(s, offset);
155 Stream_Read_UINT32(s, len2);
156 if (len != offset + len2)
157 {
158 WLog_Print(log, WLOG_ERROR,
159 "Invalid data when reading full NDR pointer: total=%" PRIuz
160 ", offset=%" PRIuz ", remaining=%" PRIuz,
161 len, offset, len2);
162 return STATUS_BUFFER_TOO_SMALL;
163 }
164 break;
165 case NDR_PTR_SIMPLE:
166 Stream_Read_UINT32(s, len);
167
168 if ((len != min) && (min > 0))
169 {
170 WLog_Print(log, WLOG_ERROR,
171 "Invalid data when reading simple NDR pointer: total=%" PRIuz
172 ", expected=%" PRIuz,
173 len, min);
174 return STATUS_BUFFER_TOO_SMALL;
175 }
176 break;
177 case NDR_PTR_FIXED:
178 len = (UINT32)min;
179 break;
180 default:
181 return STATUS_INVALID_PARAMETER;
182 }
183
184 if (min > len)
185 {
186 WLog_Print(log, WLOG_ERROR,
187 "Invalid length read from NDR pointer, minimum %" PRIuz ", got %" PRIuz, min,
188 len);
189 return STATUS_DATA_ERROR;
190 }
191
192 if (len > SIZE_MAX / 2)
193 return STATUS_BUFFER_TOO_SMALL;
194
195 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, elementSize))
196 return STATUS_BUFFER_TOO_SMALL;
197
198 len *= elementSize;
199
200 /* Ensure proper '\0' termination for all kinds of unicode strings
201 * as we do not know if the data from the wire contains one.
202 */
203 r = calloc(len + sizeof(WCHAR), sizeof(CHAR));
204 if (!r)
205 return SCARD_E_NO_MEMORY;
206 Stream_Read(s, r, len);
207 const LONG pad = smartcard_unpack_read_size_align(s, len, 4);
208 if (pad < 0)
209 {
210 free(r);
211 return STATUS_INVALID_PARAMETER;
212 }
213 *data = r;
214 if (plen)
215 *plen = len; /* payload bytes only, excluding the NDR alignment padding */
216 return STATUS_SUCCESS;
217}
218
219WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read(wLog* log, wStream* s, BYTE** data, size_t min,
220 size_t elementSize, const ndr_ptr_t type)
221{
222 return smartcard_ndr_read_ex(log, s, data, min, elementSize, type, nullptr);
223}
224
225static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, UINT32 length)
226{
227 const UINT32 ndrPtr = 0x20000 + (*index) * 4;
228
229 if (!s)
230 return FALSE;
231 if (!Stream_EnsureRemainingCapacity(s, 4))
232 return FALSE;
233
234 if (length > 0)
235 {
236 Stream_Write_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
237 (*index) = (*index) + 1;
238 }
239 else
240 Stream_Write_UINT32(s, 0);
241 return TRUE;
242}
243
244WINPR_ATTR_NODISCARD static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size,
245 UINT32 elementSize, const ndr_ptr_t type)
246{
247 const UINT32 offset = 0;
248 const UINT32 len = size;
249 const UINT32 dataLen = size * elementSize;
250 size_t required = 0;
251
252 if (size == 0)
253 return SCARD_S_SUCCESS;
254
255 switch (type)
256 {
257 case NDR_PTR_FULL:
258 required = 12;
259 break;
260 case NDR_PTR_SIMPLE:
261 required = 4;
262 break;
263 case NDR_PTR_FIXED:
264 required = 0;
265 break;
266 default:
267 return SCARD_E_INVALID_PARAMETER;
268 }
269
270 if (!Stream_EnsureRemainingCapacity(s, required + dataLen + 4ull))
271 return STATUS_BUFFER_TOO_SMALL;
272
273 switch (type)
274 {
275 case NDR_PTR_FULL:
276 Stream_Write_UINT32(s, len);
277 Stream_Write_UINT32(s, offset);
278 Stream_Write_UINT32(s, len);
279 break;
280 case NDR_PTR_SIMPLE:
281 Stream_Write_UINT32(s, len);
282 break;
283 case NDR_PTR_FIXED:
284 break;
285 default:
286 return SCARD_E_INVALID_PARAMETER;
287 }
288
289 if (data)
290 Stream_Write(s, data, dataLen);
291 else
292 Stream_Zero(s, dataLen);
293 return smartcard_pack_write_size_align(s, dataLen, 4);
294}
295
296WINPR_ATTR_NODISCARD static LONG smartcard_ndr_write_state(wStream* s,
297 const ReaderState_Return* data,
298 UINT32 size, const ndr_ptr_t type)
299{
300 union
301 {
302 const ReaderState_Return* reader;
303 const BYTE* data;
304 } cnv;
305
306 WINPR_ASSERT(data || (size == 0));
307 cnv.reader = data;
308
309 for (size_t x = 0; x < size; x++)
310 {
311 const ReaderState_Return* cur = &data[x];
312 if (!smartcard_reader_state_return_is_valid(x, cur))
313 return SCARD_E_INVALID_ATR;
314 }
315 return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
316}
317
318WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_state(wLog* log, wStream* s,
319 ReaderState_Return** data, size_t min,
320 const ndr_ptr_t type)
321{
322 union
323 {
324 ReaderState_Return** ppc;
325 BYTE** ppv;
326 } u;
327
328 WINPR_ASSERT(data);
329 u.ppc = data;
330
331 size_t len = 0;
332 const LONG status =
333 smartcard_ndr_read_ex(log, s, u.ppv, min, sizeof(ReaderState_Return), type, &len);
334 if (status != SCARD_S_SUCCESS)
335 return status;
336
337 if (len / sizeof(ReaderState_Return) < min)
338 return SCARD_E_INVALID_VALUE;
339
340 for (size_t x = 0; x < min; x++)
341 {
342 const ReaderState_Return* cur = &(*data)[x];
343 if (!smartcard_reader_state_return_is_valid(x, cur))
344 return SCARD_E_INVALID_ATR;
345 }
346 return status;
347}
348
349WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s,
350 LocateCards_ATRMask** data, size_t min,
351 const ndr_ptr_t type)
352{
353 union
354 {
356 BYTE** ppv;
357 } u;
358 u.ppc = data;
359 const LONG status = smartcard_ndr_read(log, s, u.ppv, min, sizeof(LocateCards_ATRMask), type);
360 if (status != SCARD_S_SUCCESS)
361 return status;
362
363 /* [MS-RDPESC] 2.2.1.5: cbAtr is range(0..36), the number of valid bytes in the fixed
364 * rgbAtr/rgbMask arrays. A larger value walks past them when the mask is compared byte
365 * by byte, so reject it here rather than trusting the wire value. */
366 LocateCards_ATRMask* masks = *data;
367 for (size_t x = 0; x < min; x++)
368 {
369 const UINT32 val = winpr_Data_Get_UINT32(&masks[x].cbAtr);
370 if (val > ARRAYSIZE(masks[x].rgbAtr))
371 {
372 WLog_Print(log, WLOG_ERROR,
373 "LocateCards_ATRMask[%" PRIuz "]::cbAtr %" PRIu32 " exceeds %" PRIuz, x, val,
374 (size_t)ARRAYSIZE(masks[x].rgbAtr));
375 free(*data);
376 *data = nullptr;
377 return STATUS_DATA_ERROR;
378 }
379 }
380 return SCARD_S_SUCCESS;
381}
382
383WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_fixed_string_a(wLog* log, wStream* s,
384 CHAR** data, size_t min,
385 const ndr_ptr_t type)
386{
387 union
388 {
389 CHAR** ppc;
390 BYTE** ppv;
391 } u;
392 u.ppc = data;
393 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(CHAR), type);
394}
395
396WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_fixed_string_w(wLog* log, wStream* s,
397 WCHAR** data, size_t min,
398 const ndr_ptr_t type)
399{
400 union
401 {
402 WCHAR** ppc;
403 BYTE** ppv;
404 } u;
405 u.ppc = data;
406 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(WCHAR), type);
407}
408
409WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_a(wLog* log, wStream* s, CHAR** data,
410 const ndr_ptr_t type)
411{
412 union
413 {
414 CHAR** ppc;
415 BYTE** ppv;
416 } u;
417 u.ppc = data;
418 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(CHAR), type);
419}
420
421WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data,
422 const ndr_ptr_t type)
423{
424 union
425 {
426 WCHAR** ppc;
427 BYTE** ppv;
428 } u;
429 u.ppc = data;
430 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
431}
432
433WINPR_ATTR_NODISCARD static LONG smartcard_ndr_write_w(wStream* s, const WCHAR* data, UINT32 size,
434 const ndr_ptr_t type)
435{
436 union
437 {
438 const WCHAR* wz;
439 const BYTE* bp;
440 } cnv;
441 cnv.wz = data;
442 return smartcard_ndr_write(s, cnv.bp, size, sizeof(WCHAR), type);
443}
444
445WINPR_ATTR_NODISCARD static LONG smartcard_ndr_write_a(wStream* s, const CHAR* data, UINT32 size,
446 const ndr_ptr_t type)
447{
448 union
449 {
450 const CHAR* sz;
451 const BYTE* bp;
452 } cnv;
453 cnv.sz = data;
454 return smartcard_ndr_write(s, cnv.bp, size, sizeof(CHAR), type);
455}
456
457WINPR_ATTR_NODISCARD static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
458{
459 union
460 {
461 UUID** ppc;
462 BYTE** ppv;
463 } u;
464 u.ppc = data;
465 return smartcard_ndr_read(log, s, u.ppv, 1, sizeof(UUID), NDR_PTR_FIXED);
466}
467
468static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode)
469{
470 size_t length = 0;
471 union
472 {
473 const void* pv;
474 const char* sz;
475 const WCHAR* wz;
476 } string;
477 char* mszA = nullptr;
478
479 string.pv = in;
480
481 if (bytes < 1)
482 return nullptr;
483
484 if (in == nullptr)
485 return nullptr;
486
487 if (unicode)
488 {
489 mszA = ConvertMszWCharNToUtf8Alloc(string.wz, bytes / sizeof(WCHAR), &length);
490 if (!mszA)
491 return nullptr;
492 }
493 else
494 {
495 mszA = (char*)calloc(bytes, sizeof(char));
496 if (!mszA)
497 return nullptr;
498 CopyMemory(mszA, string.sz, bytes - 1);
499 length = bytes;
500 }
501
502 if (length < 1)
503 {
504 free(mszA);
505 return nullptr;
506 }
507 for (size_t index = 0; index < length - 1; index++)
508 {
509 if (mszA[index] == '\0')
510 mszA[index] = ',';
511 }
512
513 return mszA;
514}
515
516WINPR_ATTR_MALLOC(free, 1)
517static char* smartcard_create_msz_dump(const char* msz, size_t len)
518{
519 size_t bufferLen = len;
520 char* buffer = calloc(len + 1, 1);
521 if (!buffer)
522 return nullptr;
523
524 char* buf = buffer;
525 const char* cur = msz;
526
527 while ((len > 0) && cur && cur[0] != '\0' && (bufferLen > 0))
528 {
529 size_t clen = strnlen(cur, len);
530 int rc = _snprintf(buf, bufferLen, "%s", cur);
531 bufferLen -= (size_t)rc;
532 buf += rc;
533
534 cur += clen;
535 }
536
537 return buffer;
538}
539
540static void smartcard_msz_dump(wLog* log, DWORD level, const char* prefix, const void* data,
541 size_t len, UINT32 wchar)
542{
543 if (!WLog_IsLevelActive(log, level))
544 return;
545
546 char* tmp = nullptr;
547 const char* msz = WINPR_CXX_COMPAT_CAST(const char*, data);
548 size_t mszlen = len;
549 if (wchar)
550 {
551 tmp = ConvertMszWCharNToUtf8Alloc(data, len, &mszlen);
552 msz = tmp;
553 }
554
555 char* array = smartcard_create_msz_dump(msz, mszlen);
556 WLog_Print(log, level, "%s%s", prefix, array);
557 free(array);
558 free(tmp);
559}
560
561WINPR_ATTR_MALLOC(free, 1)
562static char* smartcard_create_array_dump(const void* pd, size_t len)
563{
564 const BYTE* data = pd;
565 int rc = 0;
566
567 size_t bufferLen = len * 4;
568 if (bufferLen < 32)
569 bufferLen = 32;
570 char* buffer = calloc(bufferLen + 1, 1);
571 if (!buffer)
572 return nullptr;
573 char* start = buffer;
574
575 WINPR_ASSERT(buffer || (bufferLen == 0));
576
577 if (!data && (len > 0))
578 {
579 (void)_snprintf(buffer, bufferLen, "{ nullptr [%" PRIuz "] }", len);
580 goto fail;
581 }
582
583 rc = _snprintf(buffer, bufferLen, "{ ");
584 if ((rc < 0) || ((size_t)rc >= bufferLen))
585 goto fail;
586 buffer += rc;
587 bufferLen -= (size_t)rc;
588
589 for (size_t x = 0; x < len; x++)
590 {
591 rc = _snprintf(buffer, bufferLen, "%02X", data[x]);
592 if ((rc < 0) || ((size_t)rc >= bufferLen))
593 goto fail;
594 buffer += rc;
595 bufferLen -= (size_t)rc;
596 }
597
598 rc = _snprintf(buffer, bufferLen, " }");
599 if ((rc < 0) || ((size_t)rc >= bufferLen))
600 goto fail;
601
602fail:
603 return start;
604}
605
606WINPR_ATTR_FORMAT_ARG(3, 7)
607static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const char* prefix,
608 const char* postfix, const void* data, size_t len, ...)
609{
610 if (!WLog_IsLevelActive(log, level))
611 return;
612
613 char* buffer = smartcard_create_array_dump(data, len);
614
615 char* fprefix = nullptr;
616 size_t flen = 0;
617 va_list ap = WINPR_C_ARRAY_INIT;
618 va_start(ap, len);
619 winpr_vasprintf(&fprefix, &flen, prefix, ap);
620 va_end(ap);
621 WLog_Print(log, level, "%s%s%s", fprefix, buffer, postfix);
622 free(buffer);
623 free(fprefix);
624}
625
626static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
627{
628 WINPR_ASSERT(pHandle);
629 smartcard_dump_array(log, g_LogLevel, "handle: ", "", pHandle->pbHandle, pHandle->cbHandle);
630}
631
632static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
633{
634 WINPR_ASSERT(phContext);
635 smartcard_dump_array(log, g_LogLevel, "hContext: ", "", phContext->pbContext,
636 phContext->cbContext);
637}
638
639static void smartcard_trace_context_and_string_call_a(wLog* log, const char* name,
640 const REDIR_SCARDCONTEXT* phContext,
641 const CHAR* sz)
642{
643 if (!WLog_IsLevelActive(log, g_LogLevel))
644 return;
645
646 WLog_Print(log, g_LogLevel, "%s {", name);
647 smartcard_log_context(log, phContext);
648 WLog_Print(log, g_LogLevel, " sz=%s", sz);
649
650 WLog_Print(log, g_LogLevel, "}");
651}
652
653static void smartcard_trace_context_and_string_call_w(wLog* log, const char* name,
654 const REDIR_SCARDCONTEXT* phContext,
655 const WCHAR* sz)
656{
657 char* tmp = nullptr;
658
659 if (!WLog_IsLevelActive(log, g_LogLevel))
660 return;
661
662 if (sz)
663 tmp = ConvertWCharToUtf8Alloc(sz, nullptr);
664
665 WLog_Print(log, g_LogLevel, "%s {", name);
666 smartcard_log_context(log, phContext);
667 WLog_Print(log, g_LogLevel, " sz=%s", tmp);
668 WLog_Print(log, g_LogLevel, "}");
669 free(tmp);
670}
671
672static void smartcard_trace_context_call(wLog* log, const Context_Call* call, const char* name)
673{
674 WINPR_ASSERT(call);
675
676 if (!WLog_IsLevelActive(log, g_LogLevel))
677 return;
678
679 WLog_Print(log, g_LogLevel, "%s_Call {", name);
680 smartcard_log_context(log, &call->handles.hContext);
681
682 WLog_Print(log, g_LogLevel, "}");
683}
684
685static void smartcard_trace_list_reader_groups_call(wLog* log, const ListReaderGroups_Call* call,
686 BOOL unicode)
687{
688 WINPR_ASSERT(call);
689
690 if (!WLog_IsLevelActive(log, g_LogLevel))
691 return;
692
693 WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Call {", unicode ? "W" : "A");
694 smartcard_log_context(log, &call->handles.hContext);
695
696 WLog_Print(log, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32,
697 call->fmszGroupsIsNULL, call->cchGroups);
698 WLog_Print(log, g_LogLevel, "}");
699}
700
701static void dump_reader_states_return(wLog* log, const ReaderState_Return* rgReaderStates,
702 UINT32 cReaders)
703{
704 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
705 for (UINT32 index = 0; index < cReaders; index++)
706 {
707 const ReaderState_Return* readerState = &rgReaderStates[index];
708 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
709 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
710 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
711 szCurrentState, readerState->dwCurrentState);
712 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
713 szEventState, readerState->dwEventState);
714 free(szCurrentState);
715 free(szEventState);
716
717 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
718 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
719 }
720}
721
722static void dump_reader_states_a(wLog* log, const SCARD_READERSTATEA* rgReaderStates,
723 UINT32 cReaders)
724{
725 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
726 for (UINT32 index = 0; index < cReaders; index++)
727 {
728 const SCARD_READERSTATEA* readerState = &rgReaderStates[index];
729
730 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
731 readerState->szReader, readerState->cbAtr);
732 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
733 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
734 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
735 szCurrentState, readerState->dwCurrentState);
736 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
737 szEventState, readerState->dwEventState);
738 free(szCurrentState);
739 free(szEventState);
740
741 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
742 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
743 }
744}
745
746static void dump_reader_states_w(wLog* log, const SCARD_READERSTATEW* rgReaderStates,
747 UINT32 cReaders)
748{
749 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
750 for (UINT32 index = 0; index < cReaders; index++)
751 {
752 const SCARD_READERSTATEW* readerState = &rgReaderStates[index];
753 char* buffer = ConvertWCharToUtf8Alloc(readerState->szReader, nullptr);
754 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
755 buffer, readerState->cbAtr);
756 free(buffer);
757 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
758 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
759 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
760 szCurrentState, readerState->dwCurrentState);
761 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
762 szEventState, readerState->dwEventState);
763 free(szCurrentState);
764 free(szEventState);
765
766 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
767 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
768 }
769}
770
771static void smartcard_trace_get_status_change_w_call(wLog* log, const GetStatusChangeW_Call* call)
772{
773 WINPR_ASSERT(call);
774
775 if (!WLog_IsLevelActive(log, g_LogLevel))
776 return;
777
778 WLog_Print(log, g_LogLevel, "GetStatusChangeW_Call {");
779 smartcard_log_context(log, &call->handles.hContext);
780
781 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
782 call->cReaders);
783
784 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
785
786 WLog_Print(log, g_LogLevel, "}");
787}
788
789static void smartcard_trace_list_reader_groups_return(wLog* log, const ListReaderGroups_Return* ret,
790 BOOL unicode)
791{
792 WINPR_ASSERT(ret);
793
794 if (!WLog_IsLevelActive(log, g_LogLevel))
795 return;
796
797 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
798
799 WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Return {", unicode ? "W" : "A");
800 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIx32 ")",
801 SCardGetErrorString(ret->ReturnCode),
802 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
803 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
804 WLog_Print(log, g_LogLevel, "}");
805 free(mszA);
806}
807
808static void smartcard_trace_list_readers_call(wLog* log, const ListReaders_Call* call, BOOL unicode)
809{
810 WINPR_ASSERT(call);
811
812 if (!WLog_IsLevelActive(log, g_LogLevel))
813 return;
814
815 char* mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode);
816
817 WLog_Print(log, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A");
818 smartcard_log_context(log, &call->handles.hContext);
819
820 WLog_Print(log, g_LogLevel,
821 "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32
822 " cchReaders: 0x%08" PRIX32 "",
823 call->cBytes, mszGroupsA, call->fmszReadersIsNULL, call->cchReaders);
824 WLog_Print(log, g_LogLevel, "}");
825
826 free(mszGroupsA);
827}
828
829static void smartcard_trace_locate_cards_by_atr_a_call(wLog* log,
830 const LocateCardsByATRA_Call* call)
831{
832 WINPR_ASSERT(call);
833
834 if (!WLog_IsLevelActive(log, g_LogLevel))
835 return;
836
837 WLog_Print(log, g_LogLevel, "LocateCardsByATRA_Call {");
838 smartcard_log_context(log, &call->handles.hContext);
839
840 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
841
842 WLog_Print(log, g_LogLevel, "}");
843}
844
845static void smartcard_trace_locate_cards_a_call(wLog* log, const LocateCardsA_Call* call)
846{
847 WINPR_ASSERT(call);
848
849 if (!WLog_IsLevelActive(log, g_LogLevel))
850 return;
851
852 WLog_Print(log, g_LogLevel, "LocateCardsA_Call {");
853 smartcard_log_context(log, &call->handles.hContext);
854 WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
855 smartcard_msz_dump(log, g_LogLevel, " mszCards=", call->mszCards, call->cBytes, FALSE);
856 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
857 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
858
859 WLog_Print(log, g_LogLevel, "}");
860}
861
862static void smartcard_trace_locate_cards_return(wLog* log, const LocateCards_Return* ret)
863{
864 WINPR_ASSERT(ret);
865
866 if (!WLog_IsLevelActive(log, g_LogLevel))
867 return;
868
869 WLog_Print(log, g_LogLevel, "LocateCards_Return {");
870 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
871 SCardGetErrorString(ret->ReturnCode),
872 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
873
874 if (ret->ReturnCode == SCARD_S_SUCCESS)
875 {
876 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, ret->cReaders);
877 }
878 WLog_Print(log, g_LogLevel, "}");
879}
880
881static void smartcard_trace_get_reader_icon_return(wLog* log, const GetReaderIcon_Return* ret)
882{
883 WINPR_ASSERT(ret);
884
885 if (!WLog_IsLevelActive(log, g_LogLevel))
886 return;
887
888 WLog_Print(log, g_LogLevel, "GetReaderIcon_Return {");
889 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
890 SCardGetErrorString(ret->ReturnCode),
891 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
892
893 if (ret->ReturnCode == SCARD_S_SUCCESS)
894 {
895 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
896 }
897 WLog_Print(log, g_LogLevel, "}");
898}
899
900static void smartcard_trace_get_transmit_count_return(wLog* log, const GetTransmitCount_Return* ret)
901{
902 WINPR_ASSERT(ret);
903
904 if (!WLog_IsLevelActive(log, g_LogLevel))
905 return;
906
907 WLog_Print(log, g_LogLevel, "GetTransmitCount_Return {");
908 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
909 SCardGetErrorString(ret->ReturnCode),
910 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
911
912 WLog_Print(log, g_LogLevel, " cTransmitCount=%" PRIu32, ret->cTransmitCount);
913 WLog_Print(log, g_LogLevel, "}");
914}
915
916static void smartcard_trace_read_cache_return(wLog* log, const ReadCache_Return* ret)
917{
918 WINPR_ASSERT(ret);
919
920 if (!WLog_IsLevelActive(log, g_LogLevel))
921 return;
922
923 WLog_Print(log, g_LogLevel, "ReadCache_Return {");
924 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
925 SCardGetErrorString(ret->ReturnCode),
926 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
927
928 if (ret->ReturnCode == SCARD_S_SUCCESS)
929 {
930 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
931 smartcard_dump_array(log, g_LogLevel, " cbData: ", "", ret->pbData, ret->cbDataLen);
932 }
933 WLog_Print(log, g_LogLevel, "}");
934}
935
936static void smartcard_trace_locate_cards_w_call(wLog* log, const LocateCardsW_Call* call)
937{
938 WINPR_ASSERT(call);
939
940 if (!WLog_IsLevelActive(log, g_LogLevel))
941 return;
942
943 WLog_Print(log, g_LogLevel, "LocateCardsW_Call {");
944 smartcard_log_context(log, &call->handles.hContext);
945 WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
946 smartcard_msz_dump(log, g_LogLevel, " sz2=", call->mszCards, call->cBytes, TRUE);
947 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
948 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
949 WLog_Print(log, g_LogLevel, "}");
950}
951
952static void smartcard_trace_list_readers_return(wLog* log, const ListReaders_Return* ret,
953 BOOL unicode)
954{
955 WINPR_ASSERT(ret);
956
957 if (!WLog_IsLevelActive(log, g_LogLevel))
958 return;
959
960 WLog_Print(log, g_LogLevel, "ListReaders%s_Return {", unicode ? "W" : "A");
961 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
962 SCardGetErrorString(ret->ReturnCode),
963 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
964
965 if (ret->ReturnCode != SCARD_S_SUCCESS)
966 {
967 WLog_Print(log, g_LogLevel, "}");
968 return;
969 }
970
971 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
972
973 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
974 WLog_Print(log, g_LogLevel, "}");
975 free(mszA);
976}
977
978static void smartcard_trace_get_status_change_return(wLog* log, const GetStatusChange_Return* ret,
979 BOOL unicode)
980{
981 WINPR_ASSERT(ret);
982
983 if (!WLog_IsLevelActive(log, g_LogLevel))
984 return;
985
986 WLog_Print(log, g_LogLevel, "GetStatusChange%s_Return {", unicode ? "W" : "A");
987 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
988 SCardGetErrorString(ret->ReturnCode),
989 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
990 WLog_Print(log, g_LogLevel, " cReaders: %" PRIu32 "", ret->cReaders);
991
992 dump_reader_states_return(log, ret->rgReaderStates, ret->cReaders);
993
994 if (!ret->rgReaderStates && (ret->cReaders > 0))
995 {
996 WLog_Print(log, g_LogLevel, " [INVALID STATE] rgReaderStates=nullptr, cReaders=%" PRIu32,
997 ret->cReaders);
998 }
999 else if (ret->ReturnCode != SCARD_S_SUCCESS)
1000 {
1001 WLog_Print(log, g_LogLevel, " [INVALID RETURN] rgReaderStates, cReaders=%" PRIu32,
1002 ret->cReaders);
1003 }
1004 else
1005 {
1006 for (UINT32 index = 0; index < ret->cReaders; index++)
1007 {
1008 const ReaderState_Return* rgReaderState = &(ret->rgReaderStates[index]);
1009 char* szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState);
1010 char* szEventState = SCardGetReaderStateString(rgReaderState->dwEventState);
1011 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")",
1012 index, szCurrentState, rgReaderState->dwCurrentState);
1013 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")",
1014 index, szEventState, rgReaderState->dwEventState);
1015 smartcard_dump_array(
1016 log, g_LogLevel, " [%" PRIu32 "]: cbAtr: %" PRIu32 " rgbAtr: ", "",
1017 rgReaderState->rgbAtr, rgReaderState->cbAtr, index, rgReaderState->cbAtr);
1018 free(szCurrentState);
1019 free(szEventState);
1020 }
1021 }
1022
1023 WLog_Print(log, g_LogLevel, "}");
1024}
1025
1026static void smartcard_trace_context_and_two_strings_a_call(wLog* log,
1027 const ContextAndTwoStringA_Call* call)
1028{
1029 WINPR_ASSERT(call);
1030
1031 if (!WLog_IsLevelActive(log, g_LogLevel))
1032 return;
1033
1034 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
1035 smartcard_log_context(log, &call->handles.hContext);
1036 WLog_Print(log, g_LogLevel, " sz1=%s", call->sz1);
1037 WLog_Print(log, g_LogLevel, " sz2=%s", call->sz2);
1038 WLog_Print(log, g_LogLevel, "}");
1039}
1040
1041static void smartcard_trace_context_and_two_strings_w_call(wLog* log,
1042 const ContextAndTwoStringW_Call* call)
1043{
1044 WINPR_ASSERT(call);
1045 char sz1[1024] = WINPR_C_ARRAY_INIT;
1046 char sz2[1024] = WINPR_C_ARRAY_INIT;
1047
1048 if (!WLog_IsLevelActive(log, g_LogLevel))
1049 return;
1050 if (call->sz1)
1051 (void)ConvertWCharToUtf8(call->sz1, sz1, ARRAYSIZE(sz1));
1052 if (call->sz2)
1053 (void)ConvertWCharToUtf8(call->sz2, sz2, ARRAYSIZE(sz2));
1054
1055 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
1056 smartcard_log_context(log, &call->handles.hContext);
1057 WLog_Print(log, g_LogLevel, " sz1=%s", sz1);
1058 WLog_Print(log, g_LogLevel, " sz2=%s", sz2);
1059 WLog_Print(log, g_LogLevel, "}");
1060}
1061
1062static void smartcard_trace_get_transmit_count_call(wLog* log, const GetTransmitCount_Call* call)
1063{
1064 WINPR_ASSERT(call);
1065
1066 if (!WLog_IsLevelActive(log, g_LogLevel))
1067 return;
1068
1069 WLog_Print(log, g_LogLevel, "GetTransmitCount_Call {");
1070 smartcard_log_context(log, &call->handles.hContext);
1071 smartcard_log_redir_handle(log, &call->handles.hCard);
1072
1073 WLog_Print(log, g_LogLevel, "}");
1074}
1075
1076static void smartcard_trace_write_cache_a_call(wLog* log, const WriteCacheA_Call* call)
1077{
1078 WINPR_ASSERT(call);
1079
1080 if (!WLog_IsLevelActive(log, g_LogLevel))
1081 return;
1082
1083 WLog_Print(log, g_LogLevel, "WriteCacheA_Call {");
1084
1085 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
1086
1087 smartcard_log_context(log, &call->Common.handles.hContext);
1088 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1089 sizeof(UUID));
1090 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1091 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1092 smartcard_dump_array(log, g_LogLevel, " pbData=", "", call->Common.pbData,
1093 call->Common.cbDataLen);
1094 WLog_Print(log, g_LogLevel, "}");
1095}
1096
1097static void smartcard_trace_write_cache_w_call(wLog* log, const WriteCacheW_Call* call)
1098{
1099 WINPR_ASSERT(call);
1100 char tmp[1024] = WINPR_C_ARRAY_INIT;
1101
1102 if (!WLog_IsLevelActive(log, g_LogLevel))
1103 return;
1104
1105 WLog_Print(log, g_LogLevel, "WriteCacheW_Call {");
1106
1107 if (call->szLookupName)
1108 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1109 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
1110
1111 smartcard_log_context(log, &call->Common.handles.hContext);
1112 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1113 sizeof(UUID));
1114 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1115 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1116 smartcard_dump_array(log, g_LogLevel, " pbData=", "", call->Common.pbData,
1117 call->Common.cbDataLen);
1118 WLog_Print(log, g_LogLevel, "}");
1119}
1120
1121static void smartcard_trace_read_cache_a_call(wLog* log, const ReadCacheA_Call* call)
1122{
1123 WINPR_ASSERT(call);
1124
1125 if (!WLog_IsLevelActive(log, g_LogLevel))
1126 return;
1127
1128 WLog_Print(log, g_LogLevel, "ReadCacheA_Call {");
1129
1130 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
1131 smartcard_log_context(log, &call->Common.handles.hContext);
1132 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1133 sizeof(UUID));
1134 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1135 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1136 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1137
1138 WLog_Print(log, g_LogLevel, "}");
1139}
1140
1141static void smartcard_trace_read_cache_w_call(wLog* log, const ReadCacheW_Call* call)
1142{
1143 WINPR_ASSERT(call);
1144 char tmp[1024] = WINPR_C_ARRAY_INIT;
1145
1146 if (!WLog_IsLevelActive(log, g_LogLevel))
1147 return;
1148
1149 WLog_Print(log, g_LogLevel, "ReadCacheW_Call {");
1150 if (call->szLookupName)
1151 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1152 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
1153
1154 smartcard_log_context(log, &call->Common.handles.hContext);
1155 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1156 sizeof(UUID));
1157 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1158 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1159 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1160
1161 WLog_Print(log, g_LogLevel, "}");
1162}
1163
1164static void smartcard_trace_transmit_call(wLog* log, const Transmit_Call* call)
1165{
1166 WINPR_ASSERT(call);
1167 UINT32 cbExtraBytes = 0;
1168 BYTE* pbExtraBytes = nullptr;
1169
1170 if (!WLog_IsLevelActive(log, g_LogLevel))
1171 return;
1172
1173 WLog_Print(log, g_LogLevel, "Transmit_Call {");
1174 smartcard_log_context(log, &call->handles.hContext);
1175 smartcard_log_redir_handle(log, &call->handles.hCard);
1176
1177 if (call->pioSendPci)
1178 {
1179 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1180 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
1181 WLog_Print(log, g_LogLevel, "pioSendPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1182 call->pioSendPci->dwProtocol, cbExtraBytes);
1183
1184 if (cbExtraBytes)
1185 {
1186 smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1187 }
1188 }
1189 else
1190 {
1191 WLog_Print(log, g_LogLevel, "pioSendPci: null");
1192 }
1193
1194 WLog_Print(log, g_LogLevel, "cbSendLength: %" PRIu32 "", call->cbSendLength);
1195
1196 if (call->pbSendBuffer)
1197 {
1198 smartcard_dump_array(log, g_LogLevel, "pbSendBuffer: ", "", call->pbSendBuffer,
1199 call->cbSendLength);
1200 }
1201 else
1202 {
1203 WLog_Print(log, g_LogLevel, "pbSendBuffer: null");
1204 }
1205
1206 if (call->pioRecvPci)
1207 {
1208 cbExtraBytes = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1209 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1210 WLog_Print(log, g_LogLevel, "pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1211 call->pioRecvPci->dwProtocol, cbExtraBytes);
1212
1213 if (cbExtraBytes)
1214 {
1215 smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1216 }
1217 }
1218 else
1219 {
1220 WLog_Print(log, g_LogLevel, "pioRecvPci: null");
1221 }
1222
1223 WLog_Print(log, g_LogLevel, "fpbRecvBufferIsNULL: %" PRId32 " cbRecvLength: %" PRIu32 "",
1224 call->fpbRecvBufferIsNULL, call->cbRecvLength);
1225 WLog_Print(log, g_LogLevel, "}");
1226}
1227
1228static void smartcard_trace_locate_cards_by_atr_w_call(wLog* log,
1229 const LocateCardsByATRW_Call* call)
1230{
1231 WINPR_ASSERT(call);
1232
1233 if (!WLog_IsLevelActive(log, g_LogLevel))
1234 return;
1235
1236 WLog_Print(log, g_LogLevel, "LocateCardsByATRW_Call {");
1237 smartcard_log_context(log, &call->handles.hContext);
1238
1239 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
1240
1241 WLog_Print(log, g_LogLevel, "}");
1242}
1243
1244static void smartcard_trace_transmit_return(wLog* log, const Transmit_Return* ret)
1245{
1246 WINPR_ASSERT(ret);
1247 UINT32 cbExtraBytes = 0;
1248 BYTE* pbExtraBytes = nullptr;
1249
1250 if (!WLog_IsLevelActive(log, g_LogLevel))
1251 return;
1252
1253 WLog_Print(log, g_LogLevel, "Transmit_Return {");
1254 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1255 SCardGetErrorString(ret->ReturnCode),
1256 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1257
1258 if (ret->pioRecvPci)
1259 {
1260 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1261 pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1262 WLog_Print(log, g_LogLevel,
1263 " pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1264 ret->pioRecvPci->dwProtocol, cbExtraBytes);
1265
1266 if (cbExtraBytes)
1267 {
1268 smartcard_dump_array(log, g_LogLevel, " pbExtraBytes: ", "", pbExtraBytes,
1269 cbExtraBytes);
1270 }
1271 }
1272 else
1273 {
1274 WLog_Print(log, g_LogLevel, " pioRecvPci: null");
1275 }
1276
1277 WLog_Print(log, g_LogLevel, " cbRecvLength: %" PRIu32 "", ret->cbRecvLength);
1278
1279 if (ret->pbRecvBuffer)
1280 {
1281 smartcard_dump_array(log, g_LogLevel, " pbRecvBuffer: ", "", ret->pbRecvBuffer,
1282 ret->cbRecvLength);
1283 }
1284 else
1285 {
1286 WLog_Print(log, g_LogLevel, " pbRecvBuffer: null");
1287 }
1288
1289 WLog_Print(log, g_LogLevel, "}");
1290}
1291
1292static void smartcard_trace_control_return(wLog* log, const Control_Return* ret)
1293{
1294 WINPR_ASSERT(ret);
1295
1296 if (!WLog_IsLevelActive(log, g_LogLevel))
1297 return;
1298
1299 WLog_Print(log, g_LogLevel, "Control_Return {");
1300 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1301 SCardGetErrorString(ret->ReturnCode),
1302 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1303 WLog_Print(log, g_LogLevel, " cbOutBufferSize: %" PRIu32 "", ret->cbOutBufferSize);
1304
1305 if (ret->pvOutBuffer)
1306 {
1307 smartcard_dump_array(log, g_LogLevel, "pvOutBuffer: ", "", ret->pvOutBuffer,
1308 ret->cbOutBufferSize);
1309 }
1310 else
1311 {
1312 WLog_Print(log, g_LogLevel, "pvOutBuffer: null");
1313 }
1314
1315 WLog_Print(log, g_LogLevel, "}");
1316}
1317
1318static void smartcard_trace_control_call(wLog* log, const Control_Call* call)
1319{
1320 WINPR_ASSERT(call);
1321
1322 if (!WLog_IsLevelActive(log, g_LogLevel))
1323 return;
1324
1325 WLog_Print(log, g_LogLevel, "Control_Call {");
1326 smartcard_log_context(log, &call->handles.hContext);
1327 smartcard_log_redir_handle(log, &call->handles.hCard);
1328
1329 WLog_Print(log, g_LogLevel,
1330 "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32
1331 " fpvOutBufferIsNULL: %" PRId32 " cbOutBufferSize: %" PRIu32 "",
1332 call->dwControlCode, call->cbInBufferSize, call->fpvOutBufferIsNULL,
1333 call->cbOutBufferSize);
1334
1335 if (call->pvInBuffer)
1336 {
1337 smartcard_dump_array(log, WLOG_DEBUG, "pbInBuffer: ", "", call->pvInBuffer,
1338 call->cbInBufferSize);
1339 }
1340 else
1341 {
1342 WLog_Print(log, g_LogLevel, "pvInBuffer: null");
1343 }
1344
1345 WLog_Print(log, g_LogLevel, "}");
1346}
1347
1348static void smartcard_trace_set_attrib_call(wLog* log, const SetAttrib_Call* call)
1349{
1350 WINPR_ASSERT(call);
1351
1352 if (!WLog_IsLevelActive(log, g_LogLevel))
1353 return;
1354
1355 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1356 smartcard_log_context(log, &call->handles.hContext);
1357 smartcard_log_redir_handle(log, &call->handles.hCard);
1358 WLog_Print(log, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId);
1359 WLog_Print(log, g_LogLevel, "cbAttrLen: 0x%08" PRIx32, call->cbAttrLen);
1360 smartcard_dump_array(log, g_LogLevel, "pbAttr: ", "", call->pbAttr, call->cbAttrLen);
1361 WLog_Print(log, g_LogLevel, "}");
1362}
1363
1364static void smartcard_trace_get_attrib_return(wLog* log, const GetAttrib_Return* ret,
1365 DWORD dwAttrId)
1366{
1367 WINPR_ASSERT(ret);
1368
1369 if (!WLog_IsLevelActive(log, g_LogLevel))
1370 return;
1371
1372 WLog_Print(log, g_LogLevel, "GetAttrib_Return {");
1373 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1374 SCardGetErrorString(ret->ReturnCode),
1375 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1376 WLog_Print(log, g_LogLevel, " dwAttrId: %s (0x%08" PRIX32 ") cbAttrLen: 0x%08" PRIX32 "",
1377 SCardGetAttributeString(dwAttrId), dwAttrId, ret->cbAttrLen);
1378 smartcard_dump_array(log, g_LogLevel, " ", "", ret->pbAttr, ret->cbAttrLen);
1379
1380 WLog_Print(log, g_LogLevel, "}");
1381}
1382
1383static void smartcard_trace_get_attrib_call(wLog* log, const GetAttrib_Call* call)
1384{
1385 WINPR_ASSERT(call);
1386
1387 if (!WLog_IsLevelActive(log, g_LogLevel))
1388 return;
1389
1390 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1391 smartcard_log_context(log, &call->handles.hContext);
1392 smartcard_log_redir_handle(log, &call->handles.hCard);
1393
1394 WLog_Print(log, g_LogLevel,
1395 "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32
1396 "",
1397 SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->fpbAttrIsNULL,
1398 call->cbAttrLen);
1399 WLog_Print(log, g_LogLevel, "}");
1400}
1401
1402static void smartcard_trace_status_call(wLog* log, const Status_Call* call, BOOL unicode)
1403{
1404 WINPR_ASSERT(call);
1405
1406 if (!WLog_IsLevelActive(log, g_LogLevel))
1407 return;
1408
1409 WLog_Print(log, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A");
1410 smartcard_log_context(log, &call->handles.hContext);
1411 smartcard_log_redir_handle(log, &call->handles.hCard);
1412
1413 WLog_Print(log, g_LogLevel,
1414 "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "",
1415 call->fmszReaderNamesIsNULL, call->cchReaderLen, call->cbAtrLen);
1416 WLog_Print(log, g_LogLevel, "}");
1417}
1418
1419static void smartcard_trace_status_return(wLog* log, const Status_Return* ret, BOOL unicode)
1420{
1421 WINPR_ASSERT(ret);
1422 char* mszReaderNamesA = nullptr;
1423 UINT32 cBytes = 0;
1424
1425 if (!WLog_IsLevelActive(log, g_LogLevel))
1426 return;
1427 cBytes = ret->cBytes;
1428 if (ret->ReturnCode != SCARD_S_SUCCESS)
1429 cBytes = 0;
1430 if (cBytes == SCARD_AUTOALLOCATE)
1431 cBytes = 0;
1432 mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode);
1433
1434 WLog_Print(log, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A");
1435 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1436 SCardGetErrorString(ret->ReturnCode),
1437 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1438 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ") dwProtocol: %s (0x%08" PRIX32 ")",
1439 SCardGetCardStateString(ret->dwState), ret->dwState,
1440 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1441
1442 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " mszReaderNames: %s", ret->cBytes,
1443 mszReaderNamesA);
1444
1445 smartcard_dump_array(log, g_LogLevel, " cbAtrLen: %" PRIu32 " pbAtr: ", "", ret->pbAtr,
1446 ret->cbAtrLen, ret->cbAtrLen);
1447 WLog_Print(log, g_LogLevel, "}");
1448 free(mszReaderNamesA);
1449}
1450
1451static void smartcard_trace_state_return(wLog* log, const State_Return* ret)
1452{
1453 WINPR_ASSERT(ret);
1454 char* state = nullptr;
1455
1456 if (!WLog_IsLevelActive(log, g_LogLevel))
1457 return;
1458
1459 state = SCardGetReaderStateString(ret->dwState);
1460 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1461 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1462 SCardGetErrorString(ret->ReturnCode),
1463 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1464 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ")", state, ret->dwState);
1465 WLog_Print(log, g_LogLevel, " dwProtocol: %s (0x%08" PRIX32 ")",
1466 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1467 WLog_Print(log, g_LogLevel, " cbAtrLen: (0x%08" PRIX32 ")", ret->cbAtrLen);
1468 smartcard_dump_array(log, g_LogLevel, " rgAtr: ", "", ret->rgAtr, sizeof(ret->rgAtr));
1469 WLog_Print(log, g_LogLevel, "}");
1470 free(state);
1471}
1472
1473static void smartcard_trace_reconnect_return(wLog* log, const Reconnect_Return* ret)
1474{
1475 WINPR_ASSERT(ret);
1476
1477 if (!WLog_IsLevelActive(log, g_LogLevel))
1478 return;
1479
1480 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1481 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1482 SCardGetErrorString(ret->ReturnCode),
1483 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1484 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1485 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1486 WLog_Print(log, g_LogLevel, "}");
1487}
1488
1489static void smartcard_trace_connect_a_call(wLog* log, const ConnectA_Call* call)
1490{
1491 WINPR_ASSERT(call);
1492
1493 if (!WLog_IsLevelActive(log, g_LogLevel))
1494 return;
1495
1496 WLog_Print(log, g_LogLevel, "ConnectA_Call {");
1497 smartcard_log_context(log, &call->Common.handles.hContext);
1498
1499 WLog_Print(log, g_LogLevel,
1500 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1501 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1502 call->szReader, SCardGetShareModeString(call->Common.dwShareMode),
1503 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1504 call->Common.dwPreferredProtocols);
1505 WLog_Print(log, g_LogLevel, "}");
1506}
1507
1508static void smartcard_trace_connect_w_call(wLog* log, const ConnectW_Call* call)
1509{
1510 WINPR_ASSERT(call);
1511 char szReaderA[1024] = WINPR_C_ARRAY_INIT;
1512
1513 if (!WLog_IsLevelActive(log, g_LogLevel))
1514 return;
1515
1516 if (call->szReader)
1517 (void)ConvertWCharToUtf8(call->szReader, szReaderA, ARRAYSIZE(szReaderA));
1518 WLog_Print(log, g_LogLevel, "ConnectW_Call {");
1519 smartcard_log_context(log, &call->Common.handles.hContext);
1520
1521 WLog_Print(log, g_LogLevel,
1522 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1523 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1524 szReaderA, SCardGetShareModeString(call->Common.dwShareMode),
1525 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1526 call->Common.dwPreferredProtocols);
1527 WLog_Print(log, g_LogLevel, "}");
1528}
1529
1530static void smartcard_trace_hcard_and_disposition_call(wLog* log,
1531 const HCardAndDisposition_Call* call,
1532 const char* name)
1533{
1534 WINPR_ASSERT(call);
1535
1536 if (!WLog_IsLevelActive(log, g_LogLevel))
1537 return;
1538
1539 WLog_Print(log, g_LogLevel, "%s_Call {", name);
1540 smartcard_log_context(log, &call->handles.hContext);
1541 smartcard_log_redir_handle(log, &call->handles.hCard);
1542
1543 WLog_Print(log, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")",
1544 SCardGetDispositionString(call->dwDisposition), call->dwDisposition);
1545 WLog_Print(log, g_LogLevel, "}");
1546}
1547
1548static void smartcard_trace_establish_context_call(wLog* log, const EstablishContext_Call* call)
1549{
1550 WINPR_ASSERT(call);
1551
1552 if (!WLog_IsLevelActive(log, g_LogLevel))
1553 return;
1554
1555 WLog_Print(log, g_LogLevel, "EstablishContext_Call {");
1556 WLog_Print(log, g_LogLevel, "dwScope: %s (0x%08" PRIX32 ")", SCardGetScopeString(call->dwScope),
1557 call->dwScope);
1558 WLog_Print(log, g_LogLevel, "}");
1559}
1560
1561static void smartcard_trace_establish_context_return(wLog* log, const EstablishContext_Return* ret)
1562{
1563 WINPR_ASSERT(ret);
1564
1565 if (!WLog_IsLevelActive(log, g_LogLevel))
1566 return;
1567
1568 WLog_Print(log, g_LogLevel, "EstablishContext_Return {");
1569 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1570 SCardGetErrorString(ret->ReturnCode),
1571 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1572 smartcard_log_context(log, &ret->hContext);
1573
1574 WLog_Print(log, g_LogLevel, "}");
1575}
1576
1577void smartcard_trace_long_return(const Long_Return* ret, const char* name)
1578{
1579 wLog* log = scard_log();
1580 smartcard_trace_long_return_int(log, ret, name);
1581}
1582
1583void smartcard_trace_long_return_int(wLog* log, const Long_Return* ret, const char* name)
1584{
1585 WINPR_ASSERT(ret);
1586
1587 if (!WLog_IsLevelActive(log, g_LogLevel))
1588 return;
1589
1590 WLog_Print(log, g_LogLevel, "%s_Return {", name);
1591 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1592 SCardGetErrorString(ret->ReturnCode),
1593 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1594 WLog_Print(log, g_LogLevel, "}");
1595}
1596
1597static void smartcard_trace_connect_return(wLog* log, const Connect_Return* ret)
1598{
1599 WINPR_ASSERT(ret);
1600
1601 if (!WLog_IsLevelActive(log, g_LogLevel))
1602 return;
1603
1604 WLog_Print(log, g_LogLevel, "Connect_Return {");
1605 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1606 SCardGetErrorString(ret->ReturnCode),
1607 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1608 smartcard_log_context(log, &ret->hContext);
1609 smartcard_log_redir_handle(log, &ret->hCard);
1610
1611 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1612 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1613 WLog_Print(log, g_LogLevel, "}");
1614}
1615
1616static void smartcard_trace_reconnect_call(wLog* log, const Reconnect_Call* call)
1617{
1618 WINPR_ASSERT(call);
1619
1620 if (!WLog_IsLevelActive(log, g_LogLevel))
1621 return;
1622
1623 WLog_Print(log, g_LogLevel, "Reconnect_Call {");
1624 smartcard_log_context(log, &call->handles.hContext);
1625 smartcard_log_redir_handle(log, &call->handles.hCard);
1626
1627 WLog_Print(log, g_LogLevel,
1628 "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32
1629 ") dwInitialization: %s (0x%08" PRIX32 ")",
1630 SCardGetShareModeString(call->dwShareMode), call->dwShareMode,
1631 SCardGetProtocolString(call->dwPreferredProtocols), call->dwPreferredProtocols,
1632 SCardGetDispositionString(call->dwInitialization), call->dwInitialization);
1633 WLog_Print(log, g_LogLevel, "}");
1634}
1635
1636static void smartcard_trace_device_type_id_return(wLog* log, const GetDeviceTypeId_Return* ret)
1637{
1638 WINPR_ASSERT(ret);
1639
1640 if (!WLog_IsLevelActive(log, g_LogLevel))
1641 return;
1642
1643 WLog_Print(log, g_LogLevel, "GetDeviceTypeId_Return {");
1644 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1645 SCardGetErrorString(ret->ReturnCode),
1646 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1647 WLog_Print(log, g_LogLevel, " dwDeviceId=%08" PRIx32, ret->dwDeviceId);
1648
1649 WLog_Print(log, g_LogLevel, "}");
1650}
1651
1652WINPR_ATTR_NODISCARD static LONG
1653smartcard_unpack_common_context_and_string_a(wLog* log, wStream* s, REDIR_SCARDCONTEXT* phContext,
1654 CHAR** pszReaderName)
1655{
1656 UINT32 index = 0;
1657 UINT32 pbContextNdrPtr = 0;
1658 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1659 if (status != SCARD_S_SUCCESS)
1660 return status;
1661
1662 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1663 return ERROR_INVALID_DATA;
1664
1665 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1666 if (status != SCARD_S_SUCCESS)
1667 return status;
1668
1669 status = smartcard_ndr_read_a(log, s, pszReaderName, NDR_PTR_FULL);
1670 if (status != SCARD_S_SUCCESS)
1671 return status;
1672
1673 smartcard_trace_context_and_string_call_a(log, __func__, phContext, *pszReaderName);
1674 return SCARD_S_SUCCESS;
1675}
1676
1677WINPR_ATTR_NODISCARD static LONG
1678smartcard_unpack_common_context_and_string_w(wLog* log, wStream* s, REDIR_SCARDCONTEXT* phContext,
1679 WCHAR** pszReaderName)
1680{
1681 UINT32 index = 0;
1682 UINT32 pbContextNdrPtr = 0;
1683
1684 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1685 if (status != SCARD_S_SUCCESS)
1686 return status;
1687
1688 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1689 return ERROR_INVALID_DATA;
1690
1691 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1692 if (status != SCARD_S_SUCCESS)
1693 return status;
1694
1695 status = smartcard_ndr_read_w(log, s, pszReaderName, NDR_PTR_FULL);
1696 if (status != SCARD_S_SUCCESS)
1697 return status;
1698
1699 smartcard_trace_context_and_string_call_w(log, __func__, phContext, *pszReaderName);
1700 return SCARD_S_SUCCESS;
1701}
1702
1703LONG smartcard_unpack_common_type_header(wStream* s)
1704{
1705 wLog* log = scard_log();
1706 UINT8 version = 0;
1707 UINT32 filler = 0;
1708 UINT8 endianness = 0;
1709 UINT16 commonHeaderLength = 0;
1710
1711 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1712 return STATUS_BUFFER_TOO_SMALL;
1713
1714 /* Process CommonTypeHeader */
1715 Stream_Read_UINT8(s, version); /* Version (1 byte) */
1716 Stream_Read_UINT8(s, endianness); /* Endianness (1 byte) */
1717 Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
1718 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0xCCCCCCCC */
1719
1720 if (version != 1)
1721 {
1722 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Version %" PRIu8 "", version);
1723 return STATUS_INVALID_PARAMETER;
1724 }
1725
1726 if (endianness != 0x10)
1727 {
1728 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %" PRIu8 "",
1729 endianness);
1730 return STATUS_INVALID_PARAMETER;
1731 }
1732
1733 if (commonHeaderLength != 8)
1734 {
1735 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %" PRIu16 "",
1736 commonHeaderLength);
1737 return STATUS_INVALID_PARAMETER;
1738 }
1739
1740 if (filler != 0xCCCCCCCC)
1741 {
1742 WLog_Print(log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08" PRIX32 "", filler);
1743 return STATUS_INVALID_PARAMETER;
1744 }
1745
1746 return SCARD_S_SUCCESS;
1747}
1748
1749void smartcard_pack_common_type_header(wStream* s)
1750{
1751 Stream_Write_UINT8(s, 1); /* Version (1 byte) */
1752 Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */
1753 Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */
1754 Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
1755}
1756
1757LONG smartcard_unpack_private_type_header(wStream* s)
1758{
1759 wLog* log = scard_log();
1760 UINT32 filler = 0;
1761 UINT32 objectBufferLength = 0;
1762
1763 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1764 return STATUS_BUFFER_TOO_SMALL;
1765
1766 Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1767 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0x00000000 */
1768
1769 if (filler != 0x00000000)
1770 {
1771 WLog_Print(log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08" PRIX32 "", filler);
1772 return STATUS_INVALID_PARAMETER;
1773 }
1774
1775 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, objectBufferLength))
1776 return STATUS_INVALID_PARAMETER;
1777
1778 return SCARD_S_SUCCESS;
1779}
1780
1781void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength)
1782{
1783 Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1784 Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */
1785}
1786
1787LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment)
1788{
1789 const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1790 const size_t pad = padsize - size;
1791
1792 if (pad > 0)
1793 {
1794 if (!Stream_SafeSeek(s, pad))
1795 return -1;
1796 }
1797
1798 return (LONG)pad;
1799}
1800
1801LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment)
1802{
1803 const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1804 const size_t pad = padsize - size;
1805
1806 if (pad)
1807 {
1808 if (!Stream_EnsureRemainingCapacity(s, pad))
1809 {
1810 wLog* log = scard_log();
1811 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
1812 return SCARD_F_INTERNAL_ERROR;
1813 }
1814
1815 Stream_Zero(s, pad);
1816 }
1817
1818 return SCARD_S_SUCCESS;
1819}
1820
1821SCARDCONTEXT smartcard_scard_context_native_from_redir(const REDIR_SCARDCONTEXT* context)
1822{
1823 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
1824
1825 WINPR_ASSERT(context);
1826 if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
1827 {
1828 wLog* log = scard_log();
1829 WLog_Print(log, WLOG_WARN,
1830 "REDIR_SCARDCONTEXT does not match native size: Actual: %" PRIu32
1831 ", Expected: %" PRIuz "",
1832 context->cbContext, sizeof(ULONG_PTR));
1833 return 0;
1834 }
1835
1836 if (context->cbContext)
1837 CopyMemory(&hContext, &(context->pbContext), context->cbContext);
1838
1839 return hContext;
1840}
1841
1842void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context, SCARDCONTEXT hContext)
1843{
1844 WINPR_ASSERT(context);
1845 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1846 context->cbContext = sizeof(ULONG_PTR);
1847 CopyMemory(&(context->pbContext), &hContext, context->cbContext);
1848}
1849
1850SCARDHANDLE smartcard_scard_handle_native_from_redir(const REDIR_SCARDHANDLE* handle)
1851{
1852 SCARDHANDLE hCard = 0;
1853
1854 WINPR_ASSERT(handle);
1855 if (handle->cbHandle == 0)
1856 return hCard;
1857
1858 if (handle->cbHandle != sizeof(ULONG_PTR))
1859 {
1860 wLog* log = scard_log();
1861 WLog_Print(log, WLOG_WARN,
1862 "REDIR_SCARDHANDLE does not match native size: Actual: %" PRIu32
1863 ", Expected: %" PRIuz "",
1864 handle->cbHandle, sizeof(ULONG_PTR));
1865 return 0;
1866 }
1867
1868 if (handle->cbHandle)
1869 CopyMemory(&hCard, &(handle->pbHandle), handle->cbHandle);
1870
1871 return hCard;
1872}
1873
1874void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle, SCARDHANDLE hCard)
1875{
1876 WINPR_ASSERT(handle);
1877 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1878 handle->cbHandle = sizeof(ULONG_PTR);
1879 CopyMemory(&(handle->pbHandle), &hCard, handle->cbHandle);
1880}
1881
1882#define smartcard_context_supported(log, size) \
1883 smartcard_context_supported_((log), (size), __FILE__, __func__, __LINE__)
1884WINPR_ATTR_NODISCARD static LONG smartcard_context_supported_(wLog* log, uint32_t size,
1885 const char* file, const char* fkt,
1886 size_t line)
1887{
1888 switch (size)
1889 {
1890 case 0:
1891 case 4:
1892 case 8:
1893 return SCARD_S_SUCCESS;
1894 default:
1895 {
1896 const uint32_t level = WLOG_WARN;
1897 if (WLog_IsLevelActive(log, level))
1898 {
1899 WLog_PrintTextMessage(log, level, line, file, fkt,
1900 "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %" PRIu32 "",
1901 size);
1902 }
1903 return STATUS_INVALID_PARAMETER;
1904 }
1905 }
1906}
1907
1908LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
1909 UINT32* index, UINT32* ppbContextNdrPtr,
1910 const char* file, const char* function, size_t line)
1911{
1912 UINT32 pbContextNdrPtr = 0;
1913
1914 WINPR_UNUSED(file);
1915 WINPR_ASSERT(context);
1916
1917 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1918
1919 if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ")", file,
1920 function, line))
1921 return STATUS_BUFFER_TOO_SMALL;
1922
1923 const LONG status = smartcard_context_supported_(log, context->cbContext, file, function, line);
1924 if (status != SCARD_S_SUCCESS)
1925 return status;
1926
1927 Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1928
1929 if (!smartcard_ndr_pointer_read_(log, s, index, &pbContextNdrPtr, file, function, line))
1930 return ERROR_INVALID_DATA;
1931
1932 if (((context->cbContext == 0) && pbContextNdrPtr) ||
1933 ((context->cbContext != 0) && !pbContextNdrPtr))
1934 {
1935 WLog_Print(log, WLOG_WARN,
1936 "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1937 ") inconsistency",
1938 context->cbContext, pbContextNdrPtr);
1939 return STATUS_INVALID_PARAMETER;
1940 }
1941
1942 *ppbContextNdrPtr = pbContextNdrPtr;
1943 return SCARD_S_SUCCESS;
1944}
1945
1946LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1947 const REDIR_SCARDCONTEXT* context, UINT32* index)
1948{
1949 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1950
1951 WINPR_ASSERT(context);
1952 if (context->cbContext != 0)
1953 {
1954 Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1955 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1956 *index = *index + 1;
1957 }
1958 else
1959 Stream_Zero(s, 8);
1960
1961 return SCARD_S_SUCCESS;
1962}
1963
1964LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1965 WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1966 REDIR_SCARDCONTEXT* context)
1967{
1968 UINT32 length = 0;
1969
1970 WINPR_ASSERT(context);
1971
1972 if (context->cbContext == 0)
1973 return SCARD_S_SUCCESS;
1974
1975 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1976 return STATUS_BUFFER_TOO_SMALL;
1977
1978 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1979
1980 if (length != context->cbContext)
1981 {
1982 WLog_Print(log, WLOG_WARN,
1983 "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1984 length, context->cbContext);
1985 return STATUS_INVALID_PARAMETER;
1986 }
1987
1988 const LONG status = smartcard_context_supported(log, context->cbContext);
1989 if (status != SCARD_S_SUCCESS)
1990 return status;
1991
1992 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1993 return STATUS_BUFFER_TOO_SMALL;
1994
1995 if (context->cbContext)
1996 Stream_Read(s, &(context->pbContext), context->cbContext);
1997 else
1998 ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1999
2000 return SCARD_S_SUCCESS;
2001}
2002
2003LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2004 const REDIR_SCARDCONTEXT* context)
2005{
2006 WINPR_ASSERT(context);
2007
2008 if (context->cbContext == 0)
2009 return SCARD_S_SUCCESS;
2010
2011 Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
2012 Stream_Write(s, &(context->pbContext), context->cbContext);
2013
2014 return SCARD_S_SUCCESS;
2015}
2016
2017LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
2018 UINT32* index, const char* file, const char* function,
2019 size_t line)
2020{
2021 UINT32 pbHandleNdrPtr = 0;
2022
2023 WINPR_ASSERT(handle);
2024 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
2025
2026 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2027 return STATUS_BUFFER_TOO_SMALL;
2028
2029 Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2030
2031 if (!smartcard_ndr_pointer_read_(log, s, index, &pbHandleNdrPtr, file, function, line))
2032 return ERROR_INVALID_DATA;
2033
2034 if (((handle->cbHandle == 0) && pbHandleNdrPtr) ||
2035 ((handle->cbHandle != 0) && !pbHandleNdrPtr))
2036 {
2037 WLog_Print(log, WLOG_WARN,
2038 "REDIR_SCARDHANDLE cbHandle (%" PRIu32 ") pbHandleNdrPtr (%" PRIu32
2039 ") inconsistency",
2040 handle->cbHandle, pbHandleNdrPtr);
2041 return STATUS_INVALID_PARAMETER;
2042 }
2043
2044 return SCARD_S_SUCCESS;
2045}
2046
2047LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2048 const REDIR_SCARDHANDLE* handle, UINT32* index)
2049{
2050 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
2051
2052 WINPR_ASSERT(handle);
2053 if (handle->cbHandle != 0)
2054 {
2055 Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
2056 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
2057 *index = *index + 1;
2058 }
2059 else
2060 Stream_Zero(s, 8);
2061 return SCARD_S_SUCCESS;
2062}
2063
2064LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
2065{
2066 UINT32 length = 0;
2067
2068 WINPR_ASSERT(handle);
2069
2070 if (handle->cbHandle == 0)
2071 return SCARD_S_SUCCESS;
2072
2073 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2074 return STATUS_BUFFER_TOO_SMALL;
2075
2076 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
2077
2078 if (length != handle->cbHandle)
2079 {
2080 WLog_Print(log, WLOG_WARN,
2081 "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
2082 handle->cbHandle);
2083 return STATUS_INVALID_PARAMETER;
2084 }
2085
2086 if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
2087 {
2088 WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
2089 handle->cbHandle);
2090 return STATUS_INVALID_PARAMETER;
2091 }
2092
2093 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
2094 return STATUS_BUFFER_TOO_SMALL;
2095
2096 if (handle->cbHandle)
2097 Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
2098
2099 return SCARD_S_SUCCESS;
2100}
2101
2102LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2103 const REDIR_SCARDHANDLE* handle)
2104{
2105 WINPR_ASSERT(handle);
2106
2107 if (handle->cbHandle == 0)
2108 return SCARD_S_SUCCESS;
2109
2110 Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2111 Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
2112
2113 return SCARD_S_SUCCESS;
2114}
2115
2116LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
2117{
2118 WINPR_ASSERT(call);
2119 wLog* log = scard_log();
2120
2121 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2122 return STATUS_BUFFER_TOO_SMALL;
2123
2124 Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2125 smartcard_trace_establish_context_call(log, call);
2126 return SCARD_S_SUCCESS;
2127}
2128
2129LONG smartcard_pack_establish_context_call(wStream* s, const EstablishContext_Call* call)
2130{
2131 WINPR_ASSERT(call);
2132 wLog* log = scard_log();
2133
2134 smartcard_trace_establish_context_call(log, call);
2135
2136 if (!Stream_EnsureRemainingCapacity(s, 4))
2137 return SCARD_E_NO_MEMORY;
2138
2139 Stream_Write_UINT32(s, call->dwScope);
2140
2141 return SCARD_S_SUCCESS;
2142}
2143
2144LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2145{
2146 WINPR_ASSERT(ret);
2147 wLog* log = scard_log();
2148 LONG status = 0;
2149 UINT32 index = 0;
2150
2151 smartcard_trace_establish_context_return(log, ret);
2152 if (ret->ReturnCode != SCARD_S_SUCCESS)
2153 return ret->ReturnCode;
2154
2155 status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2156 if (status != SCARD_S_SUCCESS)
2157 return status;
2158
2159 return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2160}
2161
2162LONG smartcard_unpack_establish_context_return(wStream* s, EstablishContext_Return* ret)
2163{
2164 WINPR_ASSERT(ret);
2165 wLog* log = scard_log();
2166 UINT32 index = 0;
2167 UINT32 pbContextNdrPtr = 0;
2168
2169 LONG status =
2170 smartcard_unpack_redir_scard_context(log, s, &(ret->hContext), &index, &pbContextNdrPtr);
2171 if (status != SCARD_S_SUCCESS)
2172 return status;
2173
2174 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &(ret->hContext));
2175 if (status != SCARD_S_SUCCESS)
2176 return status;
2177
2178 smartcard_trace_establish_context_return(log, ret);
2179 return SCARD_S_SUCCESS;
2180}
2181
2182LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2183{
2184 UINT32 index = 0;
2185 UINT32 pbContextNdrPtr = 0;
2186 wLog* log = scard_log();
2187
2188 WINPR_ASSERT(call);
2189 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2190 &pbContextNdrPtr);
2191 if (status != SCARD_S_SUCCESS)
2192 return status;
2193
2194 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2195 &(call->handles.hContext));
2196 if (status != SCARD_S_SUCCESS)
2197 WLog_Print(log, WLOG_ERROR,
2198 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2199 status);
2200
2201 smartcard_trace_context_call(log, call, name);
2202 return status;
2203}
2204
2205LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2206{
2207 UINT32 index = 0;
2208 UINT32 pbContextNdrPtr = 0;
2209 wLog* log = scard_log();
2210
2211 WINPR_ASSERT(call);
2212 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2213 &pbContextNdrPtr);
2214
2215 if (status != SCARD_S_SUCCESS)
2216 return status;
2217
2218 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2219 return STATUS_BUFFER_TOO_SMALL;
2220
2221 Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2222 Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */
2223 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2224 &(call->handles.hContext));
2225
2226 if (status != SCARD_S_SUCCESS)
2227 return status;
2228
2229 smartcard_trace_list_reader_groups_call(log, call, unicode);
2230 return SCARD_S_SUCCESS;
2231}
2232
2233LONG smartcard_pack_list_reader_groups_call(wStream* s, const ListReaderGroups_Call* call,
2234 BOOL unicode)
2235{
2236 WINPR_ASSERT(call);
2237 wLog* log = scard_log();
2238 UINT32 index = 0;
2239
2240 smartcard_trace_list_reader_groups_call(log, call, unicode);
2241
2242 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2243 if (status != SCARD_S_SUCCESS)
2244 return status;
2245
2246 if (!Stream_EnsureRemainingCapacity(s, 8))
2247 return SCARD_E_NO_MEMORY;
2248
2249 Stream_Write_INT32(s, call->fmszGroupsIsNULL);
2250 Stream_Write_UINT32(s, call->cchGroups);
2251
2252 return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2253}
2254
2255LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2256 BOOL unicode)
2257{
2258 WINPR_ASSERT(ret);
2259 wLog* log = scard_log();
2260 LONG status = 0;
2261 UINT32 cBytes = ret->cBytes;
2262 UINT32 index = 0;
2263
2264 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2265 if (ret->ReturnCode != SCARD_S_SUCCESS)
2266 cBytes = 0;
2267 if (cBytes == SCARD_AUTOALLOCATE)
2268 cBytes = 0;
2269
2270 if (!Stream_EnsureRemainingCapacity(s, 4))
2271 return SCARD_E_NO_MEMORY;
2272
2273 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2274 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2275 return SCARD_E_NO_MEMORY;
2276
2277 status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2278 if (status != SCARD_S_SUCCESS)
2279 return status;
2280 return ret->ReturnCode;
2281}
2282
2283LONG smartcard_unpack_list_reader_groups_return(wStream* s, ListReaderGroups_Return* ret,
2284 BOOL unicode)
2285{
2286 WINPR_ASSERT(ret);
2287 wLog* log = scard_log();
2288 UINT32 index = 0;
2289 UINT32 mszNdrPtr = 0;
2290
2291 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2292 return STATUS_BUFFER_TOO_SMALL;
2293
2294 const UINT32 cBytes = Stream_Get_UINT32(s);
2295
2296 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
2297 return ERROR_INVALID_DATA;
2298
2299 if (mszNdrPtr)
2300 {
2301 LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2302 if (status != SCARD_S_SUCCESS)
2303 return status;
2304 ret->cBytes = cBytes;
2305 }
2306
2307 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2308 return SCARD_S_SUCCESS;
2309}
2310
2311LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2312{
2313 UINT32 index = 0;
2314 UINT32 mszGroupsNdrPtr = 0;
2315 UINT32 pbContextNdrPtr = 0;
2316 wLog* log = scard_log();
2317
2318 WINPR_ASSERT(call);
2319 call->mszGroups = nullptr;
2320
2321 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2322 &pbContextNdrPtr);
2323 if (status != SCARD_S_SUCCESS)
2324 return status;
2325
2326 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2327 return STATUS_BUFFER_TOO_SMALL;
2328
2329 const UINT32 cBytes = Stream_Get_UINT32(s);
2330 if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2331 return ERROR_INVALID_DATA;
2332
2333 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2334 return STATUS_BUFFER_TOO_SMALL;
2335 Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2336 Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */
2337
2338 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2339 &(call->handles.hContext));
2340 if (status != SCARD_S_SUCCESS)
2341 return status;
2342
2343 if (mszGroupsNdrPtr)
2344 {
2345 status = smartcard_ndr_read(log, s, &call->mszGroups, cBytes, 1, NDR_PTR_SIMPLE);
2346 if (status != SCARD_S_SUCCESS)
2347 return status;
2348 call->cBytes = cBytes;
2349 }
2350
2351 smartcard_trace_list_readers_call(log, call, unicode);
2352 return SCARD_S_SUCCESS;
2353}
2354
2355LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2356{
2357 WINPR_ASSERT(ret);
2358 wLog* log = scard_log();
2359 LONG status = 0;
2360 UINT32 index = 0;
2361 UINT32 size = ret->cBytes;
2362
2363 smartcard_trace_list_readers_return(log, ret, unicode);
2364 if (ret->ReturnCode != SCARD_S_SUCCESS)
2365 size = 0;
2366
2367 if (!Stream_EnsureRemainingCapacity(s, 4))
2368 {
2369 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2370 return SCARD_F_INTERNAL_ERROR;
2371 }
2372
2373 Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2374 if (!smartcard_ndr_pointer_write(s, &index, size))
2375 return SCARD_E_NO_MEMORY;
2376
2377 status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2378 if (status != SCARD_S_SUCCESS)
2379 return status;
2380 return ret->ReturnCode;
2381}
2382
2383WINPR_ATTR_NODISCARD static LONG smartcard_unpack_connect_common(wLog* log, wStream* s,
2384 Connect_Common_Call* common,
2385 UINT32* index,
2386 UINT32* ppbContextNdrPtr)
2387{
2388 WINPR_ASSERT(common);
2389 LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2390 ppbContextNdrPtr);
2391 if (status != SCARD_S_SUCCESS)
2392 return status;
2393
2394 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2395 return STATUS_BUFFER_TOO_SMALL;
2396
2397 Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
2398 Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2399 return SCARD_S_SUCCESS;
2400}
2401
2402LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2403{
2404 LONG status = 0;
2405 UINT32 index = 0;
2406 UINT32 pbContextNdrPtr = 0;
2407
2408 WINPR_ASSERT(call);
2409 wLog* log = scard_log();
2410
2411 call->szReader = nullptr;
2412
2413 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2414 return ERROR_INVALID_DATA;
2415
2416 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2417 if (status != SCARD_S_SUCCESS)
2418 {
2419 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2420 status);
2421 return status;
2422 }
2423
2424 status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2425 if (status != SCARD_S_SUCCESS)
2426 return status;
2427
2428 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2429 &(call->Common.handles.hContext));
2430 if (status != SCARD_S_SUCCESS)
2431 WLog_Print(log, WLOG_ERROR,
2432 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2433 status);
2434
2435 smartcard_trace_connect_a_call(log, call);
2436 return status;
2437}
2438
2439LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2440{
2441 LONG status = 0;
2442 UINT32 index = 0;
2443 UINT32 pbContextNdrPtr = 0;
2444
2445 WINPR_ASSERT(call);
2446 wLog* log = scard_log();
2447 call->szReader = nullptr;
2448
2449 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2450 return ERROR_INVALID_DATA;
2451
2452 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2453 if (status != SCARD_S_SUCCESS)
2454 {
2455 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2456 status);
2457 return status;
2458 }
2459
2460 status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2461 if (status != SCARD_S_SUCCESS)
2462 return status;
2463
2464 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2465 &(call->Common.handles.hContext));
2466 if (status != SCARD_S_SUCCESS)
2467 WLog_Print(log, WLOG_ERROR,
2468 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2469 status);
2470
2471 smartcard_trace_connect_w_call(log, call);
2472 return status;
2473}
2474
2475LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2476{
2477 LONG status = 0;
2478 UINT32 index = 0;
2479
2480 WINPR_ASSERT(ret);
2481 wLog* log = scard_log();
2482 smartcard_trace_connect_return(log, ret);
2483
2484 status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2485 if (status != SCARD_S_SUCCESS)
2486 return status;
2487
2488 status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2489 if (status != SCARD_S_SUCCESS)
2490 return status;
2491
2492 if (!Stream_EnsureRemainingCapacity(s, 4))
2493 return SCARD_E_NO_MEMORY;
2494
2495 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2496 status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2497 if (status != SCARD_S_SUCCESS)
2498 return status;
2499 return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2500}
2501
2502LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2503{
2504 UINT32 index = 0;
2505 UINT32 pbContextNdrPtr = 0;
2506
2507 WINPR_ASSERT(call);
2508 wLog* log = scard_log();
2509 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2510 &pbContextNdrPtr);
2511 if (status != SCARD_S_SUCCESS)
2512 return status;
2513
2514 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2515 if (status != SCARD_S_SUCCESS)
2516 return status;
2517
2518 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2519 return STATUS_BUFFER_TOO_SMALL;
2520
2521 Stream_Read_UINT32(s, call->dwShareMode); /* dwShareMode (4 bytes) */
2522 Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2523 Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */
2524
2525 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2526 &(call->handles.hContext));
2527 if (status != SCARD_S_SUCCESS)
2528 {
2529 WLog_Print(log, WLOG_ERROR,
2530 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2531 status);
2532 return status;
2533 }
2534
2535 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2536 if (status != SCARD_S_SUCCESS)
2537 WLog_Print(log, WLOG_ERROR,
2538 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2539
2540 smartcard_trace_reconnect_call(log, call);
2541 return status;
2542}
2543
2544LONG smartcard_pack_reconnect_call(wStream* s, const Reconnect_Call* call)
2545{
2546 WINPR_ASSERT(call);
2547 wLog* log = scard_log();
2548 UINT32 index = 0;
2549
2550 smartcard_trace_reconnect_call(log, call);
2551
2552 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2553 if (status != SCARD_S_SUCCESS)
2554 return status;
2555
2556 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
2557 if (status != SCARD_S_SUCCESS)
2558 return status;
2559
2560 if (!Stream_EnsureRemainingCapacity(s, 12))
2561 return SCARD_E_NO_MEMORY;
2562
2563 Stream_Write_UINT32(s, call->dwShareMode);
2564 Stream_Write_UINT32(s, call->dwPreferredProtocols);
2565 Stream_Write_UINT32(s, call->dwInitialization);
2566
2567 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2568 if (status != SCARD_S_SUCCESS)
2569 return status;
2570
2571 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
2572}
2573
2574LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2575{
2576 WINPR_ASSERT(ret);
2577 wLog* log = scard_log();
2578 smartcard_trace_reconnect_return(log, ret);
2579
2580 if (!Stream_EnsureRemainingCapacity(s, 4))
2581 return SCARD_E_NO_MEMORY;
2582 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2583 return ret->ReturnCode;
2584}
2585
2586LONG smartcard_unpack_reconnect_return(wStream* s, Reconnect_Return* ret)
2587{
2588 WINPR_ASSERT(ret);
2589 wLog* log = scard_log();
2590
2591 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2592 return STATUS_BUFFER_TOO_SMALL;
2593
2594 Stream_Read_UINT32(s, ret->dwActiveProtocol);
2595
2596 smartcard_trace_reconnect_return(log, ret);
2597 return SCARD_S_SUCCESS;
2598}
2599
2600LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2601 const char* name)
2602{
2603 UINT32 index = 0;
2604 UINT32 pbContextNdrPtr = 0;
2605
2606 WINPR_ASSERT(call);
2607 wLog* log = scard_log();
2608
2609 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2610 &pbContextNdrPtr);
2611 if (status != SCARD_S_SUCCESS)
2612 return status;
2613
2614 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2615 if (status != SCARD_S_SUCCESS)
2616 return status;
2617
2618 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2619 return STATUS_BUFFER_TOO_SMALL;
2620
2621 Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2622
2623 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2624 &(call->handles.hContext));
2625 if (status != SCARD_S_SUCCESS)
2626 return status;
2627
2628 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2629 if (status != SCARD_S_SUCCESS)
2630 return status;
2631
2632 smartcard_trace_hcard_and_disposition_call(log, call, name);
2633 return status;
2634}
2635
2636static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2637{
2638 WINPR_ASSERT(call);
2639
2640 if (!WLog_IsLevelActive(log, g_LogLevel))
2641 return;
2642
2643 WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2644 smartcard_log_context(log, &call->handles.hContext);
2645
2646 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2647 call->cReaders);
2648
2649 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2650
2651 WLog_Print(log, g_LogLevel, "}");
2652}
2653
2654WINPR_ATTR_NODISCARD static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s,
2655 LPSCARD_READERSTATEA* ppcReaders,
2656 UINT32 cReaders, UINT32* ptrIndex)
2657{
2658 LONG status = SCARD_E_NO_MEMORY;
2659
2660 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2661 if (cReaders > UINT8_MAX)
2662 {
2663 WLog_Print(log, WLOG_ERROR,
2664 "Too many readers(%" PRIu32 "), rejecting request. Limited to <= %d", cReaders,
2665 UINT8_MAX);
2666 return SCARD_E_WRITE_TOO_MANY;
2667 }
2668
2669 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2670 return status;
2671
2672 const UINT32 len = Stream_Get_UINT32(s);
2673 if (len != cReaders)
2674 {
2675 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2676 return status;
2677 }
2678
2679 LPSCARD_READERSTATEA rgReaderStates =
2680 (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2681 BOOL* states = calloc(cReaders, sizeof(BOOL));
2682 if (!rgReaderStates || !states)
2683 goto fail;
2684 status = ERROR_INVALID_DATA;
2685
2686 for (UINT32 index = 0; index < cReaders; index++)
2687 {
2688 UINT32 ptr = UINT32_MAX;
2689 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2690
2691 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2692 goto fail;
2693
2694 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2695 {
2696 if (ptr != 0)
2697 goto fail;
2698 }
2699 /* Ignore nullptr length strings */
2700 states[index] = ptr != 0;
2701 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2702 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2703 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2704 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2705 {
2706 WLog_Print(log, WLOG_ERROR,
2707 "SCARD_READERSTATEA[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2708 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2709 goto fail;
2710 }
2711 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2712 }
2713
2714 for (UINT32 index = 0; index < cReaders; index++)
2715 {
2716 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2717
2718 /* Ignore empty strings */
2719 if (!states[index])
2720 continue;
2721 status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2722 if (status != SCARD_S_SUCCESS)
2723 goto fail;
2724 if (!readerState->szReader)
2725 goto fail;
2726 }
2727
2728 *ppcReaders = rgReaderStates;
2729 free(states);
2730 return SCARD_S_SUCCESS;
2731fail:
2732 if (rgReaderStates)
2733 {
2734 for (UINT32 index = 0; index < cReaders; index++)
2735 {
2736 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2737 free(readerState->szReader);
2738 }
2739 }
2740 free(rgReaderStates);
2741 free(states);
2742 return status;
2743}
2744
2745WINPR_ATTR_NODISCARD static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s,
2746 LPSCARD_READERSTATEW* ppcReaders,
2747 UINT32 cReaders, UINT32* ptrIndex)
2748{
2749 LONG status = SCARD_E_NO_MEMORY;
2750
2751 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2752
2753 if (cReaders > UINT8_MAX)
2754 {
2755 WLog_Print(log, WLOG_ERROR,
2756 "Too many readers(%" PRIu32 "), rejecting request. Limited to <= %d", cReaders,
2757 UINT8_MAX);
2758 return SCARD_E_WRITE_TOO_MANY;
2759 }
2760
2761 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2762 return status;
2763
2764 const UINT32 len = Stream_Get_UINT32(s);
2765 if (len != cReaders)
2766 {
2767 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2768 return status;
2769 }
2770
2771 LPSCARD_READERSTATEW rgReaderStates =
2772 (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2773 BOOL* states = calloc(cReaders, sizeof(BOOL));
2774
2775 if (!rgReaderStates || !states)
2776 goto fail;
2777
2778 status = ERROR_INVALID_DATA;
2779 for (UINT32 index = 0; index < cReaders; index++)
2780 {
2781 UINT32 ptr = UINT32_MAX;
2782 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2783
2784 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2785 goto fail;
2786
2787 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2788 {
2789 if (ptr != 0)
2790 goto fail;
2791 }
2792 /* Ignore nullptr length strings */
2793 states[index] = ptr != 0;
2794 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2795 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2796 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2797 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2798 {
2799 WLog_Print(log, WLOG_ERROR,
2800 "SCARD_READERSTATEW[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2801 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2802 goto fail;
2803 }
2804 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2805 }
2806
2807 for (UINT32 index = 0; index < cReaders; index++)
2808 {
2809 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2810
2811 /* Skip nullptr pointers */
2812 if (!states[index])
2813 continue;
2814
2815 status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2816 if (status != SCARD_S_SUCCESS)
2817 goto fail;
2818 if (!readerState->szReader)
2819 goto fail;
2820 }
2821
2822 *ppcReaders = rgReaderStates;
2823 free(states);
2824 return SCARD_S_SUCCESS;
2825fail:
2826 if (rgReaderStates)
2827 {
2828 for (UINT32 index = 0; index < cReaders; index++)
2829 {
2830 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2831 free(readerState->szReader);
2832 }
2833 }
2834 free(rgReaderStates);
2835 free(states);
2836 return status;
2837}
2838
2839/******************************************************************************/
2840/************************************* End Trace Functions ********************/
2841/******************************************************************************/
2842
2843LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2844{
2845 UINT32 ndrPtr = 0;
2846 UINT32 index = 0;
2847 UINT32 pbContextNdrPtr = 0;
2848
2849 WINPR_ASSERT(call);
2850 wLog* log = scard_log();
2851
2852 call->rgReaderStates = nullptr;
2853
2854 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2855 &pbContextNdrPtr);
2856 if (status != SCARD_S_SUCCESS)
2857 return status;
2858
2859 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2860 return STATUS_BUFFER_TOO_SMALL;
2861
2862 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2863 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2864 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2865 return ERROR_INVALID_DATA;
2866
2867 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2868 &(call->handles.hContext));
2869 if (status != SCARD_S_SUCCESS)
2870 return status;
2871
2872 if (ndrPtr)
2873 {
2874 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
2875 if (status != SCARD_S_SUCCESS)
2876 return status;
2877 call->cReaders = cReaders;
2878 }
2879 else
2880 {
2881 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2882 return SCARD_E_UNEXPECTED;
2883 }
2884
2885 smartcard_trace_get_status_change_a_call(log, call);
2886 return SCARD_S_SUCCESS;
2887}
2888
2889LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2890{
2891 UINT32 ndrPtr = 0;
2892 UINT32 index = 0;
2893 UINT32 pbContextNdrPtr = 0;
2894
2895 WINPR_ASSERT(call);
2896 wLog* log = scard_log();
2897 call->rgReaderStates = nullptr;
2898
2899 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2900 &pbContextNdrPtr);
2901 if (status != SCARD_S_SUCCESS)
2902 return status;
2903
2904 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2905 return STATUS_BUFFER_TOO_SMALL;
2906
2907 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2908 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2909 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2910 return ERROR_INVALID_DATA;
2911
2912 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2913 &(call->handles.hContext));
2914 if (status != SCARD_S_SUCCESS)
2915 return status;
2916
2917 if (ndrPtr)
2918 {
2919 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
2920 if (status != SCARD_S_SUCCESS)
2921 return status;
2922 call->cReaders = cReaders;
2923 }
2924 else
2925 {
2926 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2927 return SCARD_E_UNEXPECTED;
2928 }
2929
2930 smartcard_trace_get_status_change_w_call(log, call);
2931 return SCARD_S_SUCCESS;
2932}
2933
2934LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2935 BOOL unicode)
2936{
2937 WINPR_ASSERT(ret);
2938 wLog* log = scard_log();
2939
2940 LONG status = 0;
2941 UINT32 cReaders = ret->cReaders;
2942 UINT32 index = 0;
2943
2944 smartcard_trace_get_status_change_return(log, ret, unicode);
2945 if ((ret->ReturnCode != SCARD_S_SUCCESS) && (ret->ReturnCode != SCARD_E_TIMEOUT))
2946 cReaders = 0;
2947 if (cReaders == SCARD_AUTOALLOCATE)
2948 cReaders = 0;
2949
2950 if (!Stream_EnsureRemainingCapacity(s, 4))
2951 return SCARD_E_NO_MEMORY;
2952
2953 Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2954 if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2955 return SCARD_E_NO_MEMORY;
2956 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2957 if (status != SCARD_S_SUCCESS)
2958 return status;
2959 return ret->ReturnCode;
2960}
2961
2962LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2963{
2964 UINT32 index = 0;
2965 UINT32 pbContextNdrPtr = 0;
2966
2967 wLog* log = scard_log();
2968
2969 WINPR_ASSERT(call);
2970 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2971 &pbContextNdrPtr);
2972 if (status != SCARD_S_SUCCESS)
2973 return status;
2974
2975 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2976 if (status != SCARD_S_SUCCESS)
2977 return status;
2978
2979 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2980 return STATUS_BUFFER_TOO_SMALL;
2981
2982 Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2983 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2984
2985 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2986 &(call->handles.hContext));
2987 if (status != SCARD_S_SUCCESS)
2988 return status;
2989
2990 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2991 if (status != SCARD_S_SUCCESS)
2992 return status;
2993
2994 return status;
2995}
2996
2997LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2998{
2999 WINPR_ASSERT(ret);
3000 wLog* log = scard_log();
3001 LONG status = 0;
3002 UINT32 cbAtrLen = ret->cbAtrLen;
3003 UINT32 index = 0;
3004
3005 smartcard_trace_state_return(log, ret);
3006 if (ret->ReturnCode != SCARD_S_SUCCESS)
3007 cbAtrLen = 0;
3008 if (cbAtrLen == SCARD_AUTOALLOCATE)
3009 cbAtrLen = 0;
3010
3011 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
3012 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
3013 Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
3014 if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
3015 return SCARD_E_NO_MEMORY;
3016 status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
3017 if (status != SCARD_S_SUCCESS)
3018 return status;
3019 return ret->ReturnCode;
3020}
3021
3022LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
3023{
3024 UINT32 index = 0;
3025 UINT32 pbContextNdrPtr = 0;
3026
3027 WINPR_ASSERT(call);
3028 wLog* log = scard_log();
3029
3030 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3031 &pbContextNdrPtr);
3032 if (status != SCARD_S_SUCCESS)
3033 return status;
3034
3035 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3036 if (status != SCARD_S_SUCCESS)
3037 return status;
3038
3039 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3040 return STATUS_BUFFER_TOO_SMALL;
3041
3042 Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
3043 Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
3044 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
3045
3046 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3047 &(call->handles.hContext));
3048 if (status != SCARD_S_SUCCESS)
3049 return status;
3050
3051 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3052 if (status != SCARD_S_SUCCESS)
3053 return status;
3054
3055 smartcard_trace_status_call(log, call, unicode);
3056 return status;
3057}
3058
3059LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode)
3060{
3061 WINPR_ASSERT(call);
3062 wLog* log = scard_log();
3063 UINT32 index = 0;
3064
3065 smartcard_trace_status_call(log, call, unicode);
3066
3067 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3068 if (status != SCARD_S_SUCCESS)
3069 return status;
3070
3071 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3072 if (status != SCARD_S_SUCCESS)
3073 return status;
3074
3075 if (!Stream_EnsureRemainingCapacity(s, 12))
3076 return SCARD_E_NO_MEMORY;
3077
3078 Stream_Write_INT32(s, call->fmszReaderNamesIsNULL);
3079 Stream_Write_UINT32(s, call->cchReaderLen);
3080 Stream_Write_UINT32(s, call->cbAtrLen);
3081
3082 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3083 if (status != SCARD_S_SUCCESS)
3084 return status;
3085
3086 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3087}
3088
3089LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
3090{
3091 WINPR_ASSERT(ret);
3092 wLog* log = scard_log();
3093
3094 LONG status = 0;
3095 UINT32 index = 0;
3096 UINT32 cBytes = ret->cBytes;
3097
3098 smartcard_trace_status_return(log, ret, unicode);
3099 if (ret->ReturnCode != SCARD_S_SUCCESS)
3100 cBytes = 0;
3101 if (cBytes == SCARD_AUTOALLOCATE)
3102 cBytes = 0;
3103
3104 if (!Stream_EnsureRemainingCapacity(s, 4))
3105 return SCARD_F_INTERNAL_ERROR;
3106
3107 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
3108 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
3109 return SCARD_E_NO_MEMORY;
3110
3111 if (!Stream_EnsureRemainingCapacity(s, 44))
3112 return SCARD_F_INTERNAL_ERROR;
3113
3114 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
3115 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
3116 Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
3117 Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
3118 status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3119 if (status != SCARD_S_SUCCESS)
3120 return status;
3121 return ret->ReturnCode;
3122}
3123
3124LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode)
3125{
3126 WINPR_ASSERT(ret);
3127 wLog* log = scard_log();
3128 UINT32 index = 0;
3129 UINT32 mszNdrPtr = 0;
3130
3131 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3132 return STATUS_BUFFER_TOO_SMALL;
3133
3134 const UINT32 cBytes = Stream_Get_UINT32(s);
3135
3136 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3137 return ERROR_INVALID_DATA;
3138
3139 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 44))
3140 return STATUS_BUFFER_TOO_SMALL;
3141
3142 Stream_Read_UINT32(s, ret->dwState);
3143 Stream_Read_UINT32(s, ret->dwProtocol);
3144 Stream_Read(s, ret->pbAtr, sizeof(ret->pbAtr));
3145 Stream_Read_UINT32(s, ret->cbAtrLen);
3146
3147 if (ret->cbAtrLen > ARRAYSIZE(ret->pbAtr))
3148 {
3149 WLog_Print(log, WLOG_ERROR, "Status_Return::cbAtrLen %" PRIu32 " exceeds %" PRIuz,
3150 ret->cbAtrLen, ARRAYSIZE(ret->pbAtr));
3151 return SCARD_E_INVALID_ATR;
3152 }
3153
3154 if (mszNdrPtr)
3155 {
3156 LONG status = smartcard_ndr_read(log, s, &ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3157 if (status != SCARD_S_SUCCESS)
3158 return status;
3159 ret->cBytes = cBytes;
3160 }
3161
3162 smartcard_trace_status_return(log, ret, unicode);
3163 return SCARD_S_SUCCESS;
3164}
3165
3166LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
3167{
3168 WINPR_ASSERT(call);
3169 wLog* log = scard_log();
3170 UINT32 index = 0;
3171 UINT32 pbContextNdrPtr = 0;
3172
3173 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3174 &pbContextNdrPtr);
3175 if (status != SCARD_S_SUCCESS)
3176 return status;
3177
3178 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3179 if (status != SCARD_S_SUCCESS)
3180 return status;
3181
3182 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3183 return STATUS_BUFFER_TOO_SMALL;
3184
3185 Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
3186 Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
3187 Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
3188
3189 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3190 &(call->handles.hContext));
3191 if (status != SCARD_S_SUCCESS)
3192 return status;
3193
3194 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3195 if (status != SCARD_S_SUCCESS)
3196 return status;
3197
3198 smartcard_trace_get_attrib_call(log, call);
3199 return status;
3200}
3201
3202LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
3203 DWORD cbAttrCallLen)
3204{
3205 WINPR_ASSERT(ret);
3206 wLog* log = scard_log();
3207 LONG status = 0;
3208 UINT32 cbAttrLen = 0;
3209 UINT32 index = 0;
3210 smartcard_trace_get_attrib_return(log, ret, dwAttrId);
3211
3212 if (!Stream_EnsureRemainingCapacity(s, 4))
3213 return SCARD_F_INTERNAL_ERROR;
3214
3215 cbAttrLen = ret->cbAttrLen;
3216 if (ret->ReturnCode != SCARD_S_SUCCESS)
3217 cbAttrLen = 0;
3218 if (cbAttrLen == SCARD_AUTOALLOCATE)
3219 cbAttrLen = 0;
3220
3221 if (ret->pbAttr)
3222 {
3223 if (cbAttrCallLen < cbAttrLen)
3224 cbAttrLen = cbAttrCallLen;
3225 }
3226 Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
3227 if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
3228 return SCARD_E_NO_MEMORY;
3229
3230 status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
3231 if (status != SCARD_S_SUCCESS)
3232 return status;
3233 return ret->ReturnCode;
3234}
3235
3236LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
3237{
3238 WINPR_ASSERT(call);
3239 wLog* log = scard_log();
3240
3241 UINT32 index = 0;
3242 UINT32 pvInBufferNdrPtr = 0;
3243 UINT32 pbContextNdrPtr = 0;
3244
3245 call->pvInBuffer = nullptr;
3246
3247 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3248 &pbContextNdrPtr);
3249 if (status != SCARD_S_SUCCESS)
3250 return status;
3251
3252 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3253 if (status != SCARD_S_SUCCESS)
3254 return status;
3255
3256 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
3257 return STATUS_BUFFER_TOO_SMALL;
3258
3259 Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
3260 const UINT32 cbInBufferSize = Stream_Get_UINT32(s); /* cbInBufferSize (4 bytes) */
3261 if (!smartcard_ndr_pointer_read(log, s, &index,
3262 &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
3263 return ERROR_INVALID_DATA;
3264 Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
3265 Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
3266
3267 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3268 &(call->handles.hContext));
3269 if (status != SCARD_S_SUCCESS)
3270 return status;
3271
3272 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3273 if (status != SCARD_S_SUCCESS)
3274 return status;
3275
3276 if (pvInBufferNdrPtr)
3277 {
3278 status = smartcard_ndr_read(log, s, &call->pvInBuffer, cbInBufferSize, 1, NDR_PTR_SIMPLE);
3279 if (status != SCARD_S_SUCCESS)
3280 return status;
3281 call->cbInBufferSize = cbInBufferSize;
3282 }
3283
3284 smartcard_trace_control_call(log, call);
3285 return SCARD_S_SUCCESS;
3286}
3287
3288LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
3289{
3290 WINPR_ASSERT(ret);
3291 wLog* log = scard_log();
3292
3293 LONG status = 0;
3294 UINT32 cbDataLen = ret->cbOutBufferSize;
3295 UINT32 index = 0;
3296
3297 smartcard_trace_control_return(log, ret);
3298 if (ret->ReturnCode != SCARD_S_SUCCESS)
3299 cbDataLen = 0;
3300 if (cbDataLen == SCARD_AUTOALLOCATE)
3301 cbDataLen = 0;
3302
3303 if (!Stream_EnsureRemainingCapacity(s, 4))
3304 return SCARD_F_INTERNAL_ERROR;
3305
3306 Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
3307 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3308 return SCARD_E_NO_MEMORY;
3309
3310 status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
3311 if (status != SCARD_S_SUCCESS)
3312 return status;
3313 return ret->ReturnCode;
3314}
3315
3316LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
3317{
3318 UINT32 length = 0;
3319 BYTE* pbExtraBytes = nullptr;
3320 UINT32 pbExtraBytesNdrPtr = 0;
3321 UINT32 pbSendBufferNdrPtr = 0;
3322 UINT32 pioRecvPciNdrPtr = 0;
3323 SCardIO_Request ioSendPci;
3324 SCardIO_Request ioRecvPci;
3325 UINT32 index = 0;
3326 UINT32 pbContextNdrPtr = 0;
3327
3328 WINPR_ASSERT(call);
3329 wLog* log = scard_log();
3330
3331 call->pioSendPci = nullptr;
3332 call->pioRecvPci = nullptr;
3333 call->pbSendBuffer = nullptr;
3334
3335 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3336 &pbContextNdrPtr);
3337 if (status != SCARD_S_SUCCESS)
3338 return status;
3339
3340 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3341 if (status != SCARD_S_SUCCESS)
3342 return status;
3343
3344 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
3345 return STATUS_BUFFER_TOO_SMALL;
3346
3347 Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
3348 Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3349 if (!smartcard_ndr_pointer_read(log, s, &index,
3350 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3351 return ERROR_INVALID_DATA;
3352
3353 const UINT32 cbSendLength = Stream_Get_UINT32(s); /* cbSendLength (4 bytes) */
3354 if (!smartcard_ndr_pointer_read(log, s, &index,
3355 &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3356 return ERROR_INVALID_DATA;
3357
3358 if (!smartcard_ndr_pointer_read(log, s, &index,
3359 &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3360 return ERROR_INVALID_DATA;
3361
3362 Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3363 Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
3364
3365 if (ioSendPci.cbExtraBytes > 1024)
3366 {
3367 WLog_Print(log, WLOG_WARN,
3368 "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3369 ioSendPci.cbExtraBytes);
3370 return STATUS_INVALID_PARAMETER;
3371 }
3372
3373 if (cbSendLength > 66560)
3374 {
3375 WLog_Print(log, WLOG_WARN,
3376 "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3377 ioSendPci.cbExtraBytes);
3378 return STATUS_INVALID_PARAMETER;
3379 }
3380
3381 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3382 &(call->handles.hContext));
3383 if (status != SCARD_S_SUCCESS)
3384 return status;
3385
3386 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3387 if (status != SCARD_S_SUCCESS)
3388 return status;
3389
3390 if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3391 {
3392 WLog_Print(
3393 log, WLOG_WARN,
3394 "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3395 return STATUS_INVALID_PARAMETER;
3396 }
3397
3398 if (pbExtraBytesNdrPtr)
3399 {
3400 // TODO: Use unified pointer reading
3401 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3402 return STATUS_BUFFER_TOO_SMALL;
3403
3404 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3405
3406 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3407 return STATUS_BUFFER_TOO_SMALL;
3408
3409 ioSendPci.pbExtraBytes = Stream_Pointer(s);
3410 call->pioSendPci =
3411 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3412
3413 if (!call->pioSendPci)
3414 {
3415 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3416 return STATUS_NO_MEMORY;
3417 }
3418
3419 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3420 call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3421 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3422 Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3423 if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3424 return STATUS_INVALID_PARAMETER;
3425 }
3426 else
3427 {
3428 call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3429
3430 if (!call->pioSendPci)
3431 {
3432 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3433 return STATUS_NO_MEMORY;
3434 }
3435
3436 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3437 call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3438 }
3439
3440 if (pbSendBufferNdrPtr)
3441 {
3442 status = smartcard_ndr_read(log, s, &call->pbSendBuffer, cbSendLength, 1, NDR_PTR_SIMPLE);
3443 if (status != SCARD_S_SUCCESS)
3444 return status;
3445 call->cbSendLength = cbSendLength;
3446 }
3447
3448 if (pioRecvPciNdrPtr)
3449 {
3450 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3451 return STATUS_BUFFER_TOO_SMALL;
3452
3453 Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
3454 Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3455 if (!smartcard_ndr_pointer_read(log, s, &index,
3456 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3457 return ERROR_INVALID_DATA;
3458
3459 if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3460 {
3461 WLog_Print(
3462 log, WLOG_WARN,
3463 "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3464 return STATUS_INVALID_PARAMETER;
3465 }
3466
3467 if (pbExtraBytesNdrPtr)
3468 {
3469 // TODO: Unify ndr pointer reading
3470 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3471 return STATUS_BUFFER_TOO_SMALL;
3472
3473 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3474
3475 if (ioRecvPci.cbExtraBytes > 1024)
3476 {
3477 WLog_Print(log, WLOG_WARN,
3478 "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3479 " (max: 1024)",
3480 ioRecvPci.cbExtraBytes);
3481 return STATUS_INVALID_PARAMETER;
3482 }
3483
3484 if (length != ioRecvPci.cbExtraBytes)
3485 {
3486 WLog_Print(log, WLOG_WARN,
3487 "Transmit_Call unexpected length: Actual: %" PRIu32
3488 ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3489 length, ioRecvPci.cbExtraBytes);
3490 return STATUS_INVALID_PARAMETER;
3491 }
3492
3493 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3494 return STATUS_BUFFER_TOO_SMALL;
3495
3496 ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3497 call->pioRecvPci =
3498 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3499
3500 if (!call->pioRecvPci)
3501 {
3502 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3503 return STATUS_NO_MEMORY;
3504 }
3505
3506 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3507 call->pioRecvPci->cbPciLength =
3508 (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3509 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3510 Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3511 if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3512 return STATUS_INVALID_PARAMETER;
3513 }
3514 else
3515 {
3516 call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3517
3518 if (!call->pioRecvPci)
3519 {
3520 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3521 return STATUS_NO_MEMORY;
3522 }
3523
3524 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3525 call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3526 }
3527 }
3528
3529 smartcard_trace_transmit_call(log, call);
3530 return SCARD_S_SUCCESS;
3531}
3532
3533LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3534{
3535 WINPR_ASSERT(ret);
3536 wLog* log = scard_log();
3537
3538 LONG status = 0;
3539 UINT32 index = 0;
3540 LONG error = 0;
3541 UINT32 cbRecvLength = ret->cbRecvLength;
3542 UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3543
3544 smartcard_trace_transmit_return(log, ret);
3545
3546 if (!ret->pbRecvBuffer)
3547 cbRecvLength = 0;
3548
3549 if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3550 return SCARD_E_NO_MEMORY;
3551 if (!Stream_EnsureRemainingCapacity(s, 4))
3552 return SCARD_E_NO_MEMORY;
3553 Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3554 if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3555 return SCARD_E_NO_MEMORY;
3556
3557 if (ret->pioRecvPci)
3558 {
3559 UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3560 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3561
3562 if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16ull))
3563 {
3564 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3565 return SCARD_F_INTERNAL_ERROR;
3566 }
3567
3568 Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3569 Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
3570 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3571 return SCARD_E_NO_MEMORY;
3572 error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3573 if (error)
3574 return error;
3575 }
3576
3577 status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3578 if (status != SCARD_S_SUCCESS)
3579 return status;
3580 return ret->ReturnCode;
3581}
3582
3583LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3584{
3585 UINT32 rgReaderStatesNdrPtr = 0;
3586 UINT32 rgAtrMasksNdrPtr = 0;
3587 UINT32 index = 0;
3588 UINT32 pbContextNdrPtr = 0;
3589
3590 WINPR_ASSERT(call);
3591 wLog* log = scard_log();
3592
3593 call->rgReaderStates = nullptr;
3594
3595 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3596 &pbContextNdrPtr);
3597 if (status != SCARD_S_SUCCESS)
3598 return status;
3599
3600 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3601 return STATUS_BUFFER_TOO_SMALL;
3602
3603 Stream_Read_UINT32(s, call->cAtrs);
3604 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3605 return ERROR_INVALID_DATA;
3606 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3607 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3608 return ERROR_INVALID_DATA;
3609
3610 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3611 &(call->handles.hContext));
3612 if (status != SCARD_S_SUCCESS)
3613 return status;
3614
3615 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3616 {
3617 WLog_Print(log, WLOG_WARN,
3618 "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3619 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3620 rgAtrMasksNdrPtr, call->cAtrs);
3621 return STATUS_INVALID_PARAMETER;
3622 }
3623
3624 if (rgAtrMasksNdrPtr)
3625 {
3626 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3627 if (status != SCARD_S_SUCCESS)
3628 return status;
3629 }
3630
3631 if (rgReaderStatesNdrPtr)
3632 {
3633 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3634 if (status != SCARD_S_SUCCESS)
3635 return status;
3636 call->cReaders = cReaders;
3637 }
3638
3639 smartcard_trace_locate_cards_by_atr_a_call(log, call);
3640 return SCARD_S_SUCCESS;
3641}
3642
3643LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3644{
3645 UINT32 sz1NdrPtr = 0;
3646 UINT32 sz2NdrPtr = 0;
3647 UINT32 index = 0;
3648 UINT32 pbContextNdrPtr = 0;
3649
3650 WINPR_ASSERT(call);
3651 wLog* log = scard_log();
3652
3653 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3654 &pbContextNdrPtr);
3655 if (status != SCARD_S_SUCCESS)
3656 return status;
3657
3658 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3659 return ERROR_INVALID_DATA;
3660 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3661 return ERROR_INVALID_DATA;
3662
3663 status =
3664 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3665 if (status != SCARD_S_SUCCESS)
3666 return status;
3667
3668 if (sz1NdrPtr)
3669 {
3670 status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3671 if (status != SCARD_S_SUCCESS)
3672 return status;
3673 }
3674 if (sz2NdrPtr)
3675 {
3676 status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3677 if (status != SCARD_S_SUCCESS)
3678 return status;
3679 }
3680 smartcard_trace_context_and_two_strings_a_call(log, call);
3681 return SCARD_S_SUCCESS;
3682}
3683
3684LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3685{
3686 UINT32 sz1NdrPtr = 0;
3687 UINT32 sz2NdrPtr = 0;
3688 UINT32 index = 0;
3689 UINT32 pbContextNdrPtr = 0;
3690
3691 WINPR_ASSERT(call);
3692 wLog* log = scard_log();
3693
3694 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3695 &pbContextNdrPtr);
3696 if (status != SCARD_S_SUCCESS)
3697 return status;
3698
3699 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3700 return ERROR_INVALID_DATA;
3701 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3702 return ERROR_INVALID_DATA;
3703
3704 status =
3705 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3706 if (status != SCARD_S_SUCCESS)
3707 return status;
3708
3709 if (sz1NdrPtr)
3710 {
3711 status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3712 if (status != SCARD_S_SUCCESS)
3713 return status;
3714 }
3715 if (sz2NdrPtr)
3716 {
3717 status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3718 if (status != SCARD_S_SUCCESS)
3719 return status;
3720 }
3721 smartcard_trace_context_and_two_strings_w_call(log, call);
3722 return SCARD_S_SUCCESS;
3723}
3724
3725LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3726{
3727 UINT32 sz1NdrPtr = 0;
3728 UINT32 sz2NdrPtr = 0;
3729 UINT32 index = 0;
3730 UINT32 pbContextNdrPtr = 0;
3731
3732 WINPR_ASSERT(call);
3733 wLog* log = scard_log();
3734
3735 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3736 &pbContextNdrPtr);
3737 if (status != SCARD_S_SUCCESS)
3738 return status;
3739
3740 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3741 return STATUS_BUFFER_TOO_SMALL;
3742
3743 const UINT32 cBytes = Stream_Get_UINT32(s);
3744 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3745 return ERROR_INVALID_DATA;
3746
3747 const UINT32 cReaders = Stream_Get_UINT32(s);
3748 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3749 return ERROR_INVALID_DATA;
3750
3751 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3752 &(call->handles.hContext));
3753 if (status != SCARD_S_SUCCESS)
3754 return status;
3755
3756 if (sz1NdrPtr)
3757 {
3758 status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3759 if (status != SCARD_S_SUCCESS)
3760 return status;
3761 call->cBytes = cBytes;
3762 }
3763 if (sz2NdrPtr)
3764 {
3765 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3766 if (status != SCARD_S_SUCCESS)
3767 return status;
3768 call->cReaders = cReaders;
3769 }
3770 smartcard_trace_locate_cards_a_call(log, call);
3771 return SCARD_S_SUCCESS;
3772}
3773
3774LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3775{
3776 UINT32 sz1NdrPtr = 0;
3777 UINT32 sz2NdrPtr = 0;
3778 UINT32 index = 0;
3779 UINT32 pbContextNdrPtr = 0;
3780
3781 WINPR_ASSERT(call);
3782 wLog* log = scard_log();
3783
3784 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3785 &pbContextNdrPtr);
3786 if (status != SCARD_S_SUCCESS)
3787 return status;
3788
3789 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3790 return STATUS_BUFFER_TOO_SMALL;
3791
3792 const UINT32 cBytes = Stream_Get_UINT32(s);
3793 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3794 return ERROR_INVALID_DATA;
3795
3796 const UINT32 cReaders = Stream_Get_UINT32(s);
3797 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3798 return ERROR_INVALID_DATA;
3799
3800 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3801 &(call->handles.hContext));
3802 if (status != SCARD_S_SUCCESS)
3803 return status;
3804
3805 if (sz1NdrPtr)
3806 {
3807 status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3808 if (status != SCARD_S_SUCCESS)
3809 return status;
3810 call->cBytes = cBytes;
3811 }
3812 if (sz2NdrPtr)
3813 {
3814 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3815 if (status != SCARD_S_SUCCESS)
3816 return status;
3817 call->cReaders = cReaders;
3818 }
3819 smartcard_trace_locate_cards_w_call(log, call);
3820 return SCARD_S_SUCCESS;
3821}
3822
3823LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3824{
3825 UINT32 index = 0;
3826 UINT32 ndrPtr = 0;
3827 UINT32 pbContextNdrPtr = 0;
3828
3829 WINPR_ASSERT(call);
3830 wLog* log = scard_log();
3831
3832 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3833 &pbContextNdrPtr);
3834 if (status != SCARD_S_SUCCESS)
3835 return status;
3836 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3837 if (status != SCARD_S_SUCCESS)
3838 return status;
3839
3840 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3841 return STATUS_BUFFER_TOO_SMALL;
3842 Stream_Read_UINT32(s, call->dwAttrId);
3843 Stream_Read_UINT32(s, call->cbAttrLen);
3844
3845 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3846 return ERROR_INVALID_DATA;
3847
3848 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3849 &(call->handles.hContext));
3850 if (status != SCARD_S_SUCCESS)
3851 return status;
3852
3853 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3854 if (status != SCARD_S_SUCCESS)
3855 return status;
3856
3857 if (ndrPtr)
3858 {
3859 size_t len = 0;
3860 status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3861 if (status != SCARD_S_SUCCESS)
3862 return status;
3863 if (call->cbAttrLen > len)
3864 call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3865 }
3866 else
3867 call->cbAttrLen = 0;
3868 smartcard_trace_set_attrib_call(log, call);
3869 return SCARD_S_SUCCESS;
3870}
3871
3872LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call)
3873{
3874 WINPR_ASSERT(call);
3875 wLog* log = scard_log();
3876 UINT32 index = 0;
3877
3878 smartcard_trace_set_attrib_call(log, call);
3879
3880 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3881 if (status != SCARD_S_SUCCESS)
3882 return status;
3883
3884 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3885 if (status != SCARD_S_SUCCESS)
3886 return status;
3887
3888 if (!Stream_EnsureRemainingCapacity(s, 8))
3889 return SCARD_E_NO_MEMORY;
3890
3891 Stream_Write_UINT32(s, call->dwAttrId);
3892 Stream_Write_UINT32(s, call->cbAttrLen);
3893
3894 if (!smartcard_ndr_pointer_write(s, &index, call->cbAttrLen))
3895 return SCARD_E_NO_MEMORY;
3896
3897 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3898 if (status != SCARD_S_SUCCESS)
3899 return status;
3900
3901 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3902 if (status != SCARD_S_SUCCESS)
3903 return status;
3904
3905 status = smartcard_ndr_write(s, call->pbAttr, call->cbAttrLen, 1, NDR_PTR_SIMPLE);
3906 if (status != SCARD_S_SUCCESS)
3907 return status;
3908
3909 return SCARD_S_SUCCESS;
3910}
3911
3912LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3913{
3914 UINT32 rgReaderStatesNdrPtr = 0;
3915 UINT32 rgAtrMasksNdrPtr = 0;
3916 UINT32 index = 0;
3917 UINT32 pbContextNdrPtr = 0;
3918
3919 WINPR_ASSERT(call);
3920 wLog* log = scard_log();
3921
3922 call->rgReaderStates = nullptr;
3923
3924 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3925 &pbContextNdrPtr);
3926 if (status != SCARD_S_SUCCESS)
3927 return status;
3928
3929 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3930 return STATUS_BUFFER_TOO_SMALL;
3931
3932 Stream_Read_UINT32(s, call->cAtrs);
3933 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3934 return ERROR_INVALID_DATA;
3935
3936 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3937 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3938 return ERROR_INVALID_DATA;
3939
3940 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3941 &(call->handles.hContext));
3942 if (status != SCARD_S_SUCCESS)
3943 return status;
3944
3945 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3946 {
3947 WLog_Print(log, WLOG_WARN,
3948 "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3949 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3950 rgAtrMasksNdrPtr, call->cAtrs);
3951 return STATUS_INVALID_PARAMETER;
3952 }
3953
3954 if (rgAtrMasksNdrPtr)
3955 {
3956 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3957 if (status != SCARD_S_SUCCESS)
3958 return status;
3959 }
3960
3961 if (rgReaderStatesNdrPtr)
3962 {
3963 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3964 if (status != SCARD_S_SUCCESS)
3965 return status;
3966 call->cReaders = cReaders;
3967 }
3968
3969 smartcard_trace_locate_cards_by_atr_w_call(log, call);
3970 return SCARD_S_SUCCESS;
3971}
3972
3973LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3974{
3975 UINT32 mszNdrPtr = 0;
3976 UINT32 contextNdrPtr = 0;
3977 UINT32 index = 0;
3978 UINT32 pbContextNdrPtr = 0;
3979
3980 WINPR_ASSERT(call);
3981 wLog* log = scard_log();
3982
3983 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3984 return ERROR_INVALID_DATA;
3985
3986 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3987 &index, &pbContextNdrPtr);
3988 if (status != SCARD_S_SUCCESS)
3989 return status;
3990
3991 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3992 return ERROR_INVALID_DATA;
3993
3994 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3995 return STATUS_BUFFER_TOO_SMALL;
3996 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3997 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3998 Stream_Read_UINT32(s, call->Common.cbDataLen);
3999
4000 call->szLookupName = nullptr;
4001 if (mszNdrPtr)
4002 {
4003 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4004 if (status != SCARD_S_SUCCESS)
4005 return status;
4006 }
4007
4008 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4009 &call->Common.handles.hContext);
4010 if (status != SCARD_S_SUCCESS)
4011 return status;
4012
4013 if (contextNdrPtr)
4014 {
4015 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4016 if (status != SCARD_S_SUCCESS)
4017 return status;
4018 }
4019 smartcard_trace_read_cache_a_call(log, call);
4020 return SCARD_S_SUCCESS;
4021}
4022
4023LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
4024{
4025 UINT32 mszNdrPtr = 0;
4026 UINT32 contextNdrPtr = 0;
4027 UINT32 index = 0;
4028 UINT32 pbContextNdrPtr = 0;
4029
4030 WINPR_ASSERT(call);
4031 wLog* log = scard_log();
4032
4033 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4034 return ERROR_INVALID_DATA;
4035
4036 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4037 &index, &pbContextNdrPtr);
4038 if (status != SCARD_S_SUCCESS)
4039 return status;
4040
4041 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4042 return ERROR_INVALID_DATA;
4043
4044 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
4045 return STATUS_BUFFER_TOO_SMALL;
4046 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4047 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
4048 Stream_Read_UINT32(s, call->Common.cbDataLen);
4049
4050 call->szLookupName = nullptr;
4051 if (mszNdrPtr)
4052 {
4053 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4054 if (status != SCARD_S_SUCCESS)
4055 return status;
4056 }
4057
4058 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4059 &call->Common.handles.hContext);
4060 if (status != SCARD_S_SUCCESS)
4061 return status;
4062
4063 if (contextNdrPtr)
4064 {
4065 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4066 if (status != SCARD_S_SUCCESS)
4067 return status;
4068 }
4069 smartcard_trace_read_cache_w_call(log, call);
4070 return SCARD_S_SUCCESS;
4071}
4072
4073LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
4074{
4075 UINT32 mszNdrPtr = 0;
4076 UINT32 contextNdrPtr = 0;
4077 UINT32 pbDataNdrPtr = 0;
4078 UINT32 index = 0;
4079 UINT32 pbContextNdrPtr = 0;
4080
4081 WINPR_ASSERT(call);
4082 wLog* log = scard_log();
4083
4084 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4085 return ERROR_INVALID_DATA;
4086
4087 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4088 &index, &pbContextNdrPtr);
4089 if (status != SCARD_S_SUCCESS)
4090 return status;
4091
4092 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4093 return ERROR_INVALID_DATA;
4094
4095 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4096 return STATUS_BUFFER_TOO_SMALL;
4097
4098 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4099 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4100
4101 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4102 return ERROR_INVALID_DATA;
4103
4104 call->szLookupName = nullptr;
4105 if (mszNdrPtr)
4106 {
4107 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4108 if (status != SCARD_S_SUCCESS)
4109 return status;
4110 }
4111
4112 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4113 &call->Common.handles.hContext);
4114 if (status != SCARD_S_SUCCESS)
4115 return status;
4116
4117 call->Common.CardIdentifier = nullptr;
4118 if (contextNdrPtr)
4119 {
4120 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4121 if (status != SCARD_S_SUCCESS)
4122 return status;
4123 }
4124
4125 call->Common.pbData = nullptr;
4126 if (pbDataNdrPtr)
4127 {
4128 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4129 if (status != SCARD_S_SUCCESS)
4130 return status;
4131 call->Common.cbDataLen = cbDataLen;
4132 }
4133 smartcard_trace_write_cache_a_call(log, call);
4134 return SCARD_S_SUCCESS;
4135}
4136
4137LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
4138{
4139 UINT32 mszNdrPtr = 0;
4140 UINT32 contextNdrPtr = 0;
4141 UINT32 pbDataNdrPtr = 0;
4142 UINT32 index = 0;
4143 UINT32 pbContextNdrPtr = 0;
4144
4145 WINPR_ASSERT(call);
4146 wLog* log = scard_log();
4147
4148 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4149 return ERROR_INVALID_DATA;
4150
4151 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4152 &index, &pbContextNdrPtr);
4153 if (status != SCARD_S_SUCCESS)
4154 return status;
4155
4156 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4157 return ERROR_INVALID_DATA;
4158
4159 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4160 return STATUS_BUFFER_TOO_SMALL;
4161 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4162 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4163
4164 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4165 return ERROR_INVALID_DATA;
4166
4167 call->szLookupName = nullptr;
4168 if (mszNdrPtr)
4169 {
4170 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4171 if (status != SCARD_S_SUCCESS)
4172 return status;
4173 }
4174
4175 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4176 &call->Common.handles.hContext);
4177 if (status != SCARD_S_SUCCESS)
4178 return status;
4179
4180 call->Common.CardIdentifier = nullptr;
4181 if (contextNdrPtr)
4182 {
4183 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4184 if (status != SCARD_S_SUCCESS)
4185 return status;
4186 }
4187
4188 call->Common.pbData = nullptr;
4189 if (pbDataNdrPtr)
4190 {
4191 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4192 if (status != SCARD_S_SUCCESS)
4193 return status;
4194 call->Common.cbDataLen = cbDataLen;
4195 }
4196 smartcard_trace_write_cache_w_call(log, call);
4197 return status;
4198}
4199
4200LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
4201{
4202 WINPR_ASSERT(call);
4203 wLog* log = scard_log();
4204
4205 UINT32 index = 0;
4206 UINT32 pbContextNdrPtr = 0;
4207
4208 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
4209 &pbContextNdrPtr);
4210 if (status != SCARD_S_SUCCESS)
4211 return status;
4212
4213 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
4214 if (status != SCARD_S_SUCCESS)
4215 return status;
4216
4217 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4218 &(call->handles.hContext));
4219 if (status != SCARD_S_SUCCESS)
4220 {
4221 WLog_Print(log, WLOG_ERROR,
4222 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
4223 status);
4224 return status;
4225 }
4226
4227 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
4228 if (status != SCARD_S_SUCCESS)
4229 WLog_Print(log, WLOG_ERROR,
4230 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
4231
4232 smartcard_trace_get_transmit_count_call(log, call);
4233 return status;
4234}
4235
4236LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
4237{
4238 WINPR_ASSERT(call);
4239 wLog* log = scard_log();
4240 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4241 &call->szReaderName);
4242}
4243
4244LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
4245{
4246 WINPR_ASSERT(call);
4247 wLog* log = scard_log();
4248 return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
4249}
4250
4251LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
4252{
4253 WINPR_ASSERT(call);
4254 wLog* log = scard_log();
4255 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
4256}
4257
4258LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
4259{
4260 WINPR_ASSERT(call);
4261 wLog* log = scard_log();
4262 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4263 &call->szReaderName);
4264}
4265
4266LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
4267{
4268 WINPR_ASSERT(ret);
4269 wLog* log = scard_log();
4270 smartcard_trace_device_type_id_return(log, ret);
4271
4272 if (!Stream_EnsureRemainingCapacity(s, 4))
4273 {
4274 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4275 return SCARD_F_INTERNAL_ERROR;
4276 }
4277
4278 Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
4279
4280 return ret->ReturnCode;
4281}
4282
4283LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
4284{
4285 WINPR_ASSERT(ret);
4286 wLog* log = scard_log();
4287
4288 LONG status = 0;
4289 UINT32 cbDataLen = ret->cReaders;
4290 UINT32 index = 0;
4291
4292 smartcard_trace_locate_cards_return(log, ret);
4293 if (ret->ReturnCode != SCARD_S_SUCCESS)
4294 cbDataLen = 0;
4295 if (cbDataLen == SCARD_AUTOALLOCATE)
4296 cbDataLen = 0;
4297
4298 if (!Stream_EnsureRemainingCapacity(s, 4))
4299 {
4300 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4301 return SCARD_F_INTERNAL_ERROR;
4302 }
4303
4304 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4305 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4306 return SCARD_E_NO_MEMORY;
4307
4308 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
4309 if (status != SCARD_S_SUCCESS)
4310 return status;
4311 return ret->ReturnCode;
4312}
4313
4314LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
4315{
4316 WINPR_ASSERT(ret);
4317 wLog* log = scard_log();
4318
4319 LONG status = 0;
4320 UINT32 index = 0;
4321 UINT32 cbDataLen = ret->cbDataLen;
4322 smartcard_trace_get_reader_icon_return(log, ret);
4323 if (ret->ReturnCode != SCARD_S_SUCCESS)
4324 cbDataLen = 0;
4325 if (cbDataLen == SCARD_AUTOALLOCATE)
4326 cbDataLen = 0;
4327
4328 if (!Stream_EnsureRemainingCapacity(s, 4))
4329 {
4330 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4331 return SCARD_F_INTERNAL_ERROR;
4332 }
4333
4334 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4335 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4336 return SCARD_E_NO_MEMORY;
4337
4338 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4339 if (status != SCARD_S_SUCCESS)
4340 return status;
4341 return ret->ReturnCode;
4342}
4343
4344LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
4345{
4346 WINPR_ASSERT(ret);
4347 wLog* log = scard_log();
4348
4349 smartcard_trace_get_transmit_count_return(log, ret);
4350
4351 if (!Stream_EnsureRemainingCapacity(s, 4))
4352 {
4353 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4354 return SCARD_F_INTERNAL_ERROR;
4355 }
4356
4357 Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
4358
4359 return ret->ReturnCode;
4360}
4361
4362LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
4363{
4364 WINPR_ASSERT(ret);
4365 wLog* log = scard_log();
4366
4367 LONG status = 0;
4368 UINT32 index = 0;
4369 UINT32 cbDataLen = ret->cbDataLen;
4370 smartcard_trace_read_cache_return(log, ret);
4371 if (ret->ReturnCode != SCARD_S_SUCCESS)
4372 cbDataLen = 0;
4373
4374 if (cbDataLen == SCARD_AUTOALLOCATE)
4375 cbDataLen = 0;
4376
4377 if (!Stream_EnsureRemainingCapacity(s, 4))
4378 {
4379 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4380 return SCARD_F_INTERNAL_ERROR;
4381 }
4382
4383 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4384 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4385 return SCARD_E_NO_MEMORY;
4386
4387 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4388 if (status != SCARD_S_SUCCESS)
4389 return status;
4390 return ret->ReturnCode;
4391}
4392
4393LONG smartcard_pack_context_call(wStream* s, const Context_Call* call, const char* name)
4394{
4395 WINPR_ASSERT(call);
4396 wLog* log = scard_log();
4397 UINT32 index = 0;
4398
4399 smartcard_trace_context_call(log, call, name);
4400
4401 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4402 if (status != SCARD_S_SUCCESS)
4403 return status;
4404
4405 return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4406}
4407
4408LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call, BOOL unicode)
4409{
4410 WINPR_ASSERT(call);
4411 wLog* log = scard_log();
4412 UINT32 index = 0;
4413
4414 smartcard_trace_list_readers_call(log, call, unicode);
4415
4416 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4417 if (status != SCARD_S_SUCCESS)
4418 return status;
4419
4420 if (!Stream_EnsureRemainingCapacity(s, 4))
4421 return SCARD_E_NO_MEMORY;
4422
4423 Stream_Write_UINT32(s, call->cBytes);
4424 if (!smartcard_ndr_pointer_write(s, &index, call->cBytes))
4425 return SCARD_E_NO_MEMORY;
4426
4427 if (!Stream_EnsureRemainingCapacity(s, 8))
4428 return SCARD_E_NO_MEMORY;
4429
4430 Stream_Write_INT32(s, call->fmszReadersIsNULL);
4431 Stream_Write_UINT32(s, call->cchReaders);
4432
4433 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4434 if (status != SCARD_S_SUCCESS)
4435 return status;
4436
4437 if (call->cBytes > 0)
4438 {
4439 status = smartcard_ndr_write(s, call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
4440 if (status != SCARD_S_SUCCESS)
4441 return status;
4442 }
4443
4444 return SCARD_S_SUCCESS;
4445}
4446
4447WINPR_ATTR_NODISCARD static LONG
4448smartcard_pack_reader_state_a(wStream* s, const LPSCARD_READERSTATEA rgReaderStates,
4449 UINT32 cReaders, UINT32* ptrIndex)
4450{
4451 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4452
4453 if (!Stream_EnsureRemainingCapacity(s, 4))
4454 return SCARD_E_NO_MEMORY;
4455
4456 Stream_Write_UINT32(s, cReaders);
4457
4458 for (UINT32 i = 0; i < cReaders; i++)
4459 {
4460 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4461
4462 if (!Stream_EnsureRemainingCapacity(s, 52))
4463 return SCARD_E_NO_MEMORY;
4464
4465 const UINT32 nameLen = state->szReader ? (UINT32)(strlen(state->szReader) + 1) : 0;
4466 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4467 return SCARD_E_NO_MEMORY;
4468
4469 Stream_Write_UINT32(s, state->dwCurrentState);
4470 Stream_Write_UINT32(s, state->dwEventState);
4471 Stream_Write_UINT32(s, state->cbAtr);
4472 Stream_Write(s, state->rgbAtr, 36);
4473 }
4474
4475 for (UINT32 i = 0; i < cReaders; i++)
4476 {
4477 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4478
4479 if (state->szReader)
4480 {
4481 const UINT32 nameLen = (UINT32)(strlen(state->szReader) + 1);
4482 LONG status = smartcard_ndr_write_a(s, state->szReader, nameLen, NDR_PTR_FULL);
4483 if (status != SCARD_S_SUCCESS)
4484 return status;
4485 }
4486 }
4487
4488 return SCARD_S_SUCCESS;
4489}
4490
4491WINPR_ATTR_NODISCARD static LONG
4492smartcard_pack_reader_state_w(wStream* s, const LPSCARD_READERSTATEW rgReaderStates,
4493 UINT32 cReaders, UINT32* ptrIndex)
4494{
4495 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4496
4497 if (!Stream_EnsureRemainingCapacity(s, 4))
4498 return SCARD_E_NO_MEMORY;
4499
4500 Stream_Write_UINT32(s, cReaders);
4501
4502 for (UINT32 i = 0; i < cReaders; i++)
4503 {
4504 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4505
4506 if (!Stream_EnsureRemainingCapacity(s, 52))
4507 return SCARD_E_NO_MEMORY;
4508
4509 const UINT32 nameLen = state->szReader ? (UINT32)(_wcslen(state->szReader) + 1) : 0;
4510 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4511 return SCARD_E_NO_MEMORY;
4512
4513 Stream_Write_UINT32(s, state->dwCurrentState);
4514 Stream_Write_UINT32(s, state->dwEventState);
4515 Stream_Write_UINT32(s, state->cbAtr);
4516 Stream_Write(s, state->rgbAtr, 36);
4517 }
4518
4519 for (UINT32 i = 0; i < cReaders; i++)
4520 {
4521 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4522
4523 if (state->szReader)
4524 {
4525 const UINT32 nameLen = (UINT32)(_wcslen(state->szReader) + 1);
4526 LONG status = smartcard_ndr_write_w(s, state->szReader, nameLen, NDR_PTR_FULL);
4527 if (status != SCARD_S_SUCCESS)
4528 return status;
4529 }
4530 }
4531
4532 return SCARD_S_SUCCESS;
4533}
4534
4535LONG smartcard_pack_get_status_change_a_call(wStream* s, const GetStatusChangeA_Call* call)
4536{
4537 WINPR_ASSERT(call);
4538 wLog* log = scard_log();
4539 UINT32 index = 0;
4540
4541 smartcard_trace_get_status_change_a_call(log, call);
4542
4543 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4544 if (status != SCARD_S_SUCCESS)
4545 return status;
4546
4547 if (!Stream_EnsureRemainingCapacity(s, 8))
4548 return SCARD_E_NO_MEMORY;
4549
4550 Stream_Write_UINT32(s, call->dwTimeOut);
4551 Stream_Write_UINT32(s, call->cReaders);
4552
4553 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4554 return SCARD_E_NO_MEMORY;
4555
4556 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4557 if (status != SCARD_S_SUCCESS)
4558 return status;
4559
4560 if (call->cReaders > 0)
4561 {
4562 status = smartcard_pack_reader_state_a(s, call->rgReaderStates, call->cReaders, &index);
4563 if (status != SCARD_S_SUCCESS)
4564 return status;
4565 }
4566
4567 return SCARD_S_SUCCESS;
4568}
4569
4570LONG smartcard_pack_get_status_change_w_call(wStream* s, const GetStatusChangeW_Call* call)
4571{
4572 WINPR_ASSERT(call);
4573 wLog* log = scard_log();
4574 UINT32 index = 0;
4575
4576 smartcard_trace_get_status_change_w_call(log, call);
4577
4578 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4579 if (status != SCARD_S_SUCCESS)
4580 return status;
4581
4582 if (!Stream_EnsureRemainingCapacity(s, 8))
4583 return SCARD_E_NO_MEMORY;
4584
4585 Stream_Write_UINT32(s, call->dwTimeOut);
4586 Stream_Write_UINT32(s, call->cReaders);
4587
4588 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4589 return SCARD_E_NO_MEMORY;
4590
4591 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4592 if (status != SCARD_S_SUCCESS)
4593 return status;
4594
4595 if (call->cReaders > 0)
4596 {
4597 status = smartcard_pack_reader_state_w(s, call->rgReaderStates, call->cReaders, &index);
4598 if (status != SCARD_S_SUCCESS)
4599 return status;
4600 }
4601
4602 return SCARD_S_SUCCESS;
4603}
4604
4605LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call)
4606{
4607 WINPR_ASSERT(call);
4608 wLog* log = scard_log();
4609 UINT32 index = 0;
4610
4611 smartcard_trace_connect_a_call(log, call);
4612
4613 const UINT32 readerLen = call->szReader ? (UINT32)(strlen(call->szReader) + 1) : 0;
4614 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4615 return SCARD_E_NO_MEMORY;
4616
4617 LONG status =
4618 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4619 if (status != SCARD_S_SUCCESS)
4620 return status;
4621
4622 if (!Stream_EnsureRemainingCapacity(s, 8))
4623 return SCARD_E_NO_MEMORY;
4624
4625 Stream_Write_UINT32(s, call->Common.dwShareMode);
4626 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4627
4628 if (call->szReader)
4629 {
4630 status = smartcard_ndr_write_a(s, call->szReader, readerLen, NDR_PTR_FULL);
4631 if (status != SCARD_S_SUCCESS)
4632 return status;
4633 }
4634
4635 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4636}
4637
4638LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call)
4639{
4640 WINPR_ASSERT(call);
4641 wLog* log = scard_log();
4642 UINT32 index = 0;
4643
4644 smartcard_trace_connect_w_call(log, call);
4645
4646 const UINT32 readerLen = call->szReader ? (UINT32)(_wcslen(call->szReader) + 1) : 0;
4647 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4648 return SCARD_E_NO_MEMORY;
4649
4650 LONG status =
4651 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4652 if (status != SCARD_S_SUCCESS)
4653 return status;
4654
4655 if (!Stream_EnsureRemainingCapacity(s, 8))
4656 return SCARD_E_NO_MEMORY;
4657
4658 Stream_Write_UINT32(s, call->Common.dwShareMode);
4659 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4660
4661 if (call->szReader)
4662 {
4663 status = smartcard_ndr_write_w(s, call->szReader, readerLen, NDR_PTR_FULL);
4664 if (status != SCARD_S_SUCCESS)
4665 return status;
4666 }
4667
4668 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4669}
4670
4671LONG smartcard_pack_control_call(wStream* s, const Control_Call* call)
4672{
4673 WINPR_ASSERT(call);
4674 wLog* log = scard_log();
4675 UINT32 index = 0;
4676
4677 smartcard_trace_control_call(log, call);
4678
4679 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4680 if (status != SCARD_S_SUCCESS)
4681 return status;
4682
4683 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4684 if (status != SCARD_S_SUCCESS)
4685 return status;
4686
4687 if (!Stream_EnsureRemainingCapacity(s, 8))
4688 return SCARD_E_NO_MEMORY;
4689
4690 Stream_Write_UINT32(s, call->dwControlCode);
4691 Stream_Write_UINT32(s, call->cbInBufferSize);
4692 if (!smartcard_ndr_pointer_write(s, &index, call->cbInBufferSize))
4693 return SCARD_E_NO_MEMORY;
4694
4695 Stream_Write_INT32(s, call->fpvOutBufferIsNULL);
4696 Stream_Write_UINT32(s, call->cbOutBufferSize);
4697
4698 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4699 if (status != SCARD_S_SUCCESS)
4700 return status;
4701
4702 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4703 if (status != SCARD_S_SUCCESS)
4704 return status;
4705
4706 if (call->cbInBufferSize)
4707 {
4708 status = smartcard_ndr_write(s, call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
4709 if (status != SCARD_S_SUCCESS)
4710 return status;
4711 }
4712
4713 return status;
4714}
4715
4716LONG smartcard_pack_hcard_and_disposition_call(wStream* s, const HCardAndDisposition_Call* call,
4717 const char* name)
4718{
4719 WINPR_ASSERT(call);
4720 wLog* log = scard_log();
4721 UINT32 index = 0;
4722
4723 smartcard_trace_hcard_and_disposition_call(log, call, name);
4724
4725 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4726 if (status != SCARD_S_SUCCESS)
4727 return status;
4728
4729 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4730 if (status != SCARD_S_SUCCESS)
4731 return status;
4732
4733 if (!Stream_EnsureRemainingCapacity(s, 4))
4734 return SCARD_E_NO_MEMORY;
4735
4736 Stream_Write_UINT32(s, call->dwDisposition);
4737
4738 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4739 if (status != SCARD_S_SUCCESS)
4740 return status;
4741
4742 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4743}
4744
4745LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
4746{
4747 WINPR_ASSERT(call);
4748 wLog* log = scard_log();
4749 UINT32 index = 0;
4750
4751 smartcard_trace_transmit_call(log, call);
4752
4753 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4754 if (status != SCARD_S_SUCCESS)
4755 return status;
4756
4757 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4758 if (status != SCARD_S_SUCCESS)
4759 return status;
4760
4761 UINT32 cbExtraBytes = 0;
4762 const BYTE* pbExtraBytes = nullptr;
4763 if (call->pioSendPci)
4764 {
4765 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4766 if (cbExtraBytes > 0)
4767 pbExtraBytes = &((const BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
4768 }
4769
4770 if (!Stream_EnsureRemainingCapacity(s, 32))
4771 return SCARD_E_NO_MEMORY;
4772
4773 Stream_Write_UINT32(s, call->pioSendPci ? call->pioSendPci->dwProtocol : 0);
4774 Stream_Write_UINT32(s, cbExtraBytes);
4775 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
4776 return SCARD_E_NO_MEMORY;
4777
4778 Stream_Write_UINT32(s, call->cbSendLength);
4779 if (!smartcard_ndr_pointer_write(s, &index, call->cbSendLength))
4780 return SCARD_E_NO_MEMORY;
4781
4782 const UINT32 recvPciLen = call->pioRecvPci ? (UINT32)call->pioRecvPci->cbPciLength : 0;
4783 if (!smartcard_ndr_pointer_write(s, &index, recvPciLen))
4784 return SCARD_E_NO_MEMORY;
4785
4786 Stream_Write_INT32(s, call->fpbRecvBufferIsNULL);
4787 Stream_Write_UINT32(s, call->cbRecvLength);
4788
4789 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4790 if (status != SCARD_S_SUCCESS)
4791 return status;
4792
4793 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4794 if (status != SCARD_S_SUCCESS)
4795 return status;
4796
4797 if (cbExtraBytes > 0)
4798 {
4799 status = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
4800 if (status != SCARD_S_SUCCESS)
4801 return status;
4802 }
4803
4804 if (call->cbSendLength > 0)
4805 {
4806 status = smartcard_ndr_write(s, call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
4807 if (status != SCARD_S_SUCCESS)
4808 return status;
4809 }
4810
4811 if (call->pioRecvPci && recvPciLen > 0)
4812 {
4813 UINT32 cbRecvExtra = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4814 const BYTE* pbRecvExtra = &((const BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
4815
4816 if (!Stream_EnsureRemainingCapacity(s, 12))
4817 return SCARD_E_NO_MEMORY;
4818
4819 Stream_Write_UINT32(s, call->pioRecvPci->dwProtocol);
4820 Stream_Write_UINT32(s, cbRecvExtra);
4821 if (!smartcard_ndr_pointer_write(s, &index, cbRecvExtra))
4822 return SCARD_E_NO_MEMORY;
4823
4824 if (cbRecvExtra > 0)
4825 {
4826 status = smartcard_ndr_write(s, pbRecvExtra, cbRecvExtra, 1, NDR_PTR_SIMPLE);
4827 if (status != SCARD_S_SUCCESS)
4828 return status;
4829 }
4830 }
4831
4832 return SCARD_S_SUCCESS;
4833}
4834
4835LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call)
4836{
4837 WINPR_ASSERT(call);
4838 wLog* log = scard_log();
4839 UINT32 index = 0;
4840
4841 smartcard_trace_get_attrib_call(log, call);
4842
4843 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4844 if (status != SCARD_S_SUCCESS)
4845 return status;
4846
4847 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4848 if (status != SCARD_S_SUCCESS)
4849 return status;
4850
4851 if (!Stream_EnsureRemainingCapacity(s, 12))
4852 return STATUS_NO_MEMORY;
4853
4854 Stream_Write_UINT32(s, call->dwAttrId);
4855 Stream_Write_INT32(s, call->fpbAttrIsNULL);
4856 Stream_Write_UINT32(s, call->cbAttrLen);
4857
4858 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4859 if (status != SCARD_S_SUCCESS)
4860 return status;
4861
4862 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4863}
4864
4865LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret, BOOL unicode)
4866{
4867 WINPR_ASSERT(ret);
4868 wLog* log = scard_log();
4869 UINT32 index = 0;
4870 UINT32 mszNdrPtr = 0;
4871
4872 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4873 return STATUS_BUFFER_TOO_SMALL;
4874
4875 const UINT32 cBytes = Stream_Get_UINT32(s);
4876
4877 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4878 return ERROR_INVALID_DATA;
4879
4880 if (mszNdrPtr)
4881 {
4882 LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
4883 if (status != SCARD_S_SUCCESS)
4884 return status;
4885 ret->cBytes = cBytes;
4886 }
4887
4888 smartcard_trace_list_readers_return(log, ret, unicode);
4889 return SCARD_S_SUCCESS;
4890}
4891
4892LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Return* ret,
4893 BOOL unicode)
4894{
4895 WINPR_ASSERT(ret);
4896 wLog* log = scard_log();
4897 UINT32 index = 0;
4898 UINT32 ndrPtr = 0;
4899
4900 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4901 return STATUS_BUFFER_TOO_SMALL;
4902
4903 Stream_Read_UINT32(s, ret->cReaders);
4904
4905 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
4906 return ERROR_INVALID_DATA;
4907
4908 if (ndrPtr && ret->cReaders > 0)
4909 {
4910 LONG status =
4911 smartcard_ndr_read_state(log, s, &ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE);
4912 if (status != SCARD_S_SUCCESS)
4913 return status;
4914 }
4915 else
4916 ret->rgReaderStates = nullptr;
4917
4918 smartcard_trace_get_status_change_return(log, ret, unicode);
4919 return SCARD_S_SUCCESS;
4920}
4921
4922LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret)
4923{
4924 WINPR_ASSERT(ret);
4925 wLog* log = scard_log();
4926 UINT32 index = 0;
4927 UINT32 pbContextNdrPtr = 0;
4928
4929 LONG status =
4930 smartcard_unpack_redir_scard_context(log, s, &ret->hContext, &index, &pbContextNdrPtr);
4931 if (status != SCARD_S_SUCCESS)
4932 return status;
4933
4934 status = smartcard_unpack_redir_scard_handle(log, s, &ret->hCard, &index);
4935 if (status != SCARD_S_SUCCESS)
4936 return status;
4937
4938 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4939 return STATUS_BUFFER_TOO_SMALL;
4940
4941 Stream_Read_UINT32(s, ret->dwActiveProtocol);
4942
4943 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &ret->hContext);
4944 if (status != SCARD_S_SUCCESS)
4945 return status;
4946
4947 status = smartcard_unpack_redir_scard_handle_ref(log, s, &ret->hCard);
4948 if (status != SCARD_S_SUCCESS)
4949 return status;
4950
4951 smartcard_trace_connect_return(log, ret);
4952 return SCARD_S_SUCCESS;
4953}
4954
4955LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret)
4956{
4957 WINPR_ASSERT(ret);
4958 wLog* log = scard_log();
4959 UINT32 index = 0;
4960 UINT32 pvOutBufferNdrPtr = 0;
4961
4962 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4963 return STATUS_BUFFER_TOO_SMALL;
4964
4965 const UINT32 cbOutBufferSize = Stream_Get_UINT32(s);
4966
4967 if (!smartcard_ndr_pointer_read(log, s, &index, &pvOutBufferNdrPtr))
4968 return ERROR_INVALID_DATA;
4969
4970 if (pvOutBufferNdrPtr && (cbOutBufferSize > 0))
4971 {
4972 LONG status =
4973 smartcard_ndr_read(log, s, &ret->pvOutBuffer, cbOutBufferSize, 1, NDR_PTR_SIMPLE);
4974 if (status != SCARD_S_SUCCESS)
4975 return status;
4976 ret->cbOutBufferSize = cbOutBufferSize;
4977 }
4978 smartcard_trace_control_return(log, ret);
4979 return SCARD_S_SUCCESS;
4980}
4981
4982LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret)
4983{
4984 WINPR_ASSERT(ret);
4985 wLog* log = scard_log();
4986 UINT32 index = 0;
4987 UINT32 recvPciNdrPtr = 0;
4988 UINT32 recvBufferNdrPtr = 0;
4989
4990 if (!smartcard_ndr_pointer_read(log, s, &index, &recvPciNdrPtr))
4991 return ERROR_INVALID_DATA;
4992
4993 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4994 return STATUS_BUFFER_TOO_SMALL;
4995
4996 const UINT32 cbRecvLength = Stream_Get_UINT32(s);
4997
4998 if (!smartcard_ndr_pointer_read(log, s, &index, &recvBufferNdrPtr))
4999 return ERROR_INVALID_DATA;
5000
5001 if (recvPciNdrPtr)
5002 {
5003 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
5004 return STATUS_BUFFER_TOO_SMALL;
5005
5006 UINT32 dwProtocol = 0;
5007 UINT32 cbExtraBytes = 0;
5008 Stream_Read_UINT32(s, dwProtocol);
5009 Stream_Read_UINT32(s, cbExtraBytes);
5010
5011 UINT32 pbExtraBytesNdrPtr = 0;
5012 if (!smartcard_ndr_pointer_read(log, s, &index, &pbExtraBytesNdrPtr))
5013 return ERROR_INVALID_DATA;
5014
5015 if (pbExtraBytesNdrPtr)
5016 {
5017 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5018 return STATUS_BUFFER_TOO_SMALL;
5019
5020 UINT32 length = 0;
5021 Stream_Read_UINT32(s, length);
5022 if (length != cbExtraBytes)
5023 {
5024 WLog_Print(log, WLOG_WARN,
5025 "Transmit_Return unexpected length: Actual: %" PRIu32
5026 ", Expected: %" PRIu32 " (pioRecvPci.cbExtraBytes)",
5027 length, cbExtraBytes);
5028 return STATUS_INVALID_PARAMETER;
5029 }
5030
5031 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, cbExtraBytes))
5032 return STATUS_BUFFER_TOO_SMALL;
5033
5034 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
5035 if (!ret->pioRecvPci)
5036 return SCARD_E_NO_MEMORY;
5037
5038 ret->pioRecvPci->dwProtocol = dwProtocol;
5039 ret->pioRecvPci->cbPciLength = (DWORD)(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
5040
5041 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
5042 Stream_Read(s, pbExtraBytes, length);
5043 if (smartcard_unpack_read_size_align(s, cbExtraBytes, 4) < 0)
5044 return STATUS_INVALID_PARAMETER;
5045 }
5046 else
5047 {
5048 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST));
5049 if (!ret->pioRecvPci)
5050 return SCARD_E_NO_MEMORY;
5051
5052 ret->pioRecvPci->dwProtocol = dwProtocol;
5053 ret->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
5054 }
5055 }
5056
5057 if (recvBufferNdrPtr && (cbRecvLength > 0))
5058 {
5059 LONG status =
5060 smartcard_ndr_read(log, s, &ret->pbRecvBuffer, cbRecvLength, 1, NDR_PTR_SIMPLE);
5061 if (status != SCARD_S_SUCCESS)
5062 return status;
5063 ret->cbRecvLength = cbRecvLength;
5064 }
5065
5066 smartcard_trace_transmit_return(log, ret);
5067 return SCARD_S_SUCCESS;
5068}
5069
5070LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret)
5071{
5072 WINPR_ASSERT(ret);
5073 wLog* log = scard_log();
5074 UINT32 index = 0;
5075 UINT32 pbAttrPtr = 0;
5076
5077 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5078 return STATUS_BUFFER_TOO_SMALL;
5079
5080 const UINT32 cbAttrLen = Stream_Get_UINT32(s);
5081
5082 if (!smartcard_ndr_pointer_read(log, s, &index, &pbAttrPtr))
5083 return ERROR_INVALID_DATA;
5084
5085 LONG status = smartcard_ndr_read(log, s, &ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
5086 if (status != SCARD_S_SUCCESS)
5087 return status;
5088 ret->cbAttrLen = cbAttrLen;
5089
5090 smartcard_trace_get_attrib_return(log, ret, 0);
5091 return SCARD_S_SUCCESS;
5092}
5093
5094BOOL smartcard_reader_state_return_is_valid_ex(size_t pos, const ReaderState_Return* val,
5095 const char* file, size_t line, const char* fkt)
5096{
5097 if (!val)
5098 {
5099 WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt, "[%" PRIuz "] val = nullptr",
5100 pos);
5101 return FALSE;
5102 }
5103 if (val->cbAtr > sizeof(val->rgbAtr))
5104 {
5105 WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt,
5106 "[%" PRIuz "] val->cbAtr=%" PRIu32 ", max=%" PRIuz, pos, val->cbAtr,
5107 sizeof(val->rgbAtr));
5108 return FALSE;
5109 }
5110
5111 return TRUE;
5112}
Definition wtypes.h:263