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