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 + 4))
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 }
2725
2726 *ppcReaders = rgReaderStates;
2727 free(states);
2728 return SCARD_S_SUCCESS;
2729fail:
2730 if (rgReaderStates)
2731 {
2732 for (UINT32 index = 0; index < cReaders; index++)
2733 {
2734 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2735 free(readerState->szReader);
2736 }
2737 }
2738 free(rgReaderStates);
2739 free(states);
2740 return status;
2741}
2742
2743WINPR_ATTR_NODISCARD static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s,
2744 LPSCARD_READERSTATEW* ppcReaders,
2745 UINT32 cReaders, UINT32* ptrIndex)
2746{
2747 LONG status = SCARD_E_NO_MEMORY;
2748
2749 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2750
2751 if (cReaders > UINT8_MAX)
2752 {
2753 WLog_Print(log, WLOG_ERROR,
2754 "Too many readers(%" PRIu32 "), rejecting request. Limited to <= %d", cReaders,
2755 UINT8_MAX);
2756 return SCARD_E_WRITE_TOO_MANY;
2757 }
2758
2759 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2760 return status;
2761
2762 const UINT32 len = Stream_Get_UINT32(s);
2763 if (len != cReaders)
2764 {
2765 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2766 return status;
2767 }
2768
2769 LPSCARD_READERSTATEW rgReaderStates =
2770 (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2771 BOOL* states = calloc(cReaders, sizeof(BOOL));
2772
2773 if (!rgReaderStates || !states)
2774 goto fail;
2775
2776 status = ERROR_INVALID_DATA;
2777 for (UINT32 index = 0; index < cReaders; index++)
2778 {
2779 UINT32 ptr = UINT32_MAX;
2780 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2781
2782 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2783 goto fail;
2784
2785 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2786 {
2787 if (ptr != 0)
2788 goto fail;
2789 }
2790 /* Ignore nullptr length strings */
2791 states[index] = ptr != 0;
2792 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2793 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2794 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2795 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2796 {
2797 WLog_Print(log, WLOG_ERROR,
2798 "SCARD_READERSTATEW[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2799 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2800 goto fail;
2801 }
2802 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2803 }
2804
2805 for (UINT32 index = 0; index < cReaders; index++)
2806 {
2807 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2808
2809 /* Skip nullptr pointers */
2810 if (!states[index])
2811 continue;
2812
2813 status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2814 if (status != SCARD_S_SUCCESS)
2815 goto fail;
2816 }
2817
2818 *ppcReaders = rgReaderStates;
2819 free(states);
2820 return SCARD_S_SUCCESS;
2821fail:
2822 if (rgReaderStates)
2823 {
2824 for (UINT32 index = 0; index < cReaders; index++)
2825 {
2826 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2827 free(readerState->szReader);
2828 }
2829 }
2830 free(rgReaderStates);
2831 free(states);
2832 return status;
2833}
2834
2835/******************************************************************************/
2836/************************************* End Trace Functions ********************/
2837/******************************************************************************/
2838
2839LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2840{
2841 UINT32 ndrPtr = 0;
2842 UINT32 index = 0;
2843 UINT32 pbContextNdrPtr = 0;
2844
2845 WINPR_ASSERT(call);
2846 wLog* log = scard_log();
2847
2848 call->rgReaderStates = nullptr;
2849
2850 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2851 &pbContextNdrPtr);
2852 if (status != SCARD_S_SUCCESS)
2853 return status;
2854
2855 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2856 return STATUS_BUFFER_TOO_SMALL;
2857
2858 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2859 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2860 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2861 return ERROR_INVALID_DATA;
2862
2863 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2864 &(call->handles.hContext));
2865 if (status != SCARD_S_SUCCESS)
2866 return status;
2867
2868 if (ndrPtr)
2869 {
2870 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
2871 if (status != SCARD_S_SUCCESS)
2872 return status;
2873 call->cReaders = cReaders;
2874 }
2875 else
2876 {
2877 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2878 return SCARD_E_UNEXPECTED;
2879 }
2880
2881 smartcard_trace_get_status_change_a_call(log, call);
2882 return SCARD_S_SUCCESS;
2883}
2884
2885LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2886{
2887 UINT32 ndrPtr = 0;
2888 UINT32 index = 0;
2889 UINT32 pbContextNdrPtr = 0;
2890
2891 WINPR_ASSERT(call);
2892 wLog* log = scard_log();
2893 call->rgReaderStates = nullptr;
2894
2895 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2896 &pbContextNdrPtr);
2897 if (status != SCARD_S_SUCCESS)
2898 return status;
2899
2900 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2901 return STATUS_BUFFER_TOO_SMALL;
2902
2903 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2904 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2905 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2906 return ERROR_INVALID_DATA;
2907
2908 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2909 &(call->handles.hContext));
2910 if (status != SCARD_S_SUCCESS)
2911 return status;
2912
2913 if (ndrPtr)
2914 {
2915 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
2916 if (status != SCARD_S_SUCCESS)
2917 return status;
2918 call->cReaders = cReaders;
2919 }
2920 else
2921 {
2922 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2923 return SCARD_E_UNEXPECTED;
2924 }
2925
2926 smartcard_trace_get_status_change_w_call(log, call);
2927 return SCARD_S_SUCCESS;
2928}
2929
2930LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2931 BOOL unicode)
2932{
2933 WINPR_ASSERT(ret);
2934 wLog* log = scard_log();
2935
2936 LONG status = 0;
2937 UINT32 cReaders = ret->cReaders;
2938 UINT32 index = 0;
2939
2940 smartcard_trace_get_status_change_return(log, ret, unicode);
2941 if ((ret->ReturnCode != SCARD_S_SUCCESS) && (ret->ReturnCode != SCARD_E_TIMEOUT))
2942 cReaders = 0;
2943 if (cReaders == SCARD_AUTOALLOCATE)
2944 cReaders = 0;
2945
2946 if (!Stream_EnsureRemainingCapacity(s, 4))
2947 return SCARD_E_NO_MEMORY;
2948
2949 Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2950 if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2951 return SCARD_E_NO_MEMORY;
2952 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2953 if (status != SCARD_S_SUCCESS)
2954 return status;
2955 return ret->ReturnCode;
2956}
2957
2958LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2959{
2960 UINT32 index = 0;
2961 UINT32 pbContextNdrPtr = 0;
2962
2963 wLog* log = scard_log();
2964
2965 WINPR_ASSERT(call);
2966 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2967 &pbContextNdrPtr);
2968 if (status != SCARD_S_SUCCESS)
2969 return status;
2970
2971 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2972 if (status != SCARD_S_SUCCESS)
2973 return status;
2974
2975 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2976 return STATUS_BUFFER_TOO_SMALL;
2977
2978 Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2979 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2980
2981 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2982 &(call->handles.hContext));
2983 if (status != SCARD_S_SUCCESS)
2984 return status;
2985
2986 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2987 if (status != SCARD_S_SUCCESS)
2988 return status;
2989
2990 return status;
2991}
2992
2993LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2994{
2995 WINPR_ASSERT(ret);
2996 wLog* log = scard_log();
2997 LONG status = 0;
2998 UINT32 cbAtrLen = ret->cbAtrLen;
2999 UINT32 index = 0;
3000
3001 smartcard_trace_state_return(log, ret);
3002 if (ret->ReturnCode != SCARD_S_SUCCESS)
3003 cbAtrLen = 0;
3004 if (cbAtrLen == SCARD_AUTOALLOCATE)
3005 cbAtrLen = 0;
3006
3007 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
3008 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
3009 Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
3010 if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
3011 return SCARD_E_NO_MEMORY;
3012 status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
3013 if (status != SCARD_S_SUCCESS)
3014 return status;
3015 return ret->ReturnCode;
3016}
3017
3018LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
3019{
3020 UINT32 index = 0;
3021 UINT32 pbContextNdrPtr = 0;
3022
3023 WINPR_ASSERT(call);
3024 wLog* log = scard_log();
3025
3026 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3027 &pbContextNdrPtr);
3028 if (status != SCARD_S_SUCCESS)
3029 return status;
3030
3031 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3032 if (status != SCARD_S_SUCCESS)
3033 return status;
3034
3035 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3036 return STATUS_BUFFER_TOO_SMALL;
3037
3038 Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
3039 Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
3040 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
3041
3042 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3043 &(call->handles.hContext));
3044 if (status != SCARD_S_SUCCESS)
3045 return status;
3046
3047 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3048 if (status != SCARD_S_SUCCESS)
3049 return status;
3050
3051 smartcard_trace_status_call(log, call, unicode);
3052 return status;
3053}
3054
3055LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode)
3056{
3057 WINPR_ASSERT(call);
3058 wLog* log = scard_log();
3059 UINT32 index = 0;
3060
3061 smartcard_trace_status_call(log, call, unicode);
3062
3063 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3064 if (status != SCARD_S_SUCCESS)
3065 return status;
3066
3067 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3068 if (status != SCARD_S_SUCCESS)
3069 return status;
3070
3071 if (!Stream_EnsureRemainingCapacity(s, 12))
3072 return SCARD_E_NO_MEMORY;
3073
3074 Stream_Write_INT32(s, call->fmszReaderNamesIsNULL);
3075 Stream_Write_UINT32(s, call->cchReaderLen);
3076 Stream_Write_UINT32(s, call->cbAtrLen);
3077
3078 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3079 if (status != SCARD_S_SUCCESS)
3080 return status;
3081
3082 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3083}
3084
3085LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
3086{
3087 WINPR_ASSERT(ret);
3088 wLog* log = scard_log();
3089
3090 LONG status = 0;
3091 UINT32 index = 0;
3092 UINT32 cBytes = ret->cBytes;
3093
3094 smartcard_trace_status_return(log, ret, unicode);
3095 if (ret->ReturnCode != SCARD_S_SUCCESS)
3096 cBytes = 0;
3097 if (cBytes == SCARD_AUTOALLOCATE)
3098 cBytes = 0;
3099
3100 if (!Stream_EnsureRemainingCapacity(s, 4))
3101 return SCARD_F_INTERNAL_ERROR;
3102
3103 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
3104 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
3105 return SCARD_E_NO_MEMORY;
3106
3107 if (!Stream_EnsureRemainingCapacity(s, 44))
3108 return SCARD_F_INTERNAL_ERROR;
3109
3110 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
3111 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
3112 Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
3113 Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
3114 status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3115 if (status != SCARD_S_SUCCESS)
3116 return status;
3117 return ret->ReturnCode;
3118}
3119
3120LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode)
3121{
3122 WINPR_ASSERT(ret);
3123 wLog* log = scard_log();
3124 UINT32 index = 0;
3125 UINT32 mszNdrPtr = 0;
3126
3127 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3128 return STATUS_BUFFER_TOO_SMALL;
3129
3130 const UINT32 cBytes = Stream_Get_UINT32(s);
3131
3132 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3133 return ERROR_INVALID_DATA;
3134
3135 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 44))
3136 return STATUS_BUFFER_TOO_SMALL;
3137
3138 Stream_Read_UINT32(s, ret->dwState);
3139 Stream_Read_UINT32(s, ret->dwProtocol);
3140 Stream_Read(s, ret->pbAtr, sizeof(ret->pbAtr));
3141 Stream_Read_UINT32(s, ret->cbAtrLen);
3142
3143 if (ret->cbAtrLen > ARRAYSIZE(ret->pbAtr))
3144 {
3145 WLog_Print(log, WLOG_ERROR, "Status_Return::cbAtrLen %" PRIu32 " exceeds %" PRIuz,
3146 ret->cbAtrLen, ARRAYSIZE(ret->pbAtr));
3147 return SCARD_E_INVALID_ATR;
3148 }
3149
3150 if (mszNdrPtr)
3151 {
3152 LONG status = smartcard_ndr_read(log, s, &ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3153 if (status != SCARD_S_SUCCESS)
3154 return status;
3155 ret->cBytes = cBytes;
3156 }
3157
3158 smartcard_trace_status_return(log, ret, unicode);
3159 return SCARD_S_SUCCESS;
3160}
3161
3162LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
3163{
3164 WINPR_ASSERT(call);
3165 wLog* log = scard_log();
3166 UINT32 index = 0;
3167 UINT32 pbContextNdrPtr = 0;
3168
3169 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3170 &pbContextNdrPtr);
3171 if (status != SCARD_S_SUCCESS)
3172 return status;
3173
3174 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3175 if (status != SCARD_S_SUCCESS)
3176 return status;
3177
3178 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3179 return STATUS_BUFFER_TOO_SMALL;
3180
3181 Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
3182 Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
3183 Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
3184
3185 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3186 &(call->handles.hContext));
3187 if (status != SCARD_S_SUCCESS)
3188 return status;
3189
3190 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3191 if (status != SCARD_S_SUCCESS)
3192 return status;
3193
3194 smartcard_trace_get_attrib_call(log, call);
3195 return status;
3196}
3197
3198LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
3199 DWORD cbAttrCallLen)
3200{
3201 WINPR_ASSERT(ret);
3202 wLog* log = scard_log();
3203 LONG status = 0;
3204 UINT32 cbAttrLen = 0;
3205 UINT32 index = 0;
3206 smartcard_trace_get_attrib_return(log, ret, dwAttrId);
3207
3208 if (!Stream_EnsureRemainingCapacity(s, 4))
3209 return SCARD_F_INTERNAL_ERROR;
3210
3211 cbAttrLen = ret->cbAttrLen;
3212 if (ret->ReturnCode != SCARD_S_SUCCESS)
3213 cbAttrLen = 0;
3214 if (cbAttrLen == SCARD_AUTOALLOCATE)
3215 cbAttrLen = 0;
3216
3217 if (ret->pbAttr)
3218 {
3219 if (cbAttrCallLen < cbAttrLen)
3220 cbAttrLen = cbAttrCallLen;
3221 }
3222 Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
3223 if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
3224 return SCARD_E_NO_MEMORY;
3225
3226 status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
3227 if (status != SCARD_S_SUCCESS)
3228 return status;
3229 return ret->ReturnCode;
3230}
3231
3232LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
3233{
3234 WINPR_ASSERT(call);
3235 wLog* log = scard_log();
3236
3237 UINT32 index = 0;
3238 UINT32 pvInBufferNdrPtr = 0;
3239 UINT32 pbContextNdrPtr = 0;
3240
3241 call->pvInBuffer = nullptr;
3242
3243 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3244 &pbContextNdrPtr);
3245 if (status != SCARD_S_SUCCESS)
3246 return status;
3247
3248 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3249 if (status != SCARD_S_SUCCESS)
3250 return status;
3251
3252 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
3253 return STATUS_BUFFER_TOO_SMALL;
3254
3255 Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
3256 const UINT32 cbInBufferSize = Stream_Get_UINT32(s); /* cbInBufferSize (4 bytes) */
3257 if (!smartcard_ndr_pointer_read(log, s, &index,
3258 &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
3259 return ERROR_INVALID_DATA;
3260 Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
3261 Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
3262
3263 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3264 &(call->handles.hContext));
3265 if (status != SCARD_S_SUCCESS)
3266 return status;
3267
3268 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3269 if (status != SCARD_S_SUCCESS)
3270 return status;
3271
3272 if (pvInBufferNdrPtr)
3273 {
3274 status = smartcard_ndr_read(log, s, &call->pvInBuffer, cbInBufferSize, 1, NDR_PTR_SIMPLE);
3275 if (status != SCARD_S_SUCCESS)
3276 return status;
3277 call->cbInBufferSize = cbInBufferSize;
3278 }
3279
3280 smartcard_trace_control_call(log, call);
3281 return SCARD_S_SUCCESS;
3282}
3283
3284LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
3285{
3286 WINPR_ASSERT(ret);
3287 wLog* log = scard_log();
3288
3289 LONG status = 0;
3290 UINT32 cbDataLen = ret->cbOutBufferSize;
3291 UINT32 index = 0;
3292
3293 smartcard_trace_control_return(log, ret);
3294 if (ret->ReturnCode != SCARD_S_SUCCESS)
3295 cbDataLen = 0;
3296 if (cbDataLen == SCARD_AUTOALLOCATE)
3297 cbDataLen = 0;
3298
3299 if (!Stream_EnsureRemainingCapacity(s, 4))
3300 return SCARD_F_INTERNAL_ERROR;
3301
3302 Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
3303 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3304 return SCARD_E_NO_MEMORY;
3305
3306 status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
3307 if (status != SCARD_S_SUCCESS)
3308 return status;
3309 return ret->ReturnCode;
3310}
3311
3312LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
3313{
3314 UINT32 length = 0;
3315 BYTE* pbExtraBytes = nullptr;
3316 UINT32 pbExtraBytesNdrPtr = 0;
3317 UINT32 pbSendBufferNdrPtr = 0;
3318 UINT32 pioRecvPciNdrPtr = 0;
3319 SCardIO_Request ioSendPci;
3320 SCardIO_Request ioRecvPci;
3321 UINT32 index = 0;
3322 UINT32 pbContextNdrPtr = 0;
3323
3324 WINPR_ASSERT(call);
3325 wLog* log = scard_log();
3326
3327 call->pioSendPci = nullptr;
3328 call->pioRecvPci = nullptr;
3329 call->pbSendBuffer = nullptr;
3330
3331 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3332 &pbContextNdrPtr);
3333 if (status != SCARD_S_SUCCESS)
3334 return status;
3335
3336 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3337 if (status != SCARD_S_SUCCESS)
3338 return status;
3339
3340 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
3341 return STATUS_BUFFER_TOO_SMALL;
3342
3343 Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
3344 Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3345 if (!smartcard_ndr_pointer_read(log, s, &index,
3346 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3347 return ERROR_INVALID_DATA;
3348
3349 const UINT32 cbSendLength = Stream_Get_UINT32(s); /* cbSendLength (4 bytes) */
3350 if (!smartcard_ndr_pointer_read(log, s, &index,
3351 &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3352 return ERROR_INVALID_DATA;
3353
3354 if (!smartcard_ndr_pointer_read(log, s, &index,
3355 &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3356 return ERROR_INVALID_DATA;
3357
3358 Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3359 Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
3360
3361 if (ioSendPci.cbExtraBytes > 1024)
3362 {
3363 WLog_Print(log, WLOG_WARN,
3364 "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3365 ioSendPci.cbExtraBytes);
3366 return STATUS_INVALID_PARAMETER;
3367 }
3368
3369 if (cbSendLength > 66560)
3370 {
3371 WLog_Print(log, WLOG_WARN,
3372 "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3373 ioSendPci.cbExtraBytes);
3374 return STATUS_INVALID_PARAMETER;
3375 }
3376
3377 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3378 &(call->handles.hContext));
3379 if (status != SCARD_S_SUCCESS)
3380 return status;
3381
3382 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3383 if (status != SCARD_S_SUCCESS)
3384 return status;
3385
3386 if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3387 {
3388 WLog_Print(
3389 log, WLOG_WARN,
3390 "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3391 return STATUS_INVALID_PARAMETER;
3392 }
3393
3394 if (pbExtraBytesNdrPtr)
3395 {
3396 // TODO: Use unified pointer reading
3397 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3398 return STATUS_BUFFER_TOO_SMALL;
3399
3400 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3401
3402 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3403 return STATUS_BUFFER_TOO_SMALL;
3404
3405 ioSendPci.pbExtraBytes = Stream_Pointer(s);
3406 call->pioSendPci =
3407 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3408
3409 if (!call->pioSendPci)
3410 {
3411 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3412 return STATUS_NO_MEMORY;
3413 }
3414
3415 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3416 call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3417 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3418 Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3419 if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3420 return STATUS_INVALID_PARAMETER;
3421 }
3422 else
3423 {
3424 call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3425
3426 if (!call->pioSendPci)
3427 {
3428 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3429 return STATUS_NO_MEMORY;
3430 }
3431
3432 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3433 call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3434 }
3435
3436 if (pbSendBufferNdrPtr)
3437 {
3438 status = smartcard_ndr_read(log, s, &call->pbSendBuffer, cbSendLength, 1, NDR_PTR_SIMPLE);
3439 if (status != SCARD_S_SUCCESS)
3440 return status;
3441 call->cbSendLength = cbSendLength;
3442 }
3443
3444 if (pioRecvPciNdrPtr)
3445 {
3446 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3447 return STATUS_BUFFER_TOO_SMALL;
3448
3449 Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
3450 Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3451 if (!smartcard_ndr_pointer_read(log, s, &index,
3452 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3453 return ERROR_INVALID_DATA;
3454
3455 if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3456 {
3457 WLog_Print(
3458 log, WLOG_WARN,
3459 "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3460 return STATUS_INVALID_PARAMETER;
3461 }
3462
3463 if (pbExtraBytesNdrPtr)
3464 {
3465 // TODO: Unify ndr pointer reading
3466 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3467 return STATUS_BUFFER_TOO_SMALL;
3468
3469 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3470
3471 if (ioRecvPci.cbExtraBytes > 1024)
3472 {
3473 WLog_Print(log, WLOG_WARN,
3474 "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3475 " (max: 1024)",
3476 ioRecvPci.cbExtraBytes);
3477 return STATUS_INVALID_PARAMETER;
3478 }
3479
3480 if (length != ioRecvPci.cbExtraBytes)
3481 {
3482 WLog_Print(log, WLOG_WARN,
3483 "Transmit_Call unexpected length: Actual: %" PRIu32
3484 ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3485 length, ioRecvPci.cbExtraBytes);
3486 return STATUS_INVALID_PARAMETER;
3487 }
3488
3489 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3490 return STATUS_BUFFER_TOO_SMALL;
3491
3492 ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3493 call->pioRecvPci =
3494 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3495
3496 if (!call->pioRecvPci)
3497 {
3498 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3499 return STATUS_NO_MEMORY;
3500 }
3501
3502 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3503 call->pioRecvPci->cbPciLength =
3504 (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3505 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3506 Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3507 if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3508 return STATUS_INVALID_PARAMETER;
3509 }
3510 else
3511 {
3512 call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3513
3514 if (!call->pioRecvPci)
3515 {
3516 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3517 return STATUS_NO_MEMORY;
3518 }
3519
3520 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3521 call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3522 }
3523 }
3524
3525 smartcard_trace_transmit_call(log, call);
3526 return SCARD_S_SUCCESS;
3527}
3528
3529LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3530{
3531 WINPR_ASSERT(ret);
3532 wLog* log = scard_log();
3533
3534 LONG status = 0;
3535 UINT32 index = 0;
3536 LONG error = 0;
3537 UINT32 cbRecvLength = ret->cbRecvLength;
3538 UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3539
3540 smartcard_trace_transmit_return(log, ret);
3541
3542 if (!ret->pbRecvBuffer)
3543 cbRecvLength = 0;
3544
3545 if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3546 return SCARD_E_NO_MEMORY;
3547 if (!Stream_EnsureRemainingCapacity(s, 4))
3548 return SCARD_E_NO_MEMORY;
3549 Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3550 if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3551 return SCARD_E_NO_MEMORY;
3552
3553 if (ret->pioRecvPci)
3554 {
3555 UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3556 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3557
3558 if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3559 {
3560 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3561 return SCARD_F_INTERNAL_ERROR;
3562 }
3563
3564 Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3565 Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
3566 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3567 return SCARD_E_NO_MEMORY;
3568 error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3569 if (error)
3570 return error;
3571 }
3572
3573 status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3574 if (status != SCARD_S_SUCCESS)
3575 return status;
3576 return ret->ReturnCode;
3577}
3578
3579LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3580{
3581 UINT32 rgReaderStatesNdrPtr = 0;
3582 UINT32 rgAtrMasksNdrPtr = 0;
3583 UINT32 index = 0;
3584 UINT32 pbContextNdrPtr = 0;
3585
3586 WINPR_ASSERT(call);
3587 wLog* log = scard_log();
3588
3589 call->rgReaderStates = nullptr;
3590
3591 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3592 &pbContextNdrPtr);
3593 if (status != SCARD_S_SUCCESS)
3594 return status;
3595
3596 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3597 return STATUS_BUFFER_TOO_SMALL;
3598
3599 Stream_Read_UINT32(s, call->cAtrs);
3600 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3601 return ERROR_INVALID_DATA;
3602 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3603 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3604 return ERROR_INVALID_DATA;
3605
3606 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3607 &(call->handles.hContext));
3608 if (status != SCARD_S_SUCCESS)
3609 return status;
3610
3611 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3612 {
3613 WLog_Print(log, WLOG_WARN,
3614 "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3615 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3616 rgAtrMasksNdrPtr, call->cAtrs);
3617 return STATUS_INVALID_PARAMETER;
3618 }
3619
3620 if (rgAtrMasksNdrPtr)
3621 {
3622 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3623 if (status != SCARD_S_SUCCESS)
3624 return status;
3625 }
3626
3627 if (rgReaderStatesNdrPtr)
3628 {
3629 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3630 if (status != SCARD_S_SUCCESS)
3631 return status;
3632 call->cReaders = cReaders;
3633 }
3634
3635 smartcard_trace_locate_cards_by_atr_a_call(log, call);
3636 return SCARD_S_SUCCESS;
3637}
3638
3639LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3640{
3641 UINT32 sz1NdrPtr = 0;
3642 UINT32 sz2NdrPtr = 0;
3643 UINT32 index = 0;
3644 UINT32 pbContextNdrPtr = 0;
3645
3646 WINPR_ASSERT(call);
3647 wLog* log = scard_log();
3648
3649 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3650 &pbContextNdrPtr);
3651 if (status != SCARD_S_SUCCESS)
3652 return status;
3653
3654 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3655 return ERROR_INVALID_DATA;
3656 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3657 return ERROR_INVALID_DATA;
3658
3659 status =
3660 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3661 if (status != SCARD_S_SUCCESS)
3662 return status;
3663
3664 if (sz1NdrPtr)
3665 {
3666 status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3667 if (status != SCARD_S_SUCCESS)
3668 return status;
3669 }
3670 if (sz2NdrPtr)
3671 {
3672 status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3673 if (status != SCARD_S_SUCCESS)
3674 return status;
3675 }
3676 smartcard_trace_context_and_two_strings_a_call(log, call);
3677 return SCARD_S_SUCCESS;
3678}
3679
3680LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3681{
3682 UINT32 sz1NdrPtr = 0;
3683 UINT32 sz2NdrPtr = 0;
3684 UINT32 index = 0;
3685 UINT32 pbContextNdrPtr = 0;
3686
3687 WINPR_ASSERT(call);
3688 wLog* log = scard_log();
3689
3690 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3691 &pbContextNdrPtr);
3692 if (status != SCARD_S_SUCCESS)
3693 return status;
3694
3695 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3696 return ERROR_INVALID_DATA;
3697 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3698 return ERROR_INVALID_DATA;
3699
3700 status =
3701 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3702 if (status != SCARD_S_SUCCESS)
3703 return status;
3704
3705 if (sz1NdrPtr)
3706 {
3707 status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3708 if (status != SCARD_S_SUCCESS)
3709 return status;
3710 }
3711 if (sz2NdrPtr)
3712 {
3713 status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3714 if (status != SCARD_S_SUCCESS)
3715 return status;
3716 }
3717 smartcard_trace_context_and_two_strings_w_call(log, call);
3718 return SCARD_S_SUCCESS;
3719}
3720
3721LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3722{
3723 UINT32 sz1NdrPtr = 0;
3724 UINT32 sz2NdrPtr = 0;
3725 UINT32 index = 0;
3726 UINT32 pbContextNdrPtr = 0;
3727
3728 WINPR_ASSERT(call);
3729 wLog* log = scard_log();
3730
3731 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3732 &pbContextNdrPtr);
3733 if (status != SCARD_S_SUCCESS)
3734 return status;
3735
3736 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3737 return STATUS_BUFFER_TOO_SMALL;
3738
3739 const UINT32 cBytes = Stream_Get_UINT32(s);
3740 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3741 return ERROR_INVALID_DATA;
3742
3743 const UINT32 cReaders = Stream_Get_UINT32(s);
3744 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3745 return ERROR_INVALID_DATA;
3746
3747 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3748 &(call->handles.hContext));
3749 if (status != SCARD_S_SUCCESS)
3750 return status;
3751
3752 if (sz1NdrPtr)
3753 {
3754 status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3755 if (status != SCARD_S_SUCCESS)
3756 return status;
3757 call->cBytes = cBytes;
3758 }
3759 if (sz2NdrPtr)
3760 {
3761 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3762 if (status != SCARD_S_SUCCESS)
3763 return status;
3764 call->cReaders = cReaders;
3765 }
3766 smartcard_trace_locate_cards_a_call(log, call);
3767 return SCARD_S_SUCCESS;
3768}
3769
3770LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3771{
3772 UINT32 sz1NdrPtr = 0;
3773 UINT32 sz2NdrPtr = 0;
3774 UINT32 index = 0;
3775 UINT32 pbContextNdrPtr = 0;
3776
3777 WINPR_ASSERT(call);
3778 wLog* log = scard_log();
3779
3780 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3781 &pbContextNdrPtr);
3782 if (status != SCARD_S_SUCCESS)
3783 return status;
3784
3785 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3786 return STATUS_BUFFER_TOO_SMALL;
3787
3788 const UINT32 cBytes = Stream_Get_UINT32(s);
3789 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3790 return ERROR_INVALID_DATA;
3791
3792 const UINT32 cReaders = Stream_Get_UINT32(s);
3793 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3794 return ERROR_INVALID_DATA;
3795
3796 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3797 &(call->handles.hContext));
3798 if (status != SCARD_S_SUCCESS)
3799 return status;
3800
3801 if (sz1NdrPtr)
3802 {
3803 status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3804 if (status != SCARD_S_SUCCESS)
3805 return status;
3806 call->cBytes = cBytes;
3807 }
3808 if (sz2NdrPtr)
3809 {
3810 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3811 if (status != SCARD_S_SUCCESS)
3812 return status;
3813 call->cReaders = cReaders;
3814 }
3815 smartcard_trace_locate_cards_w_call(log, call);
3816 return SCARD_S_SUCCESS;
3817}
3818
3819LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3820{
3821 UINT32 index = 0;
3822 UINT32 ndrPtr = 0;
3823 UINT32 pbContextNdrPtr = 0;
3824
3825 WINPR_ASSERT(call);
3826 wLog* log = scard_log();
3827
3828 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3829 &pbContextNdrPtr);
3830 if (status != SCARD_S_SUCCESS)
3831 return status;
3832 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3833 if (status != SCARD_S_SUCCESS)
3834 return status;
3835
3836 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3837 return STATUS_BUFFER_TOO_SMALL;
3838 Stream_Read_UINT32(s, call->dwAttrId);
3839 Stream_Read_UINT32(s, call->cbAttrLen);
3840
3841 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3842 return ERROR_INVALID_DATA;
3843
3844 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3845 &(call->handles.hContext));
3846 if (status != SCARD_S_SUCCESS)
3847 return status;
3848
3849 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3850 if (status != SCARD_S_SUCCESS)
3851 return status;
3852
3853 if (ndrPtr)
3854 {
3855 size_t len = 0;
3856 status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3857 if (status != SCARD_S_SUCCESS)
3858 return status;
3859 if (call->cbAttrLen > len)
3860 call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3861 }
3862 else
3863 call->cbAttrLen = 0;
3864 smartcard_trace_set_attrib_call(log, call);
3865 return SCARD_S_SUCCESS;
3866}
3867
3868LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call)
3869{
3870 WINPR_ASSERT(call);
3871 wLog* log = scard_log();
3872 UINT32 index = 0;
3873
3874 smartcard_trace_set_attrib_call(log, call);
3875
3876 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3877 if (status != SCARD_S_SUCCESS)
3878 return status;
3879
3880 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3881 if (status != SCARD_S_SUCCESS)
3882 return status;
3883
3884 if (!Stream_EnsureRemainingCapacity(s, 8))
3885 return SCARD_E_NO_MEMORY;
3886
3887 Stream_Write_UINT32(s, call->dwAttrId);
3888 Stream_Write_UINT32(s, call->cbAttrLen);
3889
3890 if (!smartcard_ndr_pointer_write(s, &index, call->cbAttrLen))
3891 return SCARD_E_NO_MEMORY;
3892
3893 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3894 if (status != SCARD_S_SUCCESS)
3895 return status;
3896
3897 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3898 if (status != SCARD_S_SUCCESS)
3899 return status;
3900
3901 status = smartcard_ndr_write(s, call->pbAttr, call->cbAttrLen, 1, NDR_PTR_SIMPLE);
3902 if (status != SCARD_S_SUCCESS)
3903 return status;
3904
3905 return SCARD_S_SUCCESS;
3906}
3907
3908LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3909{
3910 UINT32 rgReaderStatesNdrPtr = 0;
3911 UINT32 rgAtrMasksNdrPtr = 0;
3912 UINT32 index = 0;
3913 UINT32 pbContextNdrPtr = 0;
3914
3915 WINPR_ASSERT(call);
3916 wLog* log = scard_log();
3917
3918 call->rgReaderStates = nullptr;
3919
3920 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3921 &pbContextNdrPtr);
3922 if (status != SCARD_S_SUCCESS)
3923 return status;
3924
3925 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3926 return STATUS_BUFFER_TOO_SMALL;
3927
3928 Stream_Read_UINT32(s, call->cAtrs);
3929 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3930 return ERROR_INVALID_DATA;
3931
3932 const UINT32 cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3933 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3934 return ERROR_INVALID_DATA;
3935
3936 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3937 &(call->handles.hContext));
3938 if (status != SCARD_S_SUCCESS)
3939 return status;
3940
3941 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3942 {
3943 WLog_Print(log, WLOG_WARN,
3944 "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3945 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3946 rgAtrMasksNdrPtr, call->cAtrs);
3947 return STATUS_INVALID_PARAMETER;
3948 }
3949
3950 if (rgAtrMasksNdrPtr)
3951 {
3952 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3953 if (status != SCARD_S_SUCCESS)
3954 return status;
3955 }
3956
3957 if (rgReaderStatesNdrPtr)
3958 {
3959 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3960 if (status != SCARD_S_SUCCESS)
3961 return status;
3962 call->cReaders = cReaders;
3963 }
3964
3965 smartcard_trace_locate_cards_by_atr_w_call(log, call);
3966 return SCARD_S_SUCCESS;
3967}
3968
3969LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3970{
3971 UINT32 mszNdrPtr = 0;
3972 UINT32 contextNdrPtr = 0;
3973 UINT32 index = 0;
3974 UINT32 pbContextNdrPtr = 0;
3975
3976 WINPR_ASSERT(call);
3977 wLog* log = scard_log();
3978
3979 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3980 return ERROR_INVALID_DATA;
3981
3982 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3983 &index, &pbContextNdrPtr);
3984 if (status != SCARD_S_SUCCESS)
3985 return status;
3986
3987 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3988 return ERROR_INVALID_DATA;
3989
3990 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3991 return STATUS_BUFFER_TOO_SMALL;
3992 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3993 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3994 Stream_Read_UINT32(s, call->Common.cbDataLen);
3995
3996 call->szLookupName = nullptr;
3997 if (mszNdrPtr)
3998 {
3999 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4000 if (status != SCARD_S_SUCCESS)
4001 return status;
4002 }
4003
4004 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4005 &call->Common.handles.hContext);
4006 if (status != SCARD_S_SUCCESS)
4007 return status;
4008
4009 if (contextNdrPtr)
4010 {
4011 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4012 if (status != SCARD_S_SUCCESS)
4013 return status;
4014 }
4015 smartcard_trace_read_cache_a_call(log, call);
4016 return SCARD_S_SUCCESS;
4017}
4018
4019LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
4020{
4021 UINT32 mszNdrPtr = 0;
4022 UINT32 contextNdrPtr = 0;
4023 UINT32 index = 0;
4024 UINT32 pbContextNdrPtr = 0;
4025
4026 WINPR_ASSERT(call);
4027 wLog* log = scard_log();
4028
4029 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4030 return ERROR_INVALID_DATA;
4031
4032 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4033 &index, &pbContextNdrPtr);
4034 if (status != SCARD_S_SUCCESS)
4035 return status;
4036
4037 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4038 return ERROR_INVALID_DATA;
4039
4040 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
4041 return STATUS_BUFFER_TOO_SMALL;
4042 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4043 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
4044 Stream_Read_UINT32(s, call->Common.cbDataLen);
4045
4046 call->szLookupName = nullptr;
4047 if (mszNdrPtr)
4048 {
4049 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4050 if (status != SCARD_S_SUCCESS)
4051 return status;
4052 }
4053
4054 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4055 &call->Common.handles.hContext);
4056 if (status != SCARD_S_SUCCESS)
4057 return status;
4058
4059 if (contextNdrPtr)
4060 {
4061 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4062 if (status != SCARD_S_SUCCESS)
4063 return status;
4064 }
4065 smartcard_trace_read_cache_w_call(log, call);
4066 return SCARD_S_SUCCESS;
4067}
4068
4069LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
4070{
4071 UINT32 mszNdrPtr = 0;
4072 UINT32 contextNdrPtr = 0;
4073 UINT32 pbDataNdrPtr = 0;
4074 UINT32 index = 0;
4075 UINT32 pbContextNdrPtr = 0;
4076
4077 WINPR_ASSERT(call);
4078 wLog* log = scard_log();
4079
4080 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4081 return ERROR_INVALID_DATA;
4082
4083 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4084 &index, &pbContextNdrPtr);
4085 if (status != SCARD_S_SUCCESS)
4086 return status;
4087
4088 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4089 return ERROR_INVALID_DATA;
4090
4091 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4092 return STATUS_BUFFER_TOO_SMALL;
4093
4094 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4095 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4096
4097 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4098 return ERROR_INVALID_DATA;
4099
4100 call->szLookupName = nullptr;
4101 if (mszNdrPtr)
4102 {
4103 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4104 if (status != SCARD_S_SUCCESS)
4105 return status;
4106 }
4107
4108 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4109 &call->Common.handles.hContext);
4110 if (status != SCARD_S_SUCCESS)
4111 return status;
4112
4113 call->Common.CardIdentifier = nullptr;
4114 if (contextNdrPtr)
4115 {
4116 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4117 if (status != SCARD_S_SUCCESS)
4118 return status;
4119 }
4120
4121 call->Common.pbData = nullptr;
4122 if (pbDataNdrPtr)
4123 {
4124 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4125 if (status != SCARD_S_SUCCESS)
4126 return status;
4127 call->Common.cbDataLen = cbDataLen;
4128 }
4129 smartcard_trace_write_cache_a_call(log, call);
4130 return SCARD_S_SUCCESS;
4131}
4132
4133LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
4134{
4135 UINT32 mszNdrPtr = 0;
4136 UINT32 contextNdrPtr = 0;
4137 UINT32 pbDataNdrPtr = 0;
4138 UINT32 index = 0;
4139 UINT32 pbContextNdrPtr = 0;
4140
4141 WINPR_ASSERT(call);
4142 wLog* log = scard_log();
4143
4144 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4145 return ERROR_INVALID_DATA;
4146
4147 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4148 &index, &pbContextNdrPtr);
4149 if (status != SCARD_S_SUCCESS)
4150 return status;
4151
4152 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4153 return ERROR_INVALID_DATA;
4154
4155 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4156 return STATUS_BUFFER_TOO_SMALL;
4157 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4158 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4159
4160 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4161 return ERROR_INVALID_DATA;
4162
4163 call->szLookupName = nullptr;
4164 if (mszNdrPtr)
4165 {
4166 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4167 if (status != SCARD_S_SUCCESS)
4168 return status;
4169 }
4170
4171 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4172 &call->Common.handles.hContext);
4173 if (status != SCARD_S_SUCCESS)
4174 return status;
4175
4176 call->Common.CardIdentifier = nullptr;
4177 if (contextNdrPtr)
4178 {
4179 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4180 if (status != SCARD_S_SUCCESS)
4181 return status;
4182 }
4183
4184 call->Common.pbData = nullptr;
4185 if (pbDataNdrPtr)
4186 {
4187 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4188 if (status != SCARD_S_SUCCESS)
4189 return status;
4190 call->Common.cbDataLen = cbDataLen;
4191 }
4192 smartcard_trace_write_cache_w_call(log, call);
4193 return status;
4194}
4195
4196LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
4197{
4198 WINPR_ASSERT(call);
4199 wLog* log = scard_log();
4200
4201 UINT32 index = 0;
4202 UINT32 pbContextNdrPtr = 0;
4203
4204 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
4205 &pbContextNdrPtr);
4206 if (status != SCARD_S_SUCCESS)
4207 return status;
4208
4209 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
4210 if (status != SCARD_S_SUCCESS)
4211 return status;
4212
4213 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4214 &(call->handles.hContext));
4215 if (status != SCARD_S_SUCCESS)
4216 {
4217 WLog_Print(log, WLOG_ERROR,
4218 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
4219 status);
4220 return status;
4221 }
4222
4223 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
4224 if (status != SCARD_S_SUCCESS)
4225 WLog_Print(log, WLOG_ERROR,
4226 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
4227
4228 smartcard_trace_get_transmit_count_call(log, call);
4229 return status;
4230}
4231
4232LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
4233{
4234 WINPR_ASSERT(call);
4235 wLog* log = scard_log();
4236 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4237 &call->szReaderName);
4238}
4239
4240LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
4241{
4242 WINPR_ASSERT(call);
4243 wLog* log = scard_log();
4244 return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
4245}
4246
4247LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
4248{
4249 WINPR_ASSERT(call);
4250 wLog* log = scard_log();
4251 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
4252}
4253
4254LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
4255{
4256 WINPR_ASSERT(call);
4257 wLog* log = scard_log();
4258 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4259 &call->szReaderName);
4260}
4261
4262LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
4263{
4264 WINPR_ASSERT(ret);
4265 wLog* log = scard_log();
4266 smartcard_trace_device_type_id_return(log, ret);
4267
4268 if (!Stream_EnsureRemainingCapacity(s, 4))
4269 {
4270 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4271 return SCARD_F_INTERNAL_ERROR;
4272 }
4273
4274 Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
4275
4276 return ret->ReturnCode;
4277}
4278
4279LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
4280{
4281 WINPR_ASSERT(ret);
4282 wLog* log = scard_log();
4283
4284 LONG status = 0;
4285 UINT32 cbDataLen = ret->cReaders;
4286 UINT32 index = 0;
4287
4288 smartcard_trace_locate_cards_return(log, ret);
4289 if (ret->ReturnCode != SCARD_S_SUCCESS)
4290 cbDataLen = 0;
4291 if (cbDataLen == SCARD_AUTOALLOCATE)
4292 cbDataLen = 0;
4293
4294 if (!Stream_EnsureRemainingCapacity(s, 4))
4295 {
4296 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4297 return SCARD_F_INTERNAL_ERROR;
4298 }
4299
4300 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4301 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4302 return SCARD_E_NO_MEMORY;
4303
4304 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
4305 if (status != SCARD_S_SUCCESS)
4306 return status;
4307 return ret->ReturnCode;
4308}
4309
4310LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
4311{
4312 WINPR_ASSERT(ret);
4313 wLog* log = scard_log();
4314
4315 LONG status = 0;
4316 UINT32 index = 0;
4317 UINT32 cbDataLen = ret->cbDataLen;
4318 smartcard_trace_get_reader_icon_return(log, ret);
4319 if (ret->ReturnCode != SCARD_S_SUCCESS)
4320 cbDataLen = 0;
4321 if (cbDataLen == SCARD_AUTOALLOCATE)
4322 cbDataLen = 0;
4323
4324 if (!Stream_EnsureRemainingCapacity(s, 4))
4325 {
4326 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4327 return SCARD_F_INTERNAL_ERROR;
4328 }
4329
4330 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4331 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4332 return SCARD_E_NO_MEMORY;
4333
4334 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4335 if (status != SCARD_S_SUCCESS)
4336 return status;
4337 return ret->ReturnCode;
4338}
4339
4340LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
4341{
4342 WINPR_ASSERT(ret);
4343 wLog* log = scard_log();
4344
4345 smartcard_trace_get_transmit_count_return(log, ret);
4346
4347 if (!Stream_EnsureRemainingCapacity(s, 4))
4348 {
4349 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4350 return SCARD_F_INTERNAL_ERROR;
4351 }
4352
4353 Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
4354
4355 return ret->ReturnCode;
4356}
4357
4358LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
4359{
4360 WINPR_ASSERT(ret);
4361 wLog* log = scard_log();
4362
4363 LONG status = 0;
4364 UINT32 index = 0;
4365 UINT32 cbDataLen = ret->cbDataLen;
4366 smartcard_trace_read_cache_return(log, ret);
4367 if (ret->ReturnCode != SCARD_S_SUCCESS)
4368 cbDataLen = 0;
4369
4370 if (cbDataLen == SCARD_AUTOALLOCATE)
4371 cbDataLen = 0;
4372
4373 if (!Stream_EnsureRemainingCapacity(s, 4))
4374 {
4375 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4376 return SCARD_F_INTERNAL_ERROR;
4377 }
4378
4379 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4380 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4381 return SCARD_E_NO_MEMORY;
4382
4383 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4384 if (status != SCARD_S_SUCCESS)
4385 return status;
4386 return ret->ReturnCode;
4387}
4388
4389LONG smartcard_pack_context_call(wStream* s, const Context_Call* call, const char* name)
4390{
4391 WINPR_ASSERT(call);
4392 wLog* log = scard_log();
4393 UINT32 index = 0;
4394
4395 smartcard_trace_context_call(log, call, name);
4396
4397 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4398 if (status != SCARD_S_SUCCESS)
4399 return status;
4400
4401 return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4402}
4403
4404LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call, BOOL unicode)
4405{
4406 WINPR_ASSERT(call);
4407 wLog* log = scard_log();
4408 UINT32 index = 0;
4409
4410 smartcard_trace_list_readers_call(log, call, unicode);
4411
4412 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4413 if (status != SCARD_S_SUCCESS)
4414 return status;
4415
4416 if (!Stream_EnsureRemainingCapacity(s, 4))
4417 return SCARD_E_NO_MEMORY;
4418
4419 Stream_Write_UINT32(s, call->cBytes);
4420 if (!smartcard_ndr_pointer_write(s, &index, call->cBytes))
4421 return SCARD_E_NO_MEMORY;
4422
4423 if (!Stream_EnsureRemainingCapacity(s, 8))
4424 return SCARD_E_NO_MEMORY;
4425
4426 Stream_Write_INT32(s, call->fmszReadersIsNULL);
4427 Stream_Write_UINT32(s, call->cchReaders);
4428
4429 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4430 if (status != SCARD_S_SUCCESS)
4431 return status;
4432
4433 if (call->cBytes > 0)
4434 {
4435 status = smartcard_ndr_write(s, call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
4436 if (status != SCARD_S_SUCCESS)
4437 return status;
4438 }
4439
4440 return SCARD_S_SUCCESS;
4441}
4442
4443WINPR_ATTR_NODISCARD static LONG
4444smartcard_pack_reader_state_a(wStream* s, const LPSCARD_READERSTATEA rgReaderStates,
4445 UINT32 cReaders, UINT32* ptrIndex)
4446{
4447 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4448
4449 if (!Stream_EnsureRemainingCapacity(s, 4))
4450 return SCARD_E_NO_MEMORY;
4451
4452 Stream_Write_UINT32(s, cReaders);
4453
4454 for (UINT32 i = 0; i < cReaders; i++)
4455 {
4456 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4457
4458 if (!Stream_EnsureRemainingCapacity(s, 52))
4459 return SCARD_E_NO_MEMORY;
4460
4461 const UINT32 nameLen = state->szReader ? (UINT32)(strlen(state->szReader) + 1) : 0;
4462 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4463 return SCARD_E_NO_MEMORY;
4464
4465 Stream_Write_UINT32(s, state->dwCurrentState);
4466 Stream_Write_UINT32(s, state->dwEventState);
4467 Stream_Write_UINT32(s, state->cbAtr);
4468 Stream_Write(s, state->rgbAtr, 36);
4469 }
4470
4471 for (UINT32 i = 0; i < cReaders; i++)
4472 {
4473 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4474
4475 if (state->szReader)
4476 {
4477 const UINT32 nameLen = (UINT32)(strlen(state->szReader) + 1);
4478 LONG status = smartcard_ndr_write_a(s, state->szReader, nameLen, NDR_PTR_FULL);
4479 if (status != SCARD_S_SUCCESS)
4480 return status;
4481 }
4482 }
4483
4484 return SCARD_S_SUCCESS;
4485}
4486
4487WINPR_ATTR_NODISCARD static LONG
4488smartcard_pack_reader_state_w(wStream* s, const LPSCARD_READERSTATEW rgReaderStates,
4489 UINT32 cReaders, UINT32* ptrIndex)
4490{
4491 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4492
4493 if (!Stream_EnsureRemainingCapacity(s, 4))
4494 return SCARD_E_NO_MEMORY;
4495
4496 Stream_Write_UINT32(s, cReaders);
4497
4498 for (UINT32 i = 0; i < cReaders; i++)
4499 {
4500 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4501
4502 if (!Stream_EnsureRemainingCapacity(s, 52))
4503 return SCARD_E_NO_MEMORY;
4504
4505 const UINT32 nameLen = state->szReader ? (UINT32)(_wcslen(state->szReader) + 1) : 0;
4506 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4507 return SCARD_E_NO_MEMORY;
4508
4509 Stream_Write_UINT32(s, state->dwCurrentState);
4510 Stream_Write_UINT32(s, state->dwEventState);
4511 Stream_Write_UINT32(s, state->cbAtr);
4512 Stream_Write(s, state->rgbAtr, 36);
4513 }
4514
4515 for (UINT32 i = 0; i < cReaders; i++)
4516 {
4517 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4518
4519 if (state->szReader)
4520 {
4521 const UINT32 nameLen = (UINT32)(_wcslen(state->szReader) + 1);
4522 LONG status = smartcard_ndr_write_w(s, state->szReader, nameLen, NDR_PTR_FULL);
4523 if (status != SCARD_S_SUCCESS)
4524 return status;
4525 }
4526 }
4527
4528 return SCARD_S_SUCCESS;
4529}
4530
4531LONG smartcard_pack_get_status_change_a_call(wStream* s, const GetStatusChangeA_Call* call)
4532{
4533 WINPR_ASSERT(call);
4534 wLog* log = scard_log();
4535 UINT32 index = 0;
4536
4537 smartcard_trace_get_status_change_a_call(log, call);
4538
4539 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4540 if (status != SCARD_S_SUCCESS)
4541 return status;
4542
4543 if (!Stream_EnsureRemainingCapacity(s, 8))
4544 return SCARD_E_NO_MEMORY;
4545
4546 Stream_Write_UINT32(s, call->dwTimeOut);
4547 Stream_Write_UINT32(s, call->cReaders);
4548
4549 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4550 return SCARD_E_NO_MEMORY;
4551
4552 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4553 if (status != SCARD_S_SUCCESS)
4554 return status;
4555
4556 if (call->cReaders > 0)
4557 {
4558 status = smartcard_pack_reader_state_a(s, call->rgReaderStates, call->cReaders, &index);
4559 if (status != SCARD_S_SUCCESS)
4560 return status;
4561 }
4562
4563 return SCARD_S_SUCCESS;
4564}
4565
4566LONG smartcard_pack_get_status_change_w_call(wStream* s, const GetStatusChangeW_Call* call)
4567{
4568 WINPR_ASSERT(call);
4569 wLog* log = scard_log();
4570 UINT32 index = 0;
4571
4572 smartcard_trace_get_status_change_w_call(log, call);
4573
4574 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4575 if (status != SCARD_S_SUCCESS)
4576 return status;
4577
4578 if (!Stream_EnsureRemainingCapacity(s, 8))
4579 return SCARD_E_NO_MEMORY;
4580
4581 Stream_Write_UINT32(s, call->dwTimeOut);
4582 Stream_Write_UINT32(s, call->cReaders);
4583
4584 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4585 return SCARD_E_NO_MEMORY;
4586
4587 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4588 if (status != SCARD_S_SUCCESS)
4589 return status;
4590
4591 if (call->cReaders > 0)
4592 {
4593 status = smartcard_pack_reader_state_w(s, call->rgReaderStates, call->cReaders, &index);
4594 if (status != SCARD_S_SUCCESS)
4595 return status;
4596 }
4597
4598 return SCARD_S_SUCCESS;
4599}
4600
4601LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call)
4602{
4603 WINPR_ASSERT(call);
4604 wLog* log = scard_log();
4605 UINT32 index = 0;
4606
4607 smartcard_trace_connect_a_call(log, call);
4608
4609 const UINT32 readerLen = call->szReader ? (UINT32)(strlen(call->szReader) + 1) : 0;
4610 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4611 return SCARD_E_NO_MEMORY;
4612
4613 LONG status =
4614 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4615 if (status != SCARD_S_SUCCESS)
4616 return status;
4617
4618 if (!Stream_EnsureRemainingCapacity(s, 8))
4619 return SCARD_E_NO_MEMORY;
4620
4621 Stream_Write_UINT32(s, call->Common.dwShareMode);
4622 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4623
4624 if (call->szReader)
4625 {
4626 status = smartcard_ndr_write_a(s, call->szReader, readerLen, NDR_PTR_FULL);
4627 if (status != SCARD_S_SUCCESS)
4628 return status;
4629 }
4630
4631 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4632}
4633
4634LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call)
4635{
4636 WINPR_ASSERT(call);
4637 wLog* log = scard_log();
4638 UINT32 index = 0;
4639
4640 smartcard_trace_connect_w_call(log, call);
4641
4642 const UINT32 readerLen = call->szReader ? (UINT32)(_wcslen(call->szReader) + 1) : 0;
4643 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4644 return SCARD_E_NO_MEMORY;
4645
4646 LONG status =
4647 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4648 if (status != SCARD_S_SUCCESS)
4649 return status;
4650
4651 if (!Stream_EnsureRemainingCapacity(s, 8))
4652 return SCARD_E_NO_MEMORY;
4653
4654 Stream_Write_UINT32(s, call->Common.dwShareMode);
4655 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4656
4657 if (call->szReader)
4658 {
4659 status = smartcard_ndr_write_w(s, call->szReader, readerLen, NDR_PTR_FULL);
4660 if (status != SCARD_S_SUCCESS)
4661 return status;
4662 }
4663
4664 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4665}
4666
4667LONG smartcard_pack_control_call(wStream* s, const Control_Call* call)
4668{
4669 WINPR_ASSERT(call);
4670 wLog* log = scard_log();
4671 UINT32 index = 0;
4672
4673 smartcard_trace_control_call(log, call);
4674
4675 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4676 if (status != SCARD_S_SUCCESS)
4677 return status;
4678
4679 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4680 if (status != SCARD_S_SUCCESS)
4681 return status;
4682
4683 if (!Stream_EnsureRemainingCapacity(s, 8))
4684 return SCARD_E_NO_MEMORY;
4685
4686 Stream_Write_UINT32(s, call->dwControlCode);
4687 Stream_Write_UINT32(s, call->cbInBufferSize);
4688 if (!smartcard_ndr_pointer_write(s, &index, call->cbInBufferSize))
4689 return SCARD_E_NO_MEMORY;
4690
4691 Stream_Write_INT32(s, call->fpvOutBufferIsNULL);
4692 Stream_Write_UINT32(s, call->cbOutBufferSize);
4693
4694 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4695 if (status != SCARD_S_SUCCESS)
4696 return status;
4697
4698 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4699 if (status != SCARD_S_SUCCESS)
4700 return status;
4701
4702 if (call->cbInBufferSize)
4703 {
4704 status = smartcard_ndr_write(s, call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
4705 if (status != SCARD_S_SUCCESS)
4706 return status;
4707 }
4708
4709 return status;
4710}
4711
4712LONG smartcard_pack_hcard_and_disposition_call(wStream* s, const HCardAndDisposition_Call* call,
4713 const char* name)
4714{
4715 WINPR_ASSERT(call);
4716 wLog* log = scard_log();
4717 UINT32 index = 0;
4718
4719 smartcard_trace_hcard_and_disposition_call(log, call, name);
4720
4721 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4722 if (status != SCARD_S_SUCCESS)
4723 return status;
4724
4725 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4726 if (status != SCARD_S_SUCCESS)
4727 return status;
4728
4729 if (!Stream_EnsureRemainingCapacity(s, 4))
4730 return SCARD_E_NO_MEMORY;
4731
4732 Stream_Write_UINT32(s, call->dwDisposition);
4733
4734 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4735 if (status != SCARD_S_SUCCESS)
4736 return status;
4737
4738 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4739}
4740
4741LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
4742{
4743 WINPR_ASSERT(call);
4744 wLog* log = scard_log();
4745 UINT32 index = 0;
4746
4747 smartcard_trace_transmit_call(log, call);
4748
4749 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4750 if (status != SCARD_S_SUCCESS)
4751 return status;
4752
4753 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4754 if (status != SCARD_S_SUCCESS)
4755 return status;
4756
4757 UINT32 cbExtraBytes = 0;
4758 const BYTE* pbExtraBytes = nullptr;
4759 if (call->pioSendPci)
4760 {
4761 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4762 if (cbExtraBytes > 0)
4763 pbExtraBytes = &((const BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
4764 }
4765
4766 if (!Stream_EnsureRemainingCapacity(s, 32))
4767 return SCARD_E_NO_MEMORY;
4768
4769 Stream_Write_UINT32(s, call->pioSendPci ? call->pioSendPci->dwProtocol : 0);
4770 Stream_Write_UINT32(s, cbExtraBytes);
4771 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
4772 return SCARD_E_NO_MEMORY;
4773
4774 Stream_Write_UINT32(s, call->cbSendLength);
4775 if (!smartcard_ndr_pointer_write(s, &index, call->cbSendLength))
4776 return SCARD_E_NO_MEMORY;
4777
4778 const UINT32 recvPciLen = call->pioRecvPci ? (UINT32)call->pioRecvPci->cbPciLength : 0;
4779 if (!smartcard_ndr_pointer_write(s, &index, recvPciLen))
4780 return SCARD_E_NO_MEMORY;
4781
4782 Stream_Write_INT32(s, call->fpbRecvBufferIsNULL);
4783 Stream_Write_UINT32(s, call->cbRecvLength);
4784
4785 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4786 if (status != SCARD_S_SUCCESS)
4787 return status;
4788
4789 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4790 if (status != SCARD_S_SUCCESS)
4791 return status;
4792
4793 if (cbExtraBytes > 0)
4794 {
4795 status = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
4796 if (status != SCARD_S_SUCCESS)
4797 return status;
4798 }
4799
4800 if (call->cbSendLength > 0)
4801 {
4802 status = smartcard_ndr_write(s, call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
4803 if (status != SCARD_S_SUCCESS)
4804 return status;
4805 }
4806
4807 if (call->pioRecvPci && recvPciLen > 0)
4808 {
4809 UINT32 cbRecvExtra = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4810 const BYTE* pbRecvExtra = &((const BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
4811
4812 if (!Stream_EnsureRemainingCapacity(s, 12))
4813 return SCARD_E_NO_MEMORY;
4814
4815 Stream_Write_UINT32(s, call->pioRecvPci->dwProtocol);
4816 Stream_Write_UINT32(s, cbRecvExtra);
4817 if (!smartcard_ndr_pointer_write(s, &index, cbRecvExtra))
4818 return SCARD_E_NO_MEMORY;
4819
4820 if (cbRecvExtra > 0)
4821 {
4822 status = smartcard_ndr_write(s, pbRecvExtra, cbRecvExtra, 1, NDR_PTR_SIMPLE);
4823 if (status != SCARD_S_SUCCESS)
4824 return status;
4825 }
4826 }
4827
4828 return SCARD_S_SUCCESS;
4829}
4830
4831LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call)
4832{
4833 WINPR_ASSERT(call);
4834 wLog* log = scard_log();
4835 UINT32 index = 0;
4836
4837 smartcard_trace_get_attrib_call(log, call);
4838
4839 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4840 if (status != SCARD_S_SUCCESS)
4841 return status;
4842
4843 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4844 if (status != SCARD_S_SUCCESS)
4845 return status;
4846
4847 if (!Stream_EnsureRemainingCapacity(s, 12))
4848 return STATUS_NO_MEMORY;
4849
4850 Stream_Write_UINT32(s, call->dwAttrId);
4851 Stream_Write_INT32(s, call->fpbAttrIsNULL);
4852 Stream_Write_UINT32(s, call->cbAttrLen);
4853
4854 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4855 if (status != SCARD_S_SUCCESS)
4856 return status;
4857
4858 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4859}
4860
4861LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret, BOOL unicode)
4862{
4863 WINPR_ASSERT(ret);
4864 wLog* log = scard_log();
4865 UINT32 index = 0;
4866 UINT32 mszNdrPtr = 0;
4867
4868 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4869 return STATUS_BUFFER_TOO_SMALL;
4870
4871 const UINT32 cBytes = Stream_Get_UINT32(s);
4872
4873 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4874 return ERROR_INVALID_DATA;
4875
4876 if (mszNdrPtr)
4877 {
4878 LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
4879 if (status != SCARD_S_SUCCESS)
4880 return status;
4881 ret->cBytes = cBytes;
4882 }
4883
4884 smartcard_trace_list_readers_return(log, ret, unicode);
4885 return SCARD_S_SUCCESS;
4886}
4887
4888LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Return* ret,
4889 BOOL unicode)
4890{
4891 WINPR_ASSERT(ret);
4892 wLog* log = scard_log();
4893 UINT32 index = 0;
4894 UINT32 ndrPtr = 0;
4895
4896 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4897 return STATUS_BUFFER_TOO_SMALL;
4898
4899 Stream_Read_UINT32(s, ret->cReaders);
4900
4901 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
4902 return ERROR_INVALID_DATA;
4903
4904 if (ndrPtr && ret->cReaders > 0)
4905 {
4906 LONG status =
4907 smartcard_ndr_read_state(log, s, &ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE);
4908 if (status != SCARD_S_SUCCESS)
4909 return status;
4910 }
4911 else
4912 ret->rgReaderStates = nullptr;
4913
4914 smartcard_trace_get_status_change_return(log, ret, unicode);
4915 return SCARD_S_SUCCESS;
4916}
4917
4918LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret)
4919{
4920 WINPR_ASSERT(ret);
4921 wLog* log = scard_log();
4922 UINT32 index = 0;
4923 UINT32 pbContextNdrPtr = 0;
4924
4925 LONG status =
4926 smartcard_unpack_redir_scard_context(log, s, &ret->hContext, &index, &pbContextNdrPtr);
4927 if (status != SCARD_S_SUCCESS)
4928 return status;
4929
4930 status = smartcard_unpack_redir_scard_handle(log, s, &ret->hCard, &index);
4931 if (status != SCARD_S_SUCCESS)
4932 return status;
4933
4934 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4935 return STATUS_BUFFER_TOO_SMALL;
4936
4937 Stream_Read_UINT32(s, ret->dwActiveProtocol);
4938
4939 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &ret->hContext);
4940 if (status != SCARD_S_SUCCESS)
4941 return status;
4942
4943 status = smartcard_unpack_redir_scard_handle_ref(log, s, &ret->hCard);
4944 if (status != SCARD_S_SUCCESS)
4945 return status;
4946
4947 smartcard_trace_connect_return(log, ret);
4948 return SCARD_S_SUCCESS;
4949}
4950
4951LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret)
4952{
4953 WINPR_ASSERT(ret);
4954 wLog* log = scard_log();
4955 UINT32 index = 0;
4956 UINT32 pvOutBufferNdrPtr = 0;
4957
4958 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4959 return STATUS_BUFFER_TOO_SMALL;
4960
4961 const UINT32 cbOutBufferSize = Stream_Get_UINT32(s);
4962
4963 if (!smartcard_ndr_pointer_read(log, s, &index, &pvOutBufferNdrPtr))
4964 return ERROR_INVALID_DATA;
4965
4966 if (pvOutBufferNdrPtr && (cbOutBufferSize > 0))
4967 {
4968 LONG status =
4969 smartcard_ndr_read(log, s, &ret->pvOutBuffer, cbOutBufferSize, 1, NDR_PTR_SIMPLE);
4970 if (status != SCARD_S_SUCCESS)
4971 return status;
4972 ret->cbOutBufferSize = cbOutBufferSize;
4973 }
4974 smartcard_trace_control_return(log, ret);
4975 return SCARD_S_SUCCESS;
4976}
4977
4978LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret)
4979{
4980 WINPR_ASSERT(ret);
4981 wLog* log = scard_log();
4982 UINT32 index = 0;
4983 UINT32 recvPciNdrPtr = 0;
4984 UINT32 recvBufferNdrPtr = 0;
4985
4986 if (!smartcard_ndr_pointer_read(log, s, &index, &recvPciNdrPtr))
4987 return ERROR_INVALID_DATA;
4988
4989 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4990 return STATUS_BUFFER_TOO_SMALL;
4991
4992 const UINT32 cbRecvLength = Stream_Get_UINT32(s);
4993
4994 if (!smartcard_ndr_pointer_read(log, s, &index, &recvBufferNdrPtr))
4995 return ERROR_INVALID_DATA;
4996
4997 if (recvPciNdrPtr)
4998 {
4999 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
5000 return STATUS_BUFFER_TOO_SMALL;
5001
5002 UINT32 dwProtocol = 0;
5003 UINT32 cbExtraBytes = 0;
5004 Stream_Read_UINT32(s, dwProtocol);
5005 Stream_Read_UINT32(s, cbExtraBytes);
5006
5007 UINT32 pbExtraBytesNdrPtr = 0;
5008 if (!smartcard_ndr_pointer_read(log, s, &index, &pbExtraBytesNdrPtr))
5009 return ERROR_INVALID_DATA;
5010
5011 if (pbExtraBytesNdrPtr)
5012 {
5013 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5014 return STATUS_BUFFER_TOO_SMALL;
5015
5016 UINT32 length = 0;
5017 Stream_Read_UINT32(s, length);
5018 if (length != cbExtraBytes)
5019 {
5020 WLog_Print(log, WLOG_WARN,
5021 "Transmit_Return unexpected length: Actual: %" PRIu32
5022 ", Expected: %" PRIu32 " (pioRecvPci.cbExtraBytes)",
5023 length, cbExtraBytes);
5024 return STATUS_INVALID_PARAMETER;
5025 }
5026
5027 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, cbExtraBytes))
5028 return STATUS_BUFFER_TOO_SMALL;
5029
5030 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
5031 if (!ret->pioRecvPci)
5032 return SCARD_E_NO_MEMORY;
5033
5034 ret->pioRecvPci->dwProtocol = dwProtocol;
5035 ret->pioRecvPci->cbPciLength = (DWORD)(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
5036
5037 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
5038 Stream_Read(s, pbExtraBytes, length);
5039 if (smartcard_unpack_read_size_align(s, cbExtraBytes, 4) < 0)
5040 return STATUS_INVALID_PARAMETER;
5041 }
5042 else
5043 {
5044 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST));
5045 if (!ret->pioRecvPci)
5046 return SCARD_E_NO_MEMORY;
5047
5048 ret->pioRecvPci->dwProtocol = dwProtocol;
5049 ret->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
5050 }
5051 }
5052
5053 if (recvBufferNdrPtr && (cbRecvLength > 0))
5054 {
5055 LONG status =
5056 smartcard_ndr_read(log, s, &ret->pbRecvBuffer, cbRecvLength, 1, NDR_PTR_SIMPLE);
5057 if (status != SCARD_S_SUCCESS)
5058 return status;
5059 ret->cbRecvLength = cbRecvLength;
5060 }
5061
5062 smartcard_trace_transmit_return(log, ret);
5063 return SCARD_S_SUCCESS;
5064}
5065
5066LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret)
5067{
5068 WINPR_ASSERT(ret);
5069 wLog* log = scard_log();
5070 UINT32 index = 0;
5071 UINT32 pbAttrPtr = 0;
5072
5073 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5074 return STATUS_BUFFER_TOO_SMALL;
5075
5076 const UINT32 cbAttrLen = Stream_Get_UINT32(s);
5077
5078 if (!smartcard_ndr_pointer_read(log, s, &index, &pbAttrPtr))
5079 return ERROR_INVALID_DATA;
5080
5081 LONG status = smartcard_ndr_read(log, s, &ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
5082 if (status != SCARD_S_SUCCESS)
5083 return status;
5084 ret->cbAttrLen = cbAttrLen;
5085
5086 smartcard_trace_get_attrib_return(log, ret, 0);
5087 return SCARD_S_SUCCESS;
5088}
5089
5090BOOL smartcard_reader_state_return_is_valid_ex(size_t pos, const ReaderState_Return* val,
5091 const char* file, size_t line, const char* fkt)
5092{
5093 if (!val)
5094 {
5095 WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt, "[%" PRIuz "] val = nullptr",
5096 pos);
5097 return FALSE;
5098 }
5099 if (val->cbAtr > sizeof(val->rgbAtr))
5100 {
5101 WLog_Print_dbg_tag(SCARD_TAG, WLOG_WARN, line, file, fkt,
5102 "[%" PRIuz "] val->cbAtr=%" PRIu32 ", max=%" PRIuz, pos, val->cbAtr,
5103 sizeof(val->rgbAtr));
5104 return FALSE;
5105 }
5106
5107 return TRUE;
5108}
Definition wtypes.h:263