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