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
53static LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s,
54 REDIR_SCARDCONTEXT* context, UINT32* index,
55 UINT32* ppbContextNdrPtr, const char* file,
56 const char* function, size_t line);
57static LONG smartcard_pack_redir_scard_context(wLog* log, wStream* s,
58 const REDIR_SCARDCONTEXT* context, DWORD* index);
59static LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
60 UINT32* index, const char* file,
61 const char* function, size_t line);
62static LONG smartcard_pack_redir_scard_handle(wLog* log, wStream* s,
63 const REDIR_SCARDHANDLE* handle, DWORD* index);
64static LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s, UINT32 pbContextNdrPtr,
65 REDIR_SCARDCONTEXT* context);
66static LONG smartcard_pack_redir_scard_context_ref(wLog* log, wStream* s,
67 const REDIR_SCARDCONTEXT* context);
68
69static LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s,
70 REDIR_SCARDHANDLE* handle);
71static LONG smartcard_pack_redir_scard_handle_ref(wLog* log, wStream* s,
72 const REDIR_SCARDHANDLE* handle);
73
74typedef enum
75{
76 NDR_PTR_FULL,
77 NDR_PTR_SIMPLE,
78 NDR_PTR_FIXED
79} ndr_ptr_t;
80
81/* Reads a NDR pointer and checks if the value read has the expected relative
82 * addressing */
83#define smartcard_ndr_pointer_read(log, s, index, ptr) \
84 smartcard_ndr_pointer_read_((log), (s), (index), (ptr), __FILE__, __func__, __LINE__)
85static BOOL smartcard_ndr_pointer_read_(wLog* log, wStream* s, UINT32* index, UINT32* ptr,
86 const char* file, const char* fkt, size_t line)
87{
88 const UINT32 expect = 0x20000 + (*index) * 4;
89 UINT32 ndrPtr = 0;
90 WINPR_UNUSED(file);
91 if (!s)
92 return FALSE;
93 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
94 return FALSE;
95
96 Stream_Read_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
97 if (ptr)
98 *ptr = ndrPtr;
99 if (expect != ndrPtr)
100 {
101 /* Allow nullptr pointer if we read the result */
102 if (ptr && (ndrPtr == 0))
103 return TRUE;
104 WLog_Print(log, WLOG_WARN,
105 "[%s:%" PRIuz "] Read context pointer 0x%08" PRIx32 ", expected 0x%08" PRIx32,
106 fkt, line, ndrPtr, expect);
107 return FALSE;
108 }
109
110 (*index) = (*index) + 1;
111 return TRUE;
112}
113
114static LONG smartcard_ndr_read_ex(wLog* log, wStream* s, BYTE** data, size_t min,
115 size_t elementSize, ndr_ptr_t type, size_t* plen)
116{
117 size_t len = 0;
118 size_t offset = 0;
119 size_t len2 = 0;
120 void* r = nullptr;
121 size_t required = 0;
122
123 *data = nullptr;
124 if (plen)
125 *plen = 0;
126
127 switch (type)
128 {
129 case NDR_PTR_FULL:
130 required = 12;
131 break;
132 case NDR_PTR_SIMPLE:
133 required = 4;
134 break;
135 case NDR_PTR_FIXED:
136 required = min;
137 break;
138 default:
139 return STATUS_INVALID_PARAMETER;
140 }
141
142 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, required))
143 return STATUS_BUFFER_TOO_SMALL;
144
145 switch (type)
146 {
147 case NDR_PTR_FULL:
148 Stream_Read_UINT32(s, len);
149 Stream_Read_UINT32(s, offset);
150 Stream_Read_UINT32(s, len2);
151 if (len != offset + len2)
152 {
153 WLog_Print(log, WLOG_ERROR,
154 "Invalid data when reading full NDR pointer: total=%" PRIuz
155 ", offset=%" PRIuz ", remaining=%" PRIuz,
156 len, offset, len2);
157 return STATUS_BUFFER_TOO_SMALL;
158 }
159 break;
160 case NDR_PTR_SIMPLE:
161 Stream_Read_UINT32(s, len);
162
163 if ((len != min) && (min > 0))
164 {
165 WLog_Print(log, WLOG_ERROR,
166 "Invalid data when reading simple NDR pointer: total=%" PRIuz
167 ", expected=%" PRIuz,
168 len, min);
169 return STATUS_BUFFER_TOO_SMALL;
170 }
171 break;
172 case NDR_PTR_FIXED:
173 len = (UINT32)min;
174 break;
175 default:
176 return STATUS_INVALID_PARAMETER;
177 }
178
179 if (min > len)
180 {
181 WLog_Print(log, WLOG_ERROR,
182 "Invalid length read from NDR pointer, minimum %" PRIuz ", got %" PRIuz, min,
183 len);
184 return STATUS_DATA_ERROR;
185 }
186
187 if (len > SIZE_MAX / 2)
188 return STATUS_BUFFER_TOO_SMALL;
189
190 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, elementSize))
191 return STATUS_BUFFER_TOO_SMALL;
192
193 len *= elementSize;
194
195 /* Ensure proper '\0' termination for all kinds of unicode strings
196 * as we do not know if the data from the wire contains one.
197 */
198 r = calloc(len + sizeof(WCHAR), sizeof(CHAR));
199 if (!r)
200 return SCARD_E_NO_MEMORY;
201 Stream_Read(s, r, len);
202 const LONG pad = smartcard_unpack_read_size_align(s, len, 4);
203 if (pad < 0)
204 {
205 free(r);
206 return STATUS_INVALID_PARAMETER;
207 }
208 len += (size_t)pad;
209 *data = r;
210 if (plen)
211 *plen = len;
212 return STATUS_SUCCESS;
213}
214
215static LONG smartcard_ndr_read(wLog* log, wStream* s, BYTE** data, size_t min, size_t elementSize,
216 ndr_ptr_t type)
217{
218 return smartcard_ndr_read_ex(log, s, data, min, elementSize, type, nullptr);
219}
220
221static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, DWORD length)
222{
223 const UINT32 ndrPtr = 0x20000 + (*index) * 4;
224
225 if (!s)
226 return FALSE;
227 if (!Stream_EnsureRemainingCapacity(s, 4))
228 return FALSE;
229
230 if (length > 0)
231 {
232 Stream_Write_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
233 (*index) = (*index) + 1;
234 }
235 else
236 Stream_Write_UINT32(s, 0);
237 return TRUE;
238}
239
240static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size, UINT32 elementSize,
241 ndr_ptr_t type)
242{
243 const UINT32 offset = 0;
244 const UINT32 len = size;
245 const UINT32 dataLen = size * elementSize;
246 size_t required = 0;
247
248 if (size == 0)
249 return SCARD_S_SUCCESS;
250
251 switch (type)
252 {
253 case NDR_PTR_FULL:
254 required = 12;
255 break;
256 case NDR_PTR_SIMPLE:
257 required = 4;
258 break;
259 case NDR_PTR_FIXED:
260 required = 0;
261 break;
262 default:
263 return SCARD_E_INVALID_PARAMETER;
264 }
265
266 if (!Stream_EnsureRemainingCapacity(s, required + dataLen + 4))
267 return STATUS_BUFFER_TOO_SMALL;
268
269 switch (type)
270 {
271 case NDR_PTR_FULL:
272 Stream_Write_UINT32(s, len);
273 Stream_Write_UINT32(s, offset);
274 Stream_Write_UINT32(s, len);
275 break;
276 case NDR_PTR_SIMPLE:
277 Stream_Write_UINT32(s, len);
278 break;
279 case NDR_PTR_FIXED:
280 break;
281 default:
282 return SCARD_E_INVALID_PARAMETER;
283 }
284
285 if (data)
286 Stream_Write(s, data, dataLen);
287 else
288 Stream_Zero(s, dataLen);
289 return smartcard_pack_write_size_align(s, len, 4);
290}
291
292static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size,
293 ndr_ptr_t type)
294{
295 union
296 {
297 const ReaderState_Return* reader;
298 const BYTE* data;
299 } cnv;
300
301 WINPR_ASSERT(data || (size == 0));
302 cnv.reader = data;
303 return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
304}
305
306static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s, LocateCards_ATRMask** data,
307 size_t min, ndr_ptr_t type)
308{
309 union
310 {
312 BYTE** ppv;
313 } u;
314 u.ppc = data;
315 const LONG status = smartcard_ndr_read(log, s, u.ppv, min, sizeof(LocateCards_ATRMask), type);
316 if (status != SCARD_S_SUCCESS)
317 return status;
318
319 /* [MS-RDPESC] 2.2.1.5: cbAtr is range(0..36), the number of valid bytes in the fixed
320 * rgbAtr/rgbMask arrays. A larger value walks past them when the mask is compared byte
321 * by byte, so reject it here rather than trusting the wire value. */
322 LocateCards_ATRMask* masks = *data;
323 for (size_t x = 0; x < min; x++)
324 {
325 const UINT32 val = winpr_Data_Get_UINT32(&masks[x].cbAtr);
326 if (val > ARRAYSIZE(masks[x].rgbAtr))
327 {
328 WLog_Print(log, WLOG_ERROR,
329 "LocateCards_ATRMask[%" PRIuz "]::cbAtr %" PRIu32 " exceeds %" PRIuz, x, val,
330 (size_t)ARRAYSIZE(masks[x].rgbAtr));
331 free(*data);
332 *data = nullptr;
333 return STATUS_DATA_ERROR;
334 }
335 }
336 return SCARD_S_SUCCESS;
337}
338
339static LONG smartcard_ndr_read_fixed_string_a(wLog* log, wStream* s, CHAR** data, size_t min,
340 ndr_ptr_t type)
341{
342 union
343 {
344 CHAR** ppc;
345 BYTE** ppv;
346 } u;
347 u.ppc = data;
348 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(CHAR), type);
349}
350
351static LONG smartcard_ndr_read_fixed_string_w(wLog* log, wStream* s, WCHAR** data, size_t min,
352 ndr_ptr_t type)
353{
354 union
355 {
356 WCHAR** ppc;
357 BYTE** ppv;
358 } u;
359 u.ppc = data;
360 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(WCHAR), type);
361}
362
363static LONG smartcard_ndr_read_a(wLog* log, wStream* s, CHAR** data, ndr_ptr_t type)
364{
365 union
366 {
367 CHAR** ppc;
368 BYTE** ppv;
369 } u;
370 u.ppc = data;
371 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(CHAR), type);
372}
373
374static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data, ndr_ptr_t type)
375{
376 union
377 {
378 WCHAR** ppc;
379 BYTE** ppv;
380 } u;
381 u.ppc = data;
382 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
383}
384
385static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
386{
387 union
388 {
389 UUID** ppc;
390 BYTE** ppv;
391 } u;
392 u.ppc = data;
393 return smartcard_ndr_read(log, s, u.ppv, 1, sizeof(UUID), NDR_PTR_FIXED);
394}
395
396static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode)
397{
398 size_t length = 0;
399 union
400 {
401 const void* pv;
402 const char* sz;
403 const WCHAR* wz;
404 } string;
405 char* mszA = nullptr;
406
407 string.pv = in;
408
409 if (bytes < 1)
410 return nullptr;
411
412 if (in == nullptr)
413 return nullptr;
414
415 if (unicode)
416 {
417 mszA = ConvertMszWCharNToUtf8Alloc(string.wz, bytes / sizeof(WCHAR), &length);
418 if (!mszA)
419 return nullptr;
420 }
421 else
422 {
423 mszA = (char*)calloc(bytes, sizeof(char));
424 if (!mszA)
425 return nullptr;
426 CopyMemory(mszA, string.sz, bytes - 1);
427 length = bytes;
428 }
429
430 if (length < 1)
431 {
432 free(mszA);
433 return nullptr;
434 }
435 for (size_t index = 0; index < length - 1; index++)
436 {
437 if (mszA[index] == '\0')
438 mszA[index] = ',';
439 }
440
441 return mszA;
442}
443
444WINPR_ATTR_MALLOC(free, 1)
445static char* smartcard_create_msz_dump(const char* msz, size_t len)
446{
447 size_t bufferLen = len;
448 char* buffer = calloc(len + 1, 1);
449 if (!buffer)
450 return nullptr;
451
452 char* buf = buffer;
453 const char* cur = msz;
454
455 while ((len > 0) && cur && cur[0] != '\0' && (bufferLen > 0))
456 {
457 size_t clen = strnlen(cur, len);
458 int rc = _snprintf(buf, bufferLen, "%s", cur);
459 bufferLen -= (size_t)rc;
460 buf += rc;
461
462 cur += clen;
463 }
464
465 return buffer;
466}
467
468static void smartcard_msz_dump(wLog* log, DWORD level, const char* prefix, const void* data,
469 size_t len, BOOL wchar)
470{
471 if (!WLog_IsLevelActive(log, level))
472 return;
473
474 char* tmp = nullptr;
475 const char* msz = WINPR_CXX_COMPAT_CAST(const char*, data);
476 size_t mszlen = len;
477 if (wchar)
478 {
479 tmp = ConvertMszWCharNToUtf8Alloc(data, len, &mszlen);
480 msz = tmp;
481 }
482
483 char* array = smartcard_create_msz_dump(msz, mszlen);
484 WLog_Print(log, level, "%s%s", prefix, array);
485 free(array);
486 free(tmp);
487}
488
489WINPR_ATTR_MALLOC(free, 1)
490static char* smartcard_create_array_dump(const void* pd, size_t len)
491{
492 const BYTE* data = pd;
493 int rc = 0;
494
495 size_t bufferLen = len * 4;
496 if (bufferLen < 32)
497 bufferLen = 32;
498 char* buffer = calloc(bufferLen + 1, 1);
499 if (!buffer)
500 return nullptr;
501 char* start = buffer;
502
503 WINPR_ASSERT(buffer || (bufferLen == 0));
504
505 if (!data && (len > 0))
506 {
507 (void)_snprintf(buffer, bufferLen, "{ nullptr [%" PRIuz "] }", len);
508 goto fail;
509 }
510
511 rc = _snprintf(buffer, bufferLen, "{ ");
512 if ((rc < 0) || ((size_t)rc >= bufferLen))
513 goto fail;
514 buffer += rc;
515 bufferLen -= (size_t)rc;
516
517 for (size_t x = 0; x < len; x++)
518 {
519 rc = _snprintf(buffer, bufferLen, "%02X", data[x]);
520 if ((rc < 0) || ((size_t)rc >= bufferLen))
521 goto fail;
522 buffer += rc;
523 bufferLen -= (size_t)rc;
524 }
525
526 rc = _snprintf(buffer, bufferLen, " }");
527 if ((rc < 0) || ((size_t)rc >= bufferLen))
528 goto fail;
529
530fail:
531 return start;
532}
533
534WINPR_ATTR_FORMAT_ARG(3, 7)
535static void smartcard_dump_array(wLog* log, DWORD level, WINPR_FORMAT_ARG const char* prefix,
536 const char* postfix, const void* data, size_t len, ...)
537{
538 if (!WLog_IsLevelActive(log, level))
539 return;
540
541 char* buffer = smartcard_create_array_dump(data, len);
542
543 char* fprefix = nullptr;
544 size_t flen = 0;
545 va_list ap = WINPR_C_ARRAY_INIT;
546 va_start(ap, len);
547 winpr_vasprintf(&fprefix, &flen, prefix, ap);
548 va_end(ap);
549 WLog_Print(log, level, "%s%s%s", prefix, buffer, postfix);
550 free(buffer);
551 free(fprefix);
552}
553
554static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
555{
556 WINPR_ASSERT(pHandle);
557 smartcard_dump_array(log, g_LogLevel, " hContext: ", "", pHandle->pbHandle, pHandle->cbHandle);
558}
559
560static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
561{
562 WINPR_ASSERT(phContext);
563 smartcard_dump_array(log, g_LogLevel, "hContext: ", "", phContext->pbContext,
564 phContext->cbContext);
565}
566
567static void smartcard_trace_context_and_string_call_a(wLog* log, const char* name,
568 const REDIR_SCARDCONTEXT* phContext,
569 const CHAR* sz)
570{
571 if (!WLog_IsLevelActive(log, g_LogLevel))
572 return;
573
574 WLog_Print(log, g_LogLevel, "%s {", name);
575 smartcard_log_context(log, phContext);
576 WLog_Print(log, g_LogLevel, " sz=%s", sz);
577
578 WLog_Print(log, g_LogLevel, "}");
579}
580
581static void smartcard_trace_context_and_string_call_w(wLog* log, const char* name,
582 const REDIR_SCARDCONTEXT* phContext,
583 const WCHAR* sz)
584{
585 char* tmp = nullptr;
586
587 if (!WLog_IsLevelActive(log, g_LogLevel))
588 return;
589
590 if (sz)
591 tmp = ConvertWCharToUtf8Alloc(sz, nullptr);
592
593 WLog_Print(log, g_LogLevel, "%s {", name);
594 smartcard_log_context(log, phContext);
595 WLog_Print(log, g_LogLevel, " sz=%s", tmp);
596 WLog_Print(log, g_LogLevel, "}");
597 free(tmp);
598}
599
600static void smartcard_trace_context_call(wLog* log, const Context_Call* call, const char* name)
601{
602 WINPR_ASSERT(call);
603
604 if (!WLog_IsLevelActive(log, g_LogLevel))
605 return;
606
607 WLog_Print(log, g_LogLevel, "%s_Call {", name);
608 smartcard_log_context(log, &call->handles.hContext);
609
610 WLog_Print(log, g_LogLevel, "}");
611}
612
613static void smartcard_trace_list_reader_groups_call(wLog* log, const ListReaderGroups_Call* call,
614 BOOL unicode)
615{
616 WINPR_ASSERT(call);
617
618 if (!WLog_IsLevelActive(log, g_LogLevel))
619 return;
620
621 WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Call {", unicode ? "W" : "A");
622 smartcard_log_context(log, &call->handles.hContext);
623
624 WLog_Print(log, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32,
625 call->fmszGroupsIsNULL, call->cchGroups);
626 WLog_Print(log, g_LogLevel, "}");
627}
628
629static void dump_reader_states_return(wLog* log, const ReaderState_Return* rgReaderStates,
630 UINT32 cReaders)
631{
632 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
633 for (UINT32 index = 0; index < cReaders; index++)
634 {
635 const ReaderState_Return* readerState = &rgReaderStates[index];
636 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
637 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
638 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
639 szCurrentState, readerState->dwCurrentState);
640 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
641 szEventState, readerState->dwEventState);
642 free(szCurrentState);
643 free(szEventState);
644
645 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
646 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
647 }
648}
649
650static void dump_reader_states_a(wLog* log, const SCARD_READERSTATEA* rgReaderStates,
651 UINT32 cReaders)
652{
653 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
654 for (UINT32 index = 0; index < cReaders; index++)
655 {
656 const SCARD_READERSTATEA* readerState = &rgReaderStates[index];
657
658 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
659 readerState->szReader, readerState->cbAtr);
660 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
661 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
662 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
663 szCurrentState, readerState->dwCurrentState);
664 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
665 szEventState, readerState->dwEventState);
666 free(szCurrentState);
667 free(szEventState);
668
669 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
670 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
671 }
672}
673
674static void dump_reader_states_w(wLog* log, const SCARD_READERSTATEW* rgReaderStates,
675 UINT32 cReaders)
676{
677 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
678 for (UINT32 index = 0; index < cReaders; index++)
679 {
680 const SCARD_READERSTATEW* readerState = &rgReaderStates[index];
681 char* buffer = ConvertWCharToUtf8Alloc(readerState->szReader, nullptr);
682 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
683 buffer, readerState->cbAtr);
684 free(buffer);
685 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
686 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
687 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
688 szCurrentState, readerState->dwCurrentState);
689 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
690 szEventState, readerState->dwEventState);
691 free(szCurrentState);
692 free(szEventState);
693
694 smartcard_dump_array(log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { ", " }",
695 readerState->rgbAtr, readerState->cbAtr, index, readerState->cbAtr);
696 }
697}
698
699static void smartcard_trace_get_status_change_w_call(wLog* log, const GetStatusChangeW_Call* call)
700{
701 WINPR_ASSERT(call);
702
703 if (!WLog_IsLevelActive(log, g_LogLevel))
704 return;
705
706 WLog_Print(log, g_LogLevel, "GetStatusChangeW_Call {");
707 smartcard_log_context(log, &call->handles.hContext);
708
709 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
710 call->cReaders);
711
712 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
713
714 WLog_Print(log, g_LogLevel, "}");
715}
716
717static void smartcard_trace_list_reader_groups_return(wLog* log, const ListReaderGroups_Return* ret,
718 BOOL unicode)
719{
720 WINPR_ASSERT(ret);
721
722 if (!WLog_IsLevelActive(log, g_LogLevel))
723 return;
724
725 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
726
727 WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Return {", unicode ? "W" : "A");
728 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIx32 ")",
729 SCardGetErrorString(ret->ReturnCode),
730 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
731 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
732 WLog_Print(log, g_LogLevel, "}");
733 free(mszA);
734}
735
736static void smartcard_trace_list_readers_call(wLog* log, const ListReaders_Call* call, BOOL unicode)
737{
738 WINPR_ASSERT(call);
739
740 if (!WLog_IsLevelActive(log, g_LogLevel))
741 return;
742
743 char* mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode);
744
745 WLog_Print(log, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A");
746 smartcard_log_context(log, &call->handles.hContext);
747
748 WLog_Print(log, g_LogLevel,
749 "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32
750 " cchReaders: 0x%08" PRIX32 "",
751 call->cBytes, mszGroupsA, call->fmszReadersIsNULL, call->cchReaders);
752 WLog_Print(log, g_LogLevel, "}");
753
754 free(mszGroupsA);
755}
756
757static void smartcard_trace_locate_cards_by_atr_a_call(wLog* log,
758 const LocateCardsByATRA_Call* call)
759{
760 WINPR_ASSERT(call);
761
762 if (!WLog_IsLevelActive(log, g_LogLevel))
763 return;
764
765 WLog_Print(log, g_LogLevel, "LocateCardsByATRA_Call {");
766 smartcard_log_context(log, &call->handles.hContext);
767
768 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
769
770 WLog_Print(log, g_LogLevel, "}");
771}
772
773static void smartcard_trace_locate_cards_a_call(wLog* log, const LocateCardsA_Call* call)
774{
775 WINPR_ASSERT(call);
776
777 if (!WLog_IsLevelActive(log, g_LogLevel))
778 return;
779
780 WLog_Print(log, g_LogLevel, "LocateCardsA_Call {");
781 smartcard_log_context(log, &call->handles.hContext);
782 WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
783 smartcard_msz_dump(log, g_LogLevel, " mszCards=", call->mszCards, call->cBytes, FALSE);
784 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
785 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
786
787 WLog_Print(log, g_LogLevel, "}");
788}
789
790static void smartcard_trace_locate_cards_return(wLog* log, const LocateCards_Return* ret)
791{
792 WINPR_ASSERT(ret);
793
794 if (!WLog_IsLevelActive(log, g_LogLevel))
795 return;
796
797 WLog_Print(log, g_LogLevel, "LocateCards_Return {");
798 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
799 SCardGetErrorString(ret->ReturnCode),
800 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
801
802 if (ret->ReturnCode == SCARD_S_SUCCESS)
803 {
804 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, ret->cReaders);
805 }
806 WLog_Print(log, g_LogLevel, "}");
807}
808
809static void smartcard_trace_get_reader_icon_return(wLog* log, const GetReaderIcon_Return* ret)
810{
811 WINPR_ASSERT(ret);
812
813 if (!WLog_IsLevelActive(log, g_LogLevel))
814 return;
815
816 WLog_Print(log, g_LogLevel, "GetReaderIcon_Return {");
817 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
818 SCardGetErrorString(ret->ReturnCode),
819 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
820
821 if (ret->ReturnCode == SCARD_S_SUCCESS)
822 {
823 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
824 }
825 WLog_Print(log, g_LogLevel, "}");
826}
827
828static void smartcard_trace_get_transmit_count_return(wLog* log, const GetTransmitCount_Return* ret)
829{
830 WINPR_ASSERT(ret);
831
832 if (!WLog_IsLevelActive(log, g_LogLevel))
833 return;
834
835 WLog_Print(log, g_LogLevel, "GetTransmitCount_Return {");
836 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
837 SCardGetErrorString(ret->ReturnCode),
838 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
839
840 WLog_Print(log, g_LogLevel, " cTransmitCount=%" PRIu32, ret->cTransmitCount);
841 WLog_Print(log, g_LogLevel, "}");
842}
843
844static void smartcard_trace_read_cache_return(wLog* log, const ReadCache_Return* ret)
845{
846 WINPR_ASSERT(ret);
847
848 if (!WLog_IsLevelActive(log, g_LogLevel))
849 return;
850
851 WLog_Print(log, g_LogLevel, "ReadCache_Return {");
852 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
853 SCardGetErrorString(ret->ReturnCode),
854 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
855
856 if (ret->ReturnCode == SCARD_S_SUCCESS)
857 {
858 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, ret->cbDataLen);
859 smartcard_dump_array(log, g_LogLevel, " cbData: ", "", ret->pbData, ret->cbDataLen);
860 }
861 WLog_Print(log, g_LogLevel, "}");
862}
863
864static void smartcard_trace_locate_cards_w_call(wLog* log, const LocateCardsW_Call* call)
865{
866 WINPR_ASSERT(call);
867
868 if (!WLog_IsLevelActive(log, g_LogLevel))
869 return;
870
871 WLog_Print(log, g_LogLevel, "LocateCardsW_Call {");
872 smartcard_log_context(log, &call->handles.hContext);
873 WLog_Print(log, g_LogLevel, " cBytes=%" PRIu32, call->cBytes);
874 smartcard_msz_dump(log, g_LogLevel, " sz2=", call->mszCards, call->cBytes, TRUE);
875 WLog_Print(log, g_LogLevel, " cReaders=%" PRIu32, call->cReaders);
876 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
877 WLog_Print(log, g_LogLevel, "}");
878}
879
880static void smartcard_trace_list_readers_return(wLog* log, const ListReaders_Return* ret,
881 BOOL unicode)
882{
883 WINPR_ASSERT(ret);
884
885 if (!WLog_IsLevelActive(log, g_LogLevel))
886 return;
887
888 WLog_Print(log, g_LogLevel, "ListReaders%s_Return {", unicode ? "W" : "A");
889 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
890 SCardGetErrorString(ret->ReturnCode),
891 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
892
893 if (ret->ReturnCode != SCARD_S_SUCCESS)
894 {
895 WLog_Print(log, g_LogLevel, "}");
896 return;
897 }
898
899 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
900
901 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
902 WLog_Print(log, g_LogLevel, "}");
903 free(mszA);
904}
905
906static void smartcard_trace_get_status_change_return(wLog* log, const GetStatusChange_Return* ret,
907 BOOL unicode)
908{
909 WINPR_ASSERT(ret);
910
911 if (!WLog_IsLevelActive(log, g_LogLevel))
912 return;
913
914 WLog_Print(log, g_LogLevel, "GetStatusChange%s_Return {", unicode ? "W" : "A");
915 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
916 SCardGetErrorString(ret->ReturnCode),
917 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
918 WLog_Print(log, g_LogLevel, " cReaders: %" PRIu32 "", ret->cReaders);
919
920 dump_reader_states_return(log, ret->rgReaderStates, ret->cReaders);
921
922 if (!ret->rgReaderStates && (ret->cReaders > 0))
923 {
924 WLog_Print(log, g_LogLevel, " [INVALID STATE] rgReaderStates=nullptr, cReaders=%" PRIu32,
925 ret->cReaders);
926 }
927 else if (ret->ReturnCode != SCARD_S_SUCCESS)
928 {
929 WLog_Print(log, g_LogLevel, " [INVALID RETURN] rgReaderStates, cReaders=%" PRIu32,
930 ret->cReaders);
931 }
932 else
933 {
934 for (UINT32 index = 0; index < ret->cReaders; index++)
935 {
936 const ReaderState_Return* rgReaderState = &(ret->rgReaderStates[index]);
937 char* szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState);
938 char* szEventState = SCardGetReaderStateString(rgReaderState->dwEventState);
939 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")",
940 index, szCurrentState, rgReaderState->dwCurrentState);
941 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")",
942 index, szEventState, rgReaderState->dwEventState);
943 smartcard_dump_array(
944 log, g_LogLevel, " [%" PRIu32 "]: cbAtr: %" PRIu32 " rgbAtr: ", "",
945 rgReaderState->rgbAtr, rgReaderState->cbAtr, index, rgReaderState->cbAtr);
946 free(szCurrentState);
947 free(szEventState);
948 }
949 }
950
951 WLog_Print(log, g_LogLevel, "}");
952}
953
954static void smartcard_trace_context_and_two_strings_a_call(wLog* log,
955 const ContextAndTwoStringA_Call* call)
956{
957 WINPR_ASSERT(call);
958
959 if (!WLog_IsLevelActive(log, g_LogLevel))
960 return;
961
962 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
963 smartcard_log_context(log, &call->handles.hContext);
964 WLog_Print(log, g_LogLevel, " sz1=%s", call->sz1);
965 WLog_Print(log, g_LogLevel, " sz2=%s", call->sz2);
966 WLog_Print(log, g_LogLevel, "}");
967}
968
969static void smartcard_trace_context_and_two_strings_w_call(wLog* log,
970 const ContextAndTwoStringW_Call* call)
971{
972 WINPR_ASSERT(call);
973 char sz1[1024] = WINPR_C_ARRAY_INIT;
974 char sz2[1024] = WINPR_C_ARRAY_INIT;
975
976 if (!WLog_IsLevelActive(log, g_LogLevel))
977 return;
978 if (call->sz1)
979 (void)ConvertWCharToUtf8(call->sz1, sz1, ARRAYSIZE(sz1));
980 if (call->sz2)
981 (void)ConvertWCharToUtf8(call->sz2, sz2, ARRAYSIZE(sz2));
982
983 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
984 smartcard_log_context(log, &call->handles.hContext);
985 WLog_Print(log, g_LogLevel, " sz1=%s", sz1);
986 WLog_Print(log, g_LogLevel, " sz2=%s", sz2);
987 WLog_Print(log, g_LogLevel, "}");
988}
989
990static void smartcard_trace_get_transmit_count_call(wLog* log, const GetTransmitCount_Call* call)
991{
992 WINPR_ASSERT(call);
993
994 if (!WLog_IsLevelActive(log, g_LogLevel))
995 return;
996
997 WLog_Print(log, g_LogLevel, "GetTransmitCount_Call {");
998 smartcard_log_context(log, &call->handles.hContext);
999 smartcard_log_redir_handle(log, &call->handles.hCard);
1000
1001 WLog_Print(log, g_LogLevel, "}");
1002}
1003
1004static void smartcard_trace_write_cache_a_call(wLog* log, const WriteCacheA_Call* call)
1005{
1006 WINPR_ASSERT(call);
1007
1008 if (!WLog_IsLevelActive(log, g_LogLevel))
1009 return;
1010
1011 WLog_Print(log, g_LogLevel, "WriteCacheA_Call {");
1012
1013 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
1014
1015 smartcard_log_context(log, &call->Common.handles.hContext);
1016 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1017 sizeof(UUID));
1018 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1019 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1020 smartcard_dump_array(log, g_LogLevel, " pbData=", "", call->Common.pbData,
1021 call->Common.cbDataLen);
1022 WLog_Print(log, g_LogLevel, "}");
1023}
1024
1025static void smartcard_trace_write_cache_w_call(wLog* log, const WriteCacheW_Call* call)
1026{
1027 WINPR_ASSERT(call);
1028 char tmp[1024] = WINPR_C_ARRAY_INIT;
1029
1030 if (!WLog_IsLevelActive(log, g_LogLevel))
1031 return;
1032
1033 WLog_Print(log, g_LogLevel, "WriteCacheW_Call {");
1034
1035 if (call->szLookupName)
1036 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1037 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
1038
1039 smartcard_log_context(log, &call->Common.handles.hContext);
1040 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1041 sizeof(UUID));
1042 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1043 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1044 smartcard_dump_array(log, g_LogLevel, " pbData=", "", call->Common.pbData,
1045 call->Common.cbDataLen);
1046 WLog_Print(log, g_LogLevel, "}");
1047}
1048
1049static void smartcard_trace_read_cache_a_call(wLog* log, const ReadCacheA_Call* call)
1050{
1051 WINPR_ASSERT(call);
1052
1053 if (!WLog_IsLevelActive(log, g_LogLevel))
1054 return;
1055
1056 WLog_Print(log, g_LogLevel, "ReadCacheA_Call {");
1057
1058 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
1059 smartcard_log_context(log, &call->Common.handles.hContext);
1060 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1061 sizeof(UUID));
1062 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1063 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1064 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1065
1066 WLog_Print(log, g_LogLevel, "}");
1067}
1068
1069static void smartcard_trace_read_cache_w_call(wLog* log, const ReadCacheW_Call* call)
1070{
1071 WINPR_ASSERT(call);
1072 char tmp[1024] = WINPR_C_ARRAY_INIT;
1073
1074 if (!WLog_IsLevelActive(log, g_LogLevel))
1075 return;
1076
1077 WLog_Print(log, g_LogLevel, "ReadCacheW_Call {");
1078 if (call->szLookupName)
1079 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1080 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
1081
1082 smartcard_log_context(log, &call->Common.handles.hContext);
1083 smartcard_dump_array(log, g_LogLevel, "..CardIdentifier=", "", call->Common.CardIdentifier,
1084 sizeof(UUID));
1085 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1086 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1087 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1088
1089 WLog_Print(log, g_LogLevel, "}");
1090}
1091
1092static void smartcard_trace_transmit_call(wLog* log, const Transmit_Call* call)
1093{
1094 WINPR_ASSERT(call);
1095 UINT32 cbExtraBytes = 0;
1096 BYTE* pbExtraBytes = nullptr;
1097
1098 if (!WLog_IsLevelActive(log, g_LogLevel))
1099 return;
1100
1101 WLog_Print(log, g_LogLevel, "Transmit_Call {");
1102 smartcard_log_context(log, &call->handles.hContext);
1103 smartcard_log_redir_handle(log, &call->handles.hCard);
1104
1105 if (call->pioSendPci)
1106 {
1107 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1108 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
1109 WLog_Print(log, g_LogLevel, "pioSendPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1110 call->pioSendPci->dwProtocol, cbExtraBytes);
1111
1112 if (cbExtraBytes)
1113 {
1114 smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1115 }
1116 }
1117 else
1118 {
1119 WLog_Print(log, g_LogLevel, "pioSendPci: null");
1120 }
1121
1122 WLog_Print(log, g_LogLevel, "cbSendLength: %" PRIu32 "", call->cbSendLength);
1123
1124 if (call->pbSendBuffer)
1125 {
1126 smartcard_dump_array(log, g_LogLevel, "pbSendBuffer: ", "", call->pbSendBuffer,
1127 call->cbSendLength);
1128 }
1129 else
1130 {
1131 WLog_Print(log, g_LogLevel, "pbSendBuffer: null");
1132 }
1133
1134 if (call->pioRecvPci)
1135 {
1136 cbExtraBytes = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1137 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1138 WLog_Print(log, g_LogLevel, "pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1139 call->pioRecvPci->dwProtocol, cbExtraBytes);
1140
1141 if (cbExtraBytes)
1142 {
1143 smartcard_dump_array(log, g_LogLevel, "pbExtraBytes: ", "", pbExtraBytes, cbExtraBytes);
1144 }
1145 }
1146 else
1147 {
1148 WLog_Print(log, g_LogLevel, "pioRecvPci: null");
1149 }
1150
1151 WLog_Print(log, g_LogLevel, "fpbRecvBufferIsNULL: %" PRId32 " cbRecvLength: %" PRIu32 "",
1152 call->fpbRecvBufferIsNULL, call->cbRecvLength);
1153 WLog_Print(log, g_LogLevel, "}");
1154}
1155
1156static void smartcard_trace_locate_cards_by_atr_w_call(wLog* log,
1157 const LocateCardsByATRW_Call* call)
1158{
1159 WINPR_ASSERT(call);
1160
1161 if (!WLog_IsLevelActive(log, g_LogLevel))
1162 return;
1163
1164 WLog_Print(log, g_LogLevel, "LocateCardsByATRW_Call {");
1165 smartcard_log_context(log, &call->handles.hContext);
1166
1167 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
1168
1169 WLog_Print(log, g_LogLevel, "}");
1170}
1171
1172static void smartcard_trace_transmit_return(wLog* log, const Transmit_Return* ret)
1173{
1174 WINPR_ASSERT(ret);
1175 UINT32 cbExtraBytes = 0;
1176 BYTE* pbExtraBytes = nullptr;
1177
1178 if (!WLog_IsLevelActive(log, g_LogLevel))
1179 return;
1180
1181 WLog_Print(log, g_LogLevel, "Transmit_Return {");
1182 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1183 SCardGetErrorString(ret->ReturnCode),
1184 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1185
1186 if (ret->pioRecvPci)
1187 {
1188 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1189 pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1190 WLog_Print(log, g_LogLevel,
1191 " pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1192 ret->pioRecvPci->dwProtocol, cbExtraBytes);
1193
1194 if (cbExtraBytes)
1195 {
1196 smartcard_dump_array(log, g_LogLevel, " pbExtraBytes: ", "", pbExtraBytes,
1197 cbExtraBytes);
1198 }
1199 }
1200 else
1201 {
1202 WLog_Print(log, g_LogLevel, " pioRecvPci: null");
1203 }
1204
1205 WLog_Print(log, g_LogLevel, " cbRecvLength: %" PRIu32 "", ret->cbRecvLength);
1206
1207 if (ret->pbRecvBuffer)
1208 {
1209 smartcard_dump_array(log, g_LogLevel, " pbRecvBuffer: ", "", ret->pbRecvBuffer,
1210 ret->cbRecvLength);
1211 }
1212 else
1213 {
1214 WLog_Print(log, g_LogLevel, " pbRecvBuffer: null");
1215 }
1216
1217 WLog_Print(log, g_LogLevel, "}");
1218}
1219
1220static void smartcard_trace_control_return(wLog* log, const Control_Return* ret)
1221{
1222 WINPR_ASSERT(ret);
1223
1224 if (!WLog_IsLevelActive(log, g_LogLevel))
1225 return;
1226
1227 WLog_Print(log, g_LogLevel, "Control_Return {");
1228 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1229 SCardGetErrorString(ret->ReturnCode),
1230 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1231 WLog_Print(log, g_LogLevel, " cbOutBufferSize: %" PRIu32 "", ret->cbOutBufferSize);
1232
1233 if (ret->pvOutBuffer)
1234 {
1235 smartcard_dump_array(log, g_LogLevel, "pvOutBuffer: ", "", ret->pvOutBuffer,
1236 ret->cbOutBufferSize);
1237 }
1238 else
1239 {
1240 WLog_Print(log, g_LogLevel, "pvOutBuffer: null");
1241 }
1242
1243 WLog_Print(log, g_LogLevel, "}");
1244}
1245
1246static void smartcard_trace_control_call(wLog* log, const Control_Call* call)
1247{
1248 WINPR_ASSERT(call);
1249
1250 if (!WLog_IsLevelActive(log, g_LogLevel))
1251 return;
1252
1253 WLog_Print(log, g_LogLevel, "Control_Call {");
1254 smartcard_log_context(log, &call->handles.hContext);
1255 smartcard_log_redir_handle(log, &call->handles.hCard);
1256
1257 WLog_Print(log, g_LogLevel,
1258 "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32
1259 " fpvOutBufferIsNULL: %" PRId32 " cbOutBufferSize: %" PRIu32 "",
1260 call->dwControlCode, call->cbInBufferSize, call->fpvOutBufferIsNULL,
1261 call->cbOutBufferSize);
1262
1263 if (call->pvInBuffer)
1264 {
1265 smartcard_dump_array(log, WLOG_DEBUG, "pbInBuffer: ", "", call->pvInBuffer,
1266 call->cbInBufferSize);
1267 }
1268 else
1269 {
1270 WLog_Print(log, g_LogLevel, "pvInBuffer: null");
1271 }
1272
1273 WLog_Print(log, g_LogLevel, "}");
1274}
1275
1276static void smartcard_trace_set_attrib_call(wLog* log, const SetAttrib_Call* call)
1277{
1278 WINPR_ASSERT(call);
1279
1280 if (!WLog_IsLevelActive(log, g_LogLevel))
1281 return;
1282
1283 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1284 smartcard_log_context(log, &call->handles.hContext);
1285 smartcard_log_redir_handle(log, &call->handles.hCard);
1286 WLog_Print(log, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId);
1287 WLog_Print(log, g_LogLevel, "cbAttrLen: 0x%08" PRIx32, call->cbAttrLen);
1288 smartcard_dump_array(log, g_LogLevel, "pbAttr: ", "", call->pbAttr, call->cbAttrLen);
1289 WLog_Print(log, g_LogLevel, "}");
1290}
1291
1292static void smartcard_trace_get_attrib_return(wLog* log, const GetAttrib_Return* ret,
1293 DWORD dwAttrId)
1294{
1295 WINPR_ASSERT(ret);
1296
1297 if (!WLog_IsLevelActive(log, g_LogLevel))
1298 return;
1299
1300 WLog_Print(log, g_LogLevel, "GetAttrib_Return {");
1301 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1302 SCardGetErrorString(ret->ReturnCode),
1303 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1304 WLog_Print(log, g_LogLevel, " dwAttrId: %s (0x%08" PRIX32 ") cbAttrLen: 0x%08" PRIX32 "",
1305 SCardGetAttributeString(dwAttrId), dwAttrId, ret->cbAttrLen);
1306 smartcard_dump_array(log, g_LogLevel, " ", "", ret->pbAttr, ret->cbAttrLen);
1307
1308 WLog_Print(log, g_LogLevel, "}");
1309}
1310
1311static void smartcard_trace_get_attrib_call(wLog* log, const GetAttrib_Call* call)
1312{
1313 WINPR_ASSERT(call);
1314
1315 if (!WLog_IsLevelActive(log, g_LogLevel))
1316 return;
1317
1318 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1319 smartcard_log_context(log, &call->handles.hContext);
1320 smartcard_log_redir_handle(log, &call->handles.hCard);
1321
1322 WLog_Print(log, g_LogLevel,
1323 "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32
1324 "",
1325 SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->fpbAttrIsNULL,
1326 call->cbAttrLen);
1327 WLog_Print(log, g_LogLevel, "}");
1328}
1329
1330static void smartcard_trace_status_call(wLog* log, const Status_Call* call, BOOL unicode)
1331{
1332 WINPR_ASSERT(call);
1333
1334 if (!WLog_IsLevelActive(log, g_LogLevel))
1335 return;
1336
1337 WLog_Print(log, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A");
1338 smartcard_log_context(log, &call->handles.hContext);
1339 smartcard_log_redir_handle(log, &call->handles.hCard);
1340
1341 WLog_Print(log, g_LogLevel,
1342 "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "",
1343 call->fmszReaderNamesIsNULL, call->cchReaderLen, call->cbAtrLen);
1344 WLog_Print(log, g_LogLevel, "}");
1345}
1346
1347static void smartcard_trace_status_return(wLog* log, const Status_Return* ret, BOOL unicode)
1348{
1349 WINPR_ASSERT(ret);
1350 char* mszReaderNamesA = nullptr;
1351 DWORD cBytes = 0;
1352
1353 if (!WLog_IsLevelActive(log, g_LogLevel))
1354 return;
1355 cBytes = ret->cBytes;
1356 if (ret->ReturnCode != SCARD_S_SUCCESS)
1357 cBytes = 0;
1358 if (cBytes == SCARD_AUTOALLOCATE)
1359 cBytes = 0;
1360 mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode);
1361
1362 WLog_Print(log, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A");
1363 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1364 SCardGetErrorString(ret->ReturnCode),
1365 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1366 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ") dwProtocol: %s (0x%08" PRIX32 ")",
1367 SCardGetCardStateString(ret->dwState), ret->dwState,
1368 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1369
1370 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " mszReaderNames: %s", ret->cBytes,
1371 mszReaderNamesA);
1372
1373 smartcard_dump_array(log, g_LogLevel, " cbAtrLen: %" PRIu32 " pbAtr: ", "", ret->pbAtr,
1374 ret->cbAtrLen, ret->cbAtrLen);
1375 WLog_Print(log, g_LogLevel, "}");
1376 free(mszReaderNamesA);
1377}
1378
1379static void smartcard_trace_state_return(wLog* log, const State_Return* ret)
1380{
1381 WINPR_ASSERT(ret);
1382 char* state = nullptr;
1383
1384 if (!WLog_IsLevelActive(log, g_LogLevel))
1385 return;
1386
1387 state = SCardGetReaderStateString(ret->dwState);
1388 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1389 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1390 SCardGetErrorString(ret->ReturnCode),
1391 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1392 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ")", state, ret->dwState);
1393 WLog_Print(log, g_LogLevel, " dwProtocol: %s (0x%08" PRIX32 ")",
1394 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1395 WLog_Print(log, g_LogLevel, " cbAtrLen: (0x%08" PRIX32 ")", ret->cbAtrLen);
1396 smartcard_dump_array(log, g_LogLevel, " rgAtr: ", "", ret->rgAtr, sizeof(ret->rgAtr));
1397 WLog_Print(log, g_LogLevel, "}");
1398 free(state);
1399}
1400
1401static void smartcard_trace_reconnect_return(wLog* log, const Reconnect_Return* ret)
1402{
1403 WINPR_ASSERT(ret);
1404
1405 if (!WLog_IsLevelActive(log, g_LogLevel))
1406 return;
1407
1408 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1409 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1410 SCardGetErrorString(ret->ReturnCode),
1411 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1412 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1413 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1414 WLog_Print(log, g_LogLevel, "}");
1415}
1416
1417static void smartcard_trace_connect_a_call(wLog* log, const ConnectA_Call* call)
1418{
1419 WINPR_ASSERT(call);
1420
1421 if (!WLog_IsLevelActive(log, g_LogLevel))
1422 return;
1423
1424 WLog_Print(log, g_LogLevel, "ConnectA_Call {");
1425 smartcard_log_context(log, &call->Common.handles.hContext);
1426
1427 WLog_Print(log, g_LogLevel,
1428 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1429 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1430 call->szReader, SCardGetShareModeString(call->Common.dwShareMode),
1431 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1432 call->Common.dwPreferredProtocols);
1433 WLog_Print(log, g_LogLevel, "}");
1434}
1435
1436static void smartcard_trace_connect_w_call(wLog* log, const ConnectW_Call* call)
1437{
1438 WINPR_ASSERT(call);
1439 char szReaderA[1024] = WINPR_C_ARRAY_INIT;
1440
1441 if (!WLog_IsLevelActive(log, g_LogLevel))
1442 return;
1443
1444 if (call->szReader)
1445 (void)ConvertWCharToUtf8(call->szReader, szReaderA, ARRAYSIZE(szReaderA));
1446 WLog_Print(log, g_LogLevel, "ConnectW_Call {");
1447 smartcard_log_context(log, &call->Common.handles.hContext);
1448
1449 WLog_Print(log, g_LogLevel,
1450 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1451 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1452 szReaderA, SCardGetShareModeString(call->Common.dwShareMode),
1453 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1454 call->Common.dwPreferredProtocols);
1455 WLog_Print(log, g_LogLevel, "}");
1456}
1457
1458static void smartcard_trace_hcard_and_disposition_call(wLog* log,
1459 const HCardAndDisposition_Call* call,
1460 const char* name)
1461{
1462 WINPR_ASSERT(call);
1463
1464 if (!WLog_IsLevelActive(log, g_LogLevel))
1465 return;
1466
1467 WLog_Print(log, g_LogLevel, "%s_Call {", name);
1468 smartcard_log_context(log, &call->handles.hContext);
1469 smartcard_log_redir_handle(log, &call->handles.hCard);
1470
1471 WLog_Print(log, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")",
1472 SCardGetDispositionString(call->dwDisposition), call->dwDisposition);
1473 WLog_Print(log, g_LogLevel, "}");
1474}
1475
1476static void smartcard_trace_establish_context_call(wLog* log, const EstablishContext_Call* call)
1477{
1478 WINPR_ASSERT(call);
1479
1480 if (!WLog_IsLevelActive(log, g_LogLevel))
1481 return;
1482
1483 WLog_Print(log, g_LogLevel, "EstablishContext_Call {");
1484 WLog_Print(log, g_LogLevel, "dwScope: %s (0x%08" PRIX32 ")", SCardGetScopeString(call->dwScope),
1485 call->dwScope);
1486 WLog_Print(log, g_LogLevel, "}");
1487}
1488
1489static void smartcard_trace_establish_context_return(wLog* log, const EstablishContext_Return* ret)
1490{
1491 WINPR_ASSERT(ret);
1492
1493 if (!WLog_IsLevelActive(log, g_LogLevel))
1494 return;
1495
1496 WLog_Print(log, g_LogLevel, "EstablishContext_Return {");
1497 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1498 SCardGetErrorString(ret->ReturnCode),
1499 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1500 smartcard_log_context(log, &ret->hContext);
1501
1502 WLog_Print(log, g_LogLevel, "}");
1503}
1504
1505void smartcard_trace_long_return(const Long_Return* ret, const char* name)
1506{
1507 wLog* log = scard_log();
1508 smartcard_trace_long_return_int(log, ret, name);
1509}
1510
1511void smartcard_trace_long_return_int(wLog* log, const Long_Return* ret, const char* name)
1512{
1513 WINPR_ASSERT(ret);
1514
1515 if (!WLog_IsLevelActive(log, g_LogLevel))
1516 return;
1517
1518 WLog_Print(log, g_LogLevel, "%s_Return {", name);
1519 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1520 SCardGetErrorString(ret->ReturnCode),
1521 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1522 WLog_Print(log, g_LogLevel, "}");
1523}
1524
1525static void smartcard_trace_connect_return(wLog* log, const Connect_Return* ret)
1526{
1527 WINPR_ASSERT(ret);
1528
1529 if (!WLog_IsLevelActive(log, g_LogLevel))
1530 return;
1531
1532 WLog_Print(log, g_LogLevel, "Connect_Return {");
1533 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1534 SCardGetErrorString(ret->ReturnCode),
1535 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1536 smartcard_log_context(log, &ret->hContext);
1537 smartcard_log_redir_handle(log, &ret->hCard);
1538
1539 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1540 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1541 WLog_Print(log, g_LogLevel, "}");
1542}
1543
1544static void smartcard_trace_reconnect_call(wLog* log, const Reconnect_Call* call)
1545{
1546 WINPR_ASSERT(call);
1547
1548 if (!WLog_IsLevelActive(log, g_LogLevel))
1549 return;
1550
1551 WLog_Print(log, g_LogLevel, "Reconnect_Call {");
1552 smartcard_log_context(log, &call->handles.hContext);
1553 smartcard_log_redir_handle(log, &call->handles.hCard);
1554
1555 WLog_Print(log, g_LogLevel,
1556 "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32
1557 ") dwInitialization: %s (0x%08" PRIX32 ")",
1558 SCardGetShareModeString(call->dwShareMode), call->dwShareMode,
1559 SCardGetProtocolString(call->dwPreferredProtocols), call->dwPreferredProtocols,
1560 SCardGetDispositionString(call->dwInitialization), call->dwInitialization);
1561 WLog_Print(log, g_LogLevel, "}");
1562}
1563
1564static void smartcard_trace_device_type_id_return(wLog* log, const GetDeviceTypeId_Return* ret)
1565{
1566 WINPR_ASSERT(ret);
1567
1568 if (!WLog_IsLevelActive(log, g_LogLevel))
1569 return;
1570
1571 WLog_Print(log, g_LogLevel, "GetDeviceTypeId_Return {");
1572 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1573 SCardGetErrorString(ret->ReturnCode),
1574 WINPR_CXX_COMPAT_CAST(UINT32, ret->ReturnCode));
1575 WLog_Print(log, g_LogLevel, " dwDeviceId=%08" PRIx32, ret->dwDeviceId);
1576
1577 WLog_Print(log, g_LogLevel, "}");
1578}
1579
1580static LONG smartcard_unpack_common_context_and_string_a(wLog* log, wStream* s,
1581 REDIR_SCARDCONTEXT* phContext,
1582 CHAR** pszReaderName)
1583{
1584 UINT32 index = 0;
1585 UINT32 pbContextNdrPtr = 0;
1586 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1587 if (status != SCARD_S_SUCCESS)
1588 return status;
1589
1590 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1591 return ERROR_INVALID_DATA;
1592
1593 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1594 if (status != SCARD_S_SUCCESS)
1595 return status;
1596
1597 status = smartcard_ndr_read_a(log, s, pszReaderName, NDR_PTR_FULL);
1598 if (status != SCARD_S_SUCCESS)
1599 return status;
1600
1601 smartcard_trace_context_and_string_call_a(log, __func__, phContext, *pszReaderName);
1602 return SCARD_S_SUCCESS;
1603}
1604
1605static LONG smartcard_unpack_common_context_and_string_w(wLog* log, wStream* s,
1606 REDIR_SCARDCONTEXT* phContext,
1607 WCHAR** pszReaderName)
1608{
1609 UINT32 index = 0;
1610 UINT32 pbContextNdrPtr = 0;
1611
1612 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1613 if (status != SCARD_S_SUCCESS)
1614 return status;
1615
1616 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
1617 return ERROR_INVALID_DATA;
1618
1619 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1620 if (status != SCARD_S_SUCCESS)
1621 return status;
1622
1623 status = smartcard_ndr_read_w(log, s, pszReaderName, NDR_PTR_FULL);
1624 if (status != SCARD_S_SUCCESS)
1625 return status;
1626
1627 smartcard_trace_context_and_string_call_w(log, __func__, phContext, *pszReaderName);
1628 return SCARD_S_SUCCESS;
1629}
1630
1631LONG smartcard_unpack_common_type_header(wStream* s)
1632{
1633 wLog* log = scard_log();
1634 UINT8 version = 0;
1635 UINT32 filler = 0;
1636 UINT8 endianness = 0;
1637 UINT16 commonHeaderLength = 0;
1638
1639 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1640 return STATUS_BUFFER_TOO_SMALL;
1641
1642 /* Process CommonTypeHeader */
1643 Stream_Read_UINT8(s, version); /* Version (1 byte) */
1644 Stream_Read_UINT8(s, endianness); /* Endianness (1 byte) */
1645 Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
1646 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0xCCCCCCCC */
1647
1648 if (version != 1)
1649 {
1650 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Version %" PRIu8 "", version);
1651 return STATUS_INVALID_PARAMETER;
1652 }
1653
1654 if (endianness != 0x10)
1655 {
1656 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %" PRIu8 "",
1657 endianness);
1658 return STATUS_INVALID_PARAMETER;
1659 }
1660
1661 if (commonHeaderLength != 8)
1662 {
1663 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %" PRIu16 "",
1664 commonHeaderLength);
1665 return STATUS_INVALID_PARAMETER;
1666 }
1667
1668 if (filler != 0xCCCCCCCC)
1669 {
1670 WLog_Print(log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08" PRIX32 "", filler);
1671 return STATUS_INVALID_PARAMETER;
1672 }
1673
1674 return SCARD_S_SUCCESS;
1675}
1676
1677void smartcard_pack_common_type_header(wStream* s)
1678{
1679 Stream_Write_UINT8(s, 1); /* Version (1 byte) */
1680 Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */
1681 Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */
1682 Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
1683}
1684
1685LONG smartcard_unpack_private_type_header(wStream* s)
1686{
1687 wLog* log = scard_log();
1688 UINT32 filler = 0;
1689 UINT32 objectBufferLength = 0;
1690
1691 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1692 return STATUS_BUFFER_TOO_SMALL;
1693
1694 Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1695 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0x00000000 */
1696
1697 if (filler != 0x00000000)
1698 {
1699 WLog_Print(log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08" PRIX32 "", filler);
1700 return STATUS_INVALID_PARAMETER;
1701 }
1702
1703 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, objectBufferLength))
1704 return STATUS_INVALID_PARAMETER;
1705
1706 return SCARD_S_SUCCESS;
1707}
1708
1709void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength)
1710{
1711 Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1712 Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */
1713}
1714
1715LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment)
1716{
1717 const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1718 const size_t pad = padsize - size;
1719
1720 if (pad > 0)
1721 {
1722 if (!Stream_SafeSeek(s, pad))
1723 return -1;
1724 }
1725
1726 return (LONG)pad;
1727}
1728
1729LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment)
1730{
1731 const size_t padsize = (size + alignment - 1) & ~(alignment - 1);
1732 const size_t pad = padsize - size;
1733
1734 if (pad)
1735 {
1736 if (!Stream_EnsureRemainingCapacity(s, pad))
1737 {
1738 wLog* log = scard_log();
1739 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
1740 return SCARD_F_INTERNAL_ERROR;
1741 }
1742
1743 Stream_Zero(s, pad);
1744 }
1745
1746 return SCARD_S_SUCCESS;
1747}
1748
1749SCARDCONTEXT smartcard_scard_context_native_from_redir(REDIR_SCARDCONTEXT* context)
1750{
1751 SCARDCONTEXT hContext = WINPR_C_ARRAY_INIT;
1752
1753 WINPR_ASSERT(context);
1754 if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
1755 {
1756 wLog* log = scard_log();
1757 WLog_Print(log, WLOG_WARN,
1758 "REDIR_SCARDCONTEXT does not match native size: Actual: %" PRIu32
1759 ", Expected: %" PRIuz "",
1760 context->cbContext, sizeof(ULONG_PTR));
1761 return 0;
1762 }
1763
1764 if (context->cbContext)
1765 CopyMemory(&hContext, &(context->pbContext), context->cbContext);
1766
1767 return hContext;
1768}
1769
1770void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context, SCARDCONTEXT hContext)
1771{
1772 WINPR_ASSERT(context);
1773 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1774 context->cbContext = sizeof(ULONG_PTR);
1775 CopyMemory(&(context->pbContext), &hContext, context->cbContext);
1776}
1777
1778SCARDHANDLE smartcard_scard_handle_native_from_redir(REDIR_SCARDHANDLE* handle)
1779{
1780 SCARDHANDLE hCard = 0;
1781
1782 WINPR_ASSERT(handle);
1783 if (handle->cbHandle == 0)
1784 return hCard;
1785
1786 if (handle->cbHandle != sizeof(ULONG_PTR))
1787 {
1788 wLog* log = scard_log();
1789 WLog_Print(log, WLOG_WARN,
1790 "REDIR_SCARDHANDLE does not match native size: Actual: %" PRIu32
1791 ", Expected: %" PRIuz "",
1792 handle->cbHandle, sizeof(ULONG_PTR));
1793 return 0;
1794 }
1795
1796 if (handle->cbHandle)
1797 CopyMemory(&hCard, &(handle->pbHandle), handle->cbHandle);
1798
1799 return hCard;
1800}
1801
1802void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle, SCARDHANDLE hCard)
1803{
1804 WINPR_ASSERT(handle);
1805 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1806 handle->cbHandle = sizeof(ULONG_PTR);
1807 CopyMemory(&(handle->pbHandle), &hCard, handle->cbHandle);
1808}
1809
1810#define smartcard_context_supported(log, size) \
1811 smartcard_context_supported_((log), (size), __FILE__, __func__, __LINE__)
1812static LONG smartcard_context_supported_(wLog* log, uint32_t size, const char* file,
1813 const char* fkt, size_t line)
1814{
1815 switch (size)
1816 {
1817 case 0:
1818 case 4:
1819 case 8:
1820 return SCARD_S_SUCCESS;
1821 default:
1822 {
1823 const uint32_t level = WLOG_WARN;
1824 if (WLog_IsLevelActive(log, level))
1825 {
1826 WLog_PrintTextMessage(log, level, line, file, fkt,
1827 "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %" PRIu32 "",
1828 size);
1829 }
1830 return STATUS_INVALID_PARAMETER;
1831 }
1832 }
1833}
1834
1835LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
1836 UINT32* index, UINT32* ppbContextNdrPtr,
1837 const char* file, const char* function, size_t line)
1838{
1839 UINT32 pbContextNdrPtr = 0;
1840
1841 WINPR_UNUSED(file);
1842 WINPR_ASSERT(context);
1843
1844 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1845
1846 if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ")", file,
1847 function, line))
1848 return STATUS_BUFFER_TOO_SMALL;
1849
1850 const LONG status = smartcard_context_supported_(log, context->cbContext, file, function, line);
1851 if (status != SCARD_S_SUCCESS)
1852 return status;
1853
1854 Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1855
1856 if (!smartcard_ndr_pointer_read_(log, s, index, &pbContextNdrPtr, file, function, line))
1857 return ERROR_INVALID_DATA;
1858
1859 if (((context->cbContext == 0) && pbContextNdrPtr) ||
1860 ((context->cbContext != 0) && !pbContextNdrPtr))
1861 {
1862 WLog_Print(log, WLOG_WARN,
1863 "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1864 ") inconsistency",
1865 context->cbContext, pbContextNdrPtr);
1866 return STATUS_INVALID_PARAMETER;
1867 }
1868
1869 if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, context->cbContext, 1,
1870 "%s(%s:%" PRIuz ")", file, function, line))
1871 return STATUS_INVALID_PARAMETER;
1872
1873 *ppbContextNdrPtr = pbContextNdrPtr;
1874 return SCARD_S_SUCCESS;
1875}
1876
1877LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1878 const REDIR_SCARDCONTEXT* context, DWORD* index)
1879{
1880 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1881
1882 WINPR_ASSERT(context);
1883 if (context->cbContext != 0)
1884 {
1885 Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1886 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1887 *index = *index + 1;
1888 }
1889 else
1890 Stream_Zero(s, 8);
1891
1892 return SCARD_S_SUCCESS;
1893}
1894
1895LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1896 WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1897 REDIR_SCARDCONTEXT* context)
1898{
1899 UINT32 length = 0;
1900
1901 WINPR_ASSERT(context);
1902 if (context->cbContext == 0)
1903 return SCARD_S_SUCCESS;
1904
1905 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1906 return STATUS_BUFFER_TOO_SMALL;
1907
1908 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1909
1910 if (length != context->cbContext)
1911 {
1912 WLog_Print(log, WLOG_WARN,
1913 "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1914 length, context->cbContext);
1915 return STATUS_INVALID_PARAMETER;
1916 }
1917
1918 const LONG status = smartcard_context_supported(log, context->cbContext);
1919 if (status != SCARD_S_SUCCESS)
1920 return status;
1921
1922 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1923 return STATUS_BUFFER_TOO_SMALL;
1924
1925 if (context->cbContext)
1926 Stream_Read(s, &(context->pbContext), context->cbContext);
1927 else
1928 ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1929
1930 return SCARD_S_SUCCESS;
1931}
1932
1933LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1934 const REDIR_SCARDCONTEXT* context)
1935{
1936 WINPR_ASSERT(context);
1937 Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1938
1939 if (context->cbContext)
1940 {
1941 Stream_Write(s, &(context->pbContext), context->cbContext);
1942 }
1943
1944 return SCARD_S_SUCCESS;
1945}
1946
1947LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
1948 UINT32* index, const char* file, const char* function,
1949 size_t line)
1950{
1951 WINPR_ASSERT(handle);
1952 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1953
1954 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1955 return STATUS_BUFFER_TOO_SMALL;
1956
1957 Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1958
1959 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
1960 return STATUS_BUFFER_TOO_SMALL;
1961
1962 if (!smartcard_ndr_pointer_read_(log, s, index, nullptr, file, function, line))
1963 return ERROR_INVALID_DATA;
1964
1965 return SCARD_S_SUCCESS;
1966}
1967
1968LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1969 const REDIR_SCARDHANDLE* handle, DWORD* index)
1970{
1971 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1972
1973 WINPR_ASSERT(handle);
1974 if (handle->cbHandle != 0)
1975 {
1976 Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
1977 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1978 *index = *index + 1;
1979 }
1980 else
1981 Stream_Zero(s, 8);
1982 return SCARD_S_SUCCESS;
1983}
1984
1985LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
1986{
1987 UINT32 length = 0;
1988
1989 WINPR_ASSERT(handle);
1990 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1991 return STATUS_BUFFER_TOO_SMALL;
1992
1993 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1994
1995 if (length != handle->cbHandle)
1996 {
1997 WLog_Print(log, WLOG_WARN,
1998 "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
1999 handle->cbHandle);
2000 return STATUS_INVALID_PARAMETER;
2001 }
2002
2003 if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
2004 {
2005 WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
2006 handle->cbHandle);
2007 return STATUS_INVALID_PARAMETER;
2008 }
2009
2010 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
2011 return STATUS_BUFFER_TOO_SMALL;
2012
2013 if (handle->cbHandle)
2014 Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
2015
2016 return SCARD_S_SUCCESS;
2017}
2018
2019LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2020 const REDIR_SCARDHANDLE* handle)
2021{
2022 WINPR_ASSERT(handle);
2023 Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2024
2025 if (handle->cbHandle)
2026 Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
2027
2028 return SCARD_S_SUCCESS;
2029}
2030
2031LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
2032{
2033 WINPR_ASSERT(call);
2034 wLog* log = scard_log();
2035
2036 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2037 return STATUS_BUFFER_TOO_SMALL;
2038
2039 Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2040 smartcard_trace_establish_context_call(log, call);
2041 return SCARD_S_SUCCESS;
2042}
2043
2044LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2045{
2046 WINPR_ASSERT(ret);
2047 wLog* log = scard_log();
2048 LONG status = 0;
2049 DWORD index = 0;
2050
2051 smartcard_trace_establish_context_return(log, ret);
2052 if (ret->ReturnCode != SCARD_S_SUCCESS)
2053 return ret->ReturnCode;
2054
2055 status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2056 if (status != SCARD_S_SUCCESS)
2057 return status;
2058
2059 return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2060}
2061
2062LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2063{
2064 UINT32 index = 0;
2065 UINT32 pbContextNdrPtr = 0;
2066 wLog* log = scard_log();
2067
2068 WINPR_ASSERT(call);
2069 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2070 &pbContextNdrPtr);
2071 if (status != SCARD_S_SUCCESS)
2072 return status;
2073
2074 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2075 &(call->handles.hContext));
2076 if (status != SCARD_S_SUCCESS)
2077 WLog_Print(log, WLOG_ERROR,
2078 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2079 status);
2080
2081 smartcard_trace_context_call(log, call, name);
2082 return status;
2083}
2084
2085LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2086{
2087 UINT32 index = 0;
2088 UINT32 pbContextNdrPtr = 0;
2089 wLog* log = scard_log();
2090
2091 WINPR_ASSERT(call);
2092 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2093 &pbContextNdrPtr);
2094
2095 if (status != SCARD_S_SUCCESS)
2096 return status;
2097
2098 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2099 return STATUS_BUFFER_TOO_SMALL;
2100
2101 Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2102 Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */
2103 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2104 &(call->handles.hContext));
2105
2106 if (status != SCARD_S_SUCCESS)
2107 return status;
2108
2109 smartcard_trace_list_reader_groups_call(log, call, unicode);
2110 return SCARD_S_SUCCESS;
2111}
2112
2113LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2114 BOOL unicode)
2115{
2116 WINPR_ASSERT(ret);
2117 wLog* log = scard_log();
2118 LONG status = 0;
2119 DWORD cBytes = ret->cBytes;
2120 UINT32 index = 0;
2121
2122 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2123 if (ret->ReturnCode != SCARD_S_SUCCESS)
2124 cBytes = 0;
2125 if (cBytes == SCARD_AUTOALLOCATE)
2126 cBytes = 0;
2127
2128 if (!Stream_EnsureRemainingCapacity(s, 4))
2129 return SCARD_E_NO_MEMORY;
2130
2131 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2132 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2133 return SCARD_E_NO_MEMORY;
2134
2135 status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2136 if (status != SCARD_S_SUCCESS)
2137 return status;
2138 return ret->ReturnCode;
2139}
2140
2141LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2142{
2143 UINT32 index = 0;
2144 UINT32 mszGroupsNdrPtr = 0;
2145 UINT32 pbContextNdrPtr = 0;
2146 wLog* log = scard_log();
2147
2148 WINPR_ASSERT(call);
2149 call->mszGroups = nullptr;
2150
2151 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2152 &pbContextNdrPtr);
2153 if (status != SCARD_S_SUCCESS)
2154 return status;
2155
2156 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2157 return STATUS_BUFFER_TOO_SMALL;
2158
2159 Stream_Read_UINT32(s, call->cBytes); /* cBytes (4 bytes) */
2160 if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2161 return ERROR_INVALID_DATA;
2162
2163 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2164 return STATUS_BUFFER_TOO_SMALL;
2165 Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2166 Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */
2167
2168 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2169 &(call->handles.hContext));
2170 if (status != SCARD_S_SUCCESS)
2171 return status;
2172
2173 if (mszGroupsNdrPtr)
2174 {
2175 status = smartcard_ndr_read(log, s, &call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
2176 if (status != SCARD_S_SUCCESS)
2177 return status;
2178 }
2179
2180 smartcard_trace_list_readers_call(log, call, unicode);
2181 return SCARD_S_SUCCESS;
2182}
2183
2184LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2185{
2186 WINPR_ASSERT(ret);
2187 wLog* log = scard_log();
2188 LONG status = 0;
2189 UINT32 index = 0;
2190 UINT32 size = ret->cBytes;
2191
2192 smartcard_trace_list_readers_return(log, ret, unicode);
2193 if (ret->ReturnCode != SCARD_S_SUCCESS)
2194 size = 0;
2195
2196 if (!Stream_EnsureRemainingCapacity(s, 4))
2197 {
2198 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2199 return SCARD_F_INTERNAL_ERROR;
2200 }
2201
2202 Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2203 if (!smartcard_ndr_pointer_write(s, &index, size))
2204 return SCARD_E_NO_MEMORY;
2205
2206 status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2207 if (status != SCARD_S_SUCCESS)
2208 return status;
2209 return ret->ReturnCode;
2210}
2211
2212static LONG smartcard_unpack_connect_common(wLog* log, wStream* s, Connect_Common_Call* common,
2213 UINT32* index, UINT32* ppbContextNdrPtr)
2214{
2215 WINPR_ASSERT(common);
2216 LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2217 ppbContextNdrPtr);
2218 if (status != SCARD_S_SUCCESS)
2219 return status;
2220
2221 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2222 return STATUS_BUFFER_TOO_SMALL;
2223
2224 Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
2225 Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2226 return SCARD_S_SUCCESS;
2227}
2228
2229LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2230{
2231 LONG status = 0;
2232 UINT32 index = 0;
2233 UINT32 pbContextNdrPtr = 0;
2234
2235 WINPR_ASSERT(call);
2236 wLog* log = scard_log();
2237
2238 call->szReader = nullptr;
2239
2240 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2241 return ERROR_INVALID_DATA;
2242
2243 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2244 if (status != SCARD_S_SUCCESS)
2245 {
2246 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2247 status);
2248 return status;
2249 }
2250
2251 status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2252 if (status != SCARD_S_SUCCESS)
2253 return status;
2254
2255 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2256 &(call->Common.handles.hContext));
2257 if (status != SCARD_S_SUCCESS)
2258 WLog_Print(log, WLOG_ERROR,
2259 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2260 status);
2261
2262 smartcard_trace_connect_a_call(log, call);
2263 return status;
2264}
2265
2266LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2267{
2268 LONG status = 0;
2269 UINT32 index = 0;
2270 UINT32 pbContextNdrPtr = 0;
2271
2272 WINPR_ASSERT(call);
2273 wLog* log = scard_log();
2274 call->szReader = nullptr;
2275
2276 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2277 return ERROR_INVALID_DATA;
2278
2279 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2280 if (status != SCARD_S_SUCCESS)
2281 {
2282 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2283 status);
2284 return status;
2285 }
2286
2287 status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2288 if (status != SCARD_S_SUCCESS)
2289 return status;
2290
2291 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2292 &(call->Common.handles.hContext));
2293 if (status != SCARD_S_SUCCESS)
2294 WLog_Print(log, WLOG_ERROR,
2295 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2296 status);
2297
2298 smartcard_trace_connect_w_call(log, call);
2299 return status;
2300}
2301
2302LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2303{
2304 LONG status = 0;
2305 DWORD index = 0;
2306
2307 WINPR_ASSERT(ret);
2308 wLog* log = scard_log();
2309 smartcard_trace_connect_return(log, ret);
2310
2311 status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2312 if (status != SCARD_S_SUCCESS)
2313 return status;
2314
2315 status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2316 if (status != SCARD_S_SUCCESS)
2317 return status;
2318
2319 if (!Stream_EnsureRemainingCapacity(s, 4))
2320 return SCARD_E_NO_MEMORY;
2321
2322 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2323 status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2324 if (status != SCARD_S_SUCCESS)
2325 return status;
2326 return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2327}
2328
2329LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2330{
2331 UINT32 index = 0;
2332 UINT32 pbContextNdrPtr = 0;
2333
2334 WINPR_ASSERT(call);
2335 wLog* log = scard_log();
2336 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2337 &pbContextNdrPtr);
2338 if (status != SCARD_S_SUCCESS)
2339 return status;
2340
2341 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2342 if (status != SCARD_S_SUCCESS)
2343 return status;
2344
2345 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2346 return STATUS_BUFFER_TOO_SMALL;
2347
2348 Stream_Read_UINT32(s, call->dwShareMode); /* dwShareMode (4 bytes) */
2349 Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2350 Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */
2351
2352 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2353 &(call->handles.hContext));
2354 if (status != SCARD_S_SUCCESS)
2355 {
2356 WLog_Print(log, WLOG_ERROR,
2357 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2358 status);
2359 return status;
2360 }
2361
2362 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2363 if (status != SCARD_S_SUCCESS)
2364 WLog_Print(log, WLOG_ERROR,
2365 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2366
2367 smartcard_trace_reconnect_call(log, call);
2368 return status;
2369}
2370
2371LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2372{
2373 WINPR_ASSERT(ret);
2374 wLog* log = scard_log();
2375 smartcard_trace_reconnect_return(log, ret);
2376
2377 if (!Stream_EnsureRemainingCapacity(s, 4))
2378 return SCARD_E_NO_MEMORY;
2379 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2380 return ret->ReturnCode;
2381}
2382
2383LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2384 const char* name)
2385{
2386 UINT32 index = 0;
2387 UINT32 pbContextNdrPtr = 0;
2388
2389 WINPR_ASSERT(call);
2390 wLog* log = scard_log();
2391
2392 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2393 &pbContextNdrPtr);
2394 if (status != SCARD_S_SUCCESS)
2395 return status;
2396
2397 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2398 if (status != SCARD_S_SUCCESS)
2399 return status;
2400
2401 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2402 return STATUS_BUFFER_TOO_SMALL;
2403
2404 Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2405
2406 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2407 &(call->handles.hContext));
2408 if (status != SCARD_S_SUCCESS)
2409 return status;
2410
2411 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2412 if (status != SCARD_S_SUCCESS)
2413 return status;
2414
2415 smartcard_trace_hcard_and_disposition_call(log, call, name);
2416 return status;
2417}
2418
2419static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2420{
2421 WINPR_ASSERT(call);
2422
2423 if (!WLog_IsLevelActive(log, g_LogLevel))
2424 return;
2425
2426 WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2427 smartcard_log_context(log, &call->handles.hContext);
2428
2429 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2430 call->cReaders);
2431
2432 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2433
2434 WLog_Print(log, g_LogLevel, "}");
2435}
2436
2437static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2438 UINT32 cReaders, UINT32* ptrIndex)
2439{
2440 LONG status = SCARD_E_NO_MEMORY;
2441
2442 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2443 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2444 return status;
2445
2446 const UINT32 len = Stream_Get_UINT32(s);
2447 if (len != cReaders)
2448 {
2449 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2450 return status;
2451 }
2452
2453 LPSCARD_READERSTATEA rgReaderStates =
2454 (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2455 BOOL* states = calloc(cReaders, sizeof(BOOL));
2456 if (!rgReaderStates || !states)
2457 goto fail;
2458 status = ERROR_INVALID_DATA;
2459
2460 for (UINT32 index = 0; index < cReaders; index++)
2461 {
2462 UINT32 ptr = UINT32_MAX;
2463 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2464
2465 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2466 goto fail;
2467
2468 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2469 {
2470 if (ptr != 0)
2471 goto fail;
2472 }
2473 /* Ignore nullptr length strings */
2474 states[index] = ptr != 0;
2475 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2476 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2477 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2478 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2479 {
2480 WLog_Print(log, WLOG_ERROR,
2481 "SCARD_READERSTATEA[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2482 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2483 goto fail;
2484 }
2485 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2486 }
2487
2488 for (UINT32 index = 0; index < cReaders; index++)
2489 {
2490 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2491
2492 /* Ignore empty strings */
2493 if (!states[index])
2494 continue;
2495 status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2496 if (status != SCARD_S_SUCCESS)
2497 goto fail;
2498 }
2499
2500 *ppcReaders = rgReaderStates;
2501 free(states);
2502 return SCARD_S_SUCCESS;
2503fail:
2504 if (rgReaderStates)
2505 {
2506 for (UINT32 index = 0; index < cReaders; index++)
2507 {
2508 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2509 free(readerState->szReader);
2510 }
2511 }
2512 free(rgReaderStates);
2513 free(states);
2514 return status;
2515}
2516
2517static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2518 UINT32 cReaders, UINT32* ptrIndex)
2519{
2520 LONG status = SCARD_E_NO_MEMORY;
2521
2522 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2523 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2524 return status;
2525
2526 const UINT32 len = Stream_Get_UINT32(s);
2527 if (len != cReaders)
2528 {
2529 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2530 return status;
2531 }
2532
2533 LPSCARD_READERSTATEW rgReaderStates =
2534 (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2535 BOOL* states = calloc(cReaders, sizeof(BOOL));
2536
2537 if (!rgReaderStates || !states)
2538 goto fail;
2539
2540 status = ERROR_INVALID_DATA;
2541 for (UINT32 index = 0; index < cReaders; index++)
2542 {
2543 UINT32 ptr = UINT32_MAX;
2544 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2545
2546 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2547 goto fail;
2548
2549 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2550 {
2551 if (ptr != 0)
2552 goto fail;
2553 }
2554 /* Ignore nullptr length strings */
2555 states[index] = ptr != 0;
2556 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2557 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2558 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2559 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2560 {
2561 WLog_Print(log, WLOG_ERROR,
2562 "SCARD_READERSTATEW[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2563 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2564 goto fail;
2565 }
2566 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2567 }
2568
2569 for (UINT32 index = 0; index < cReaders; index++)
2570 {
2571 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2572
2573 /* Skip nullptr pointers */
2574 if (!states[index])
2575 continue;
2576
2577 status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2578 if (status != SCARD_S_SUCCESS)
2579 goto fail;
2580 }
2581
2582 *ppcReaders = rgReaderStates;
2583 free(states);
2584 return SCARD_S_SUCCESS;
2585fail:
2586 if (rgReaderStates)
2587 {
2588 for (UINT32 index = 0; index < cReaders; index++)
2589 {
2590 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2591 free(readerState->szReader);
2592 }
2593 }
2594 free(rgReaderStates);
2595 free(states);
2596 return status;
2597}
2598
2599/******************************************************************************/
2600/************************************* End Trace Functions ********************/
2601/******************************************************************************/
2602
2603LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2604{
2605 UINT32 ndrPtr = 0;
2606 UINT32 index = 0;
2607 UINT32 pbContextNdrPtr = 0;
2608
2609 WINPR_ASSERT(call);
2610 wLog* log = scard_log();
2611
2612 call->rgReaderStates = nullptr;
2613
2614 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2615 &pbContextNdrPtr);
2616 if (status != SCARD_S_SUCCESS)
2617 return status;
2618
2619 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2620 return STATUS_BUFFER_TOO_SMALL;
2621
2622 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2623 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2624 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2625 return ERROR_INVALID_DATA;
2626
2627 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2628 &(call->handles.hContext));
2629 if (status != SCARD_S_SUCCESS)
2630 return status;
2631
2632 if (ndrPtr)
2633 {
2634 status =
2635 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
2636 if (status != SCARD_S_SUCCESS)
2637 return status;
2638 }
2639 else
2640 {
2641 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2642 return SCARD_E_UNEXPECTED;
2643 }
2644
2645 smartcard_trace_get_status_change_a_call(log, call);
2646 return SCARD_S_SUCCESS;
2647}
2648
2649LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2650{
2651 UINT32 ndrPtr = 0;
2652 UINT32 index = 0;
2653 UINT32 pbContextNdrPtr = 0;
2654
2655 WINPR_ASSERT(call);
2656 wLog* log = scard_log();
2657 call->rgReaderStates = nullptr;
2658
2659 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2660 &pbContextNdrPtr);
2661 if (status != SCARD_S_SUCCESS)
2662 return status;
2663
2664 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2665 return STATUS_BUFFER_TOO_SMALL;
2666
2667 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2668 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2669 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2670 return ERROR_INVALID_DATA;
2671
2672 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2673 &(call->handles.hContext));
2674 if (status != SCARD_S_SUCCESS)
2675 return status;
2676
2677 if (ndrPtr)
2678 {
2679 status =
2680 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
2681 if (status != SCARD_S_SUCCESS)
2682 return status;
2683 }
2684 else
2685 {
2686 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2687 return SCARD_E_UNEXPECTED;
2688 }
2689
2690 smartcard_trace_get_status_change_w_call(log, call);
2691 return SCARD_S_SUCCESS;
2692}
2693
2694LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2695 BOOL unicode)
2696{
2697 WINPR_ASSERT(ret);
2698 wLog* log = scard_log();
2699
2700 LONG status = 0;
2701 DWORD cReaders = ret->cReaders;
2702 UINT32 index = 0;
2703
2704 smartcard_trace_get_status_change_return(log, ret, unicode);
2705 if (ret->ReturnCode != SCARD_S_SUCCESS)
2706 cReaders = 0;
2707 if (cReaders == SCARD_AUTOALLOCATE)
2708 cReaders = 0;
2709
2710 if (!Stream_EnsureRemainingCapacity(s, 4))
2711 return SCARD_E_NO_MEMORY;
2712
2713 Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2714 if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2715 return SCARD_E_NO_MEMORY;
2716 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2717 if (status != SCARD_S_SUCCESS)
2718 return status;
2719 return ret->ReturnCode;
2720}
2721
2722LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2723{
2724 UINT32 index = 0;
2725 UINT32 pbContextNdrPtr = 0;
2726
2727 wLog* log = scard_log();
2728
2729 WINPR_ASSERT(call);
2730 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2731 &pbContextNdrPtr);
2732 if (status != SCARD_S_SUCCESS)
2733 return status;
2734
2735 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2736 if (status != SCARD_S_SUCCESS)
2737 return status;
2738
2739 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2740 return STATUS_BUFFER_TOO_SMALL;
2741
2742 Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2743 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2744
2745 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2746 &(call->handles.hContext));
2747 if (status != SCARD_S_SUCCESS)
2748 return status;
2749
2750 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2751 if (status != SCARD_S_SUCCESS)
2752 return status;
2753
2754 return status;
2755}
2756
2757LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2758{
2759 WINPR_ASSERT(ret);
2760 wLog* log = scard_log();
2761 LONG status = 0;
2762 DWORD cbAtrLen = ret->cbAtrLen;
2763 UINT32 index = 0;
2764
2765 smartcard_trace_state_return(log, ret);
2766 if (ret->ReturnCode != SCARD_S_SUCCESS)
2767 cbAtrLen = 0;
2768 if (cbAtrLen == SCARD_AUTOALLOCATE)
2769 cbAtrLen = 0;
2770
2771 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2772 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2773 Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
2774 if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2775 return SCARD_E_NO_MEMORY;
2776 status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2777 if (status != SCARD_S_SUCCESS)
2778 return status;
2779 return ret->ReturnCode;
2780}
2781
2782LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2783{
2784 UINT32 index = 0;
2785 UINT32 pbContextNdrPtr = 0;
2786
2787 WINPR_ASSERT(call);
2788 wLog* log = scard_log();
2789
2790 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2791 &pbContextNdrPtr);
2792 if (status != SCARD_S_SUCCESS)
2793 return status;
2794
2795 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2796 if (status != SCARD_S_SUCCESS)
2797 return status;
2798
2799 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2800 return STATUS_BUFFER_TOO_SMALL;
2801
2802 Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
2803 Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
2804 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2805
2806 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2807 &(call->handles.hContext));
2808 if (status != SCARD_S_SUCCESS)
2809 return status;
2810
2811 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2812 if (status != SCARD_S_SUCCESS)
2813 return status;
2814
2815 smartcard_trace_status_call(log, call, unicode);
2816 return status;
2817}
2818
2819LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
2820{
2821 WINPR_ASSERT(ret);
2822 wLog* log = scard_log();
2823
2824 LONG status = 0;
2825 UINT32 index = 0;
2826 DWORD cBytes = ret->cBytes;
2827
2828 smartcard_trace_status_return(log, ret, unicode);
2829 if (ret->ReturnCode != SCARD_S_SUCCESS)
2830 cBytes = 0;
2831 if (cBytes == SCARD_AUTOALLOCATE)
2832 cBytes = 0;
2833
2834 if (!Stream_EnsureRemainingCapacity(s, 4))
2835 return SCARD_F_INTERNAL_ERROR;
2836
2837 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2838 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2839 return SCARD_E_NO_MEMORY;
2840
2841 if (!Stream_EnsureRemainingCapacity(s, 44))
2842 return SCARD_F_INTERNAL_ERROR;
2843
2844 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2845 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2846 Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
2847 Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
2848 status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
2849 if (status != SCARD_S_SUCCESS)
2850 return status;
2851 return ret->ReturnCode;
2852}
2853
2854LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
2855{
2856 WINPR_ASSERT(call);
2857 wLog* log = scard_log();
2858 UINT32 index = 0;
2859 UINT32 pbContextNdrPtr = 0;
2860
2861 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2862 &pbContextNdrPtr);
2863 if (status != SCARD_S_SUCCESS)
2864 return status;
2865
2866 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2867 if (status != SCARD_S_SUCCESS)
2868 return status;
2869
2870 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2871 return STATUS_BUFFER_TOO_SMALL;
2872
2873 Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
2874 Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
2875 Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
2876
2877 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2878 &(call->handles.hContext));
2879 if (status != SCARD_S_SUCCESS)
2880 return status;
2881
2882 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2883 if (status != SCARD_S_SUCCESS)
2884 return status;
2885
2886 smartcard_trace_get_attrib_call(log, call);
2887 return status;
2888}
2889
2890LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
2891 DWORD cbAttrCallLen)
2892{
2893 WINPR_ASSERT(ret);
2894 wLog* log = scard_log();
2895 LONG status = 0;
2896 DWORD cbAttrLen = 0;
2897 UINT32 index = 0;
2898 smartcard_trace_get_attrib_return(log, ret, dwAttrId);
2899
2900 if (!Stream_EnsureRemainingCapacity(s, 4))
2901 return SCARD_F_INTERNAL_ERROR;
2902
2903 cbAttrLen = ret->cbAttrLen;
2904 if (ret->ReturnCode != SCARD_S_SUCCESS)
2905 cbAttrLen = 0;
2906 if (cbAttrLen == SCARD_AUTOALLOCATE)
2907 cbAttrLen = 0;
2908
2909 if (ret->pbAttr)
2910 {
2911 if (cbAttrCallLen < cbAttrLen)
2912 cbAttrLen = cbAttrCallLen;
2913 }
2914 Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
2915 if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
2916 return SCARD_E_NO_MEMORY;
2917
2918 status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
2919 if (status != SCARD_S_SUCCESS)
2920 return status;
2921 return ret->ReturnCode;
2922}
2923
2924LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
2925{
2926 WINPR_ASSERT(call);
2927 wLog* log = scard_log();
2928
2929 UINT32 index = 0;
2930 UINT32 pvInBufferNdrPtr = 0;
2931 UINT32 pbContextNdrPtr = 0;
2932
2933 call->pvInBuffer = nullptr;
2934
2935 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2936 &pbContextNdrPtr);
2937 if (status != SCARD_S_SUCCESS)
2938 return status;
2939
2940 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2941 if (status != SCARD_S_SUCCESS)
2942 return status;
2943
2944 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
2945 return STATUS_BUFFER_TOO_SMALL;
2946
2947 Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
2948 Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */
2949 if (!smartcard_ndr_pointer_read(log, s, &index,
2950 &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
2951 return ERROR_INVALID_DATA;
2952 Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
2953 Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
2954
2955 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2956 &(call->handles.hContext));
2957 if (status != SCARD_S_SUCCESS)
2958 return status;
2959
2960 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2961 if (status != SCARD_S_SUCCESS)
2962 return status;
2963
2964 if (pvInBufferNdrPtr)
2965 {
2966 status =
2967 smartcard_ndr_read(log, s, &call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
2968 if (status != SCARD_S_SUCCESS)
2969 return status;
2970 }
2971
2972 smartcard_trace_control_call(log, call);
2973 return SCARD_S_SUCCESS;
2974}
2975
2976LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
2977{
2978 WINPR_ASSERT(ret);
2979 wLog* log = scard_log();
2980
2981 LONG status = 0;
2982 DWORD cbDataLen = ret->cbOutBufferSize;
2983 UINT32 index = 0;
2984
2985 smartcard_trace_control_return(log, ret);
2986 if (ret->ReturnCode != SCARD_S_SUCCESS)
2987 cbDataLen = 0;
2988 if (cbDataLen == SCARD_AUTOALLOCATE)
2989 cbDataLen = 0;
2990
2991 if (!Stream_EnsureRemainingCapacity(s, 4))
2992 return SCARD_F_INTERNAL_ERROR;
2993
2994 Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
2995 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
2996 return SCARD_E_NO_MEMORY;
2997
2998 status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
2999 if (status != SCARD_S_SUCCESS)
3000 return status;
3001 return ret->ReturnCode;
3002}
3003
3004LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
3005{
3006 UINT32 length = 0;
3007 BYTE* pbExtraBytes = nullptr;
3008 UINT32 pbExtraBytesNdrPtr = 0;
3009 UINT32 pbSendBufferNdrPtr = 0;
3010 UINT32 pioRecvPciNdrPtr = 0;
3011 SCardIO_Request ioSendPci;
3012 SCardIO_Request ioRecvPci;
3013 UINT32 index = 0;
3014 UINT32 pbContextNdrPtr = 0;
3015
3016 WINPR_ASSERT(call);
3017 wLog* log = scard_log();
3018
3019 call->pioSendPci = nullptr;
3020 call->pioRecvPci = nullptr;
3021 call->pbSendBuffer = nullptr;
3022
3023 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3024 &pbContextNdrPtr);
3025 if (status != SCARD_S_SUCCESS)
3026 return status;
3027
3028 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3029 if (status != SCARD_S_SUCCESS)
3030 return status;
3031
3032 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
3033 return STATUS_BUFFER_TOO_SMALL;
3034
3035 Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
3036 Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3037 if (!smartcard_ndr_pointer_read(log, s, &index,
3038 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3039 return ERROR_INVALID_DATA;
3040
3041 Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */
3042 if (!smartcard_ndr_pointer_read(log, s, &index,
3043 &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3044 return ERROR_INVALID_DATA;
3045
3046 if (!smartcard_ndr_pointer_read(log, s, &index,
3047 &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3048 return ERROR_INVALID_DATA;
3049
3050 Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3051 Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
3052
3053 if (ioSendPci.cbExtraBytes > 1024)
3054 {
3055 WLog_Print(log, WLOG_WARN,
3056 "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3057 ioSendPci.cbExtraBytes);
3058 return STATUS_INVALID_PARAMETER;
3059 }
3060
3061 if (call->cbSendLength > 66560)
3062 {
3063 WLog_Print(log, WLOG_WARN,
3064 "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3065 ioSendPci.cbExtraBytes);
3066 return STATUS_INVALID_PARAMETER;
3067 }
3068
3069 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3070 &(call->handles.hContext));
3071 if (status != SCARD_S_SUCCESS)
3072 return status;
3073
3074 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3075 if (status != SCARD_S_SUCCESS)
3076 return status;
3077
3078 if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3079 {
3080 WLog_Print(
3081 log, WLOG_WARN,
3082 "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3083 return STATUS_INVALID_PARAMETER;
3084 }
3085
3086 if (pbExtraBytesNdrPtr)
3087 {
3088 // TODO: Use unified pointer reading
3089 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3090 return STATUS_BUFFER_TOO_SMALL;
3091
3092 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3093
3094 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3095 return STATUS_BUFFER_TOO_SMALL;
3096
3097 ioSendPci.pbExtraBytes = Stream_Pointer(s);
3098 call->pioSendPci =
3099 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3100
3101 if (!call->pioSendPci)
3102 {
3103 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3104 return STATUS_NO_MEMORY;
3105 }
3106
3107 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3108 call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3109 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3110 Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3111 if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3112 return STATUS_INVALID_PARAMETER;
3113 }
3114 else
3115 {
3116 call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3117
3118 if (!call->pioSendPci)
3119 {
3120 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3121 return STATUS_NO_MEMORY;
3122 }
3123
3124 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3125 call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3126 }
3127
3128 if (pbSendBufferNdrPtr)
3129 {
3130 status =
3131 smartcard_ndr_read(log, s, &call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
3132 if (status != SCARD_S_SUCCESS)
3133 return status;
3134 }
3135
3136 if (pioRecvPciNdrPtr)
3137 {
3138 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3139 return STATUS_BUFFER_TOO_SMALL;
3140
3141 Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
3142 Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3143 if (!smartcard_ndr_pointer_read(log, s, &index,
3144 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3145 return ERROR_INVALID_DATA;
3146
3147 if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3148 {
3149 WLog_Print(
3150 log, WLOG_WARN,
3151 "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3152 return STATUS_INVALID_PARAMETER;
3153 }
3154
3155 if (pbExtraBytesNdrPtr)
3156 {
3157 // TODO: Unify ndr pointer reading
3158 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3159 return STATUS_BUFFER_TOO_SMALL;
3160
3161 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3162
3163 if (ioRecvPci.cbExtraBytes > 1024)
3164 {
3165 WLog_Print(log, WLOG_WARN,
3166 "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3167 " (max: 1024)",
3168 ioRecvPci.cbExtraBytes);
3169 return STATUS_INVALID_PARAMETER;
3170 }
3171
3172 if (length != ioRecvPci.cbExtraBytes)
3173 {
3174 WLog_Print(log, WLOG_WARN,
3175 "Transmit_Call unexpected length: Actual: %" PRIu32
3176 ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3177 length, ioRecvPci.cbExtraBytes);
3178 return STATUS_INVALID_PARAMETER;
3179 }
3180
3181 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3182 return STATUS_BUFFER_TOO_SMALL;
3183
3184 ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3185 call->pioRecvPci =
3186 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3187
3188 if (!call->pioRecvPci)
3189 {
3190 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3191 return STATUS_NO_MEMORY;
3192 }
3193
3194 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3195 call->pioRecvPci->cbPciLength =
3196 (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3197 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3198 Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3199 if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3200 return STATUS_INVALID_PARAMETER;
3201 }
3202 else
3203 {
3204 call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3205
3206 if (!call->pioRecvPci)
3207 {
3208 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3209 return STATUS_NO_MEMORY;
3210 }
3211
3212 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3213 call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3214 }
3215 }
3216
3217 smartcard_trace_transmit_call(log, call);
3218 return SCARD_S_SUCCESS;
3219}
3220
3221LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3222{
3223 WINPR_ASSERT(ret);
3224 wLog* log = scard_log();
3225
3226 LONG status = 0;
3227 UINT32 index = 0;
3228 LONG error = 0;
3229 UINT32 cbRecvLength = ret->cbRecvLength;
3230 UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3231
3232 smartcard_trace_transmit_return(log, ret);
3233
3234 if (!ret->pbRecvBuffer)
3235 cbRecvLength = 0;
3236
3237 if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3238 return SCARD_E_NO_MEMORY;
3239 if (!Stream_EnsureRemainingCapacity(s, 4))
3240 return SCARD_E_NO_MEMORY;
3241 Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3242 if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3243 return SCARD_E_NO_MEMORY;
3244
3245 if (ret->pioRecvPci)
3246 {
3247 UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3248 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3249
3250 if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3251 {
3252 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3253 return SCARD_F_INTERNAL_ERROR;
3254 }
3255
3256 Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3257 Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
3258 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3259 return SCARD_E_NO_MEMORY;
3260 error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3261 if (error)
3262 return error;
3263 }
3264
3265 status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3266 if (status != SCARD_S_SUCCESS)
3267 return status;
3268 return ret->ReturnCode;
3269}
3270
3271LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3272{
3273 UINT32 rgReaderStatesNdrPtr = 0;
3274 UINT32 rgAtrMasksNdrPtr = 0;
3275 UINT32 index = 0;
3276 UINT32 pbContextNdrPtr = 0;
3277
3278 WINPR_ASSERT(call);
3279 wLog* log = scard_log();
3280
3281 call->rgReaderStates = nullptr;
3282
3283 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3284 &pbContextNdrPtr);
3285 if (status != SCARD_S_SUCCESS)
3286 return status;
3287
3288 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3289 return STATUS_BUFFER_TOO_SMALL;
3290
3291 Stream_Read_UINT32(s, call->cAtrs);
3292 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3293 return ERROR_INVALID_DATA;
3294 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3295 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3296 return ERROR_INVALID_DATA;
3297
3298 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3299 &(call->handles.hContext));
3300 if (status != SCARD_S_SUCCESS)
3301 return status;
3302
3303 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3304 {
3305 WLog_Print(log, WLOG_WARN,
3306 "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3307 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3308 rgAtrMasksNdrPtr, call->cAtrs);
3309 return STATUS_INVALID_PARAMETER;
3310 }
3311
3312 if (rgAtrMasksNdrPtr)
3313 {
3314 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3315 if (status != SCARD_S_SUCCESS)
3316 return status;
3317 }
3318
3319 if (rgReaderStatesNdrPtr)
3320 {
3321 status =
3322 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3323 if (status != SCARD_S_SUCCESS)
3324 return status;
3325 }
3326
3327 smartcard_trace_locate_cards_by_atr_a_call(log, call);
3328 return SCARD_S_SUCCESS;
3329}
3330
3331LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3332{
3333 UINT32 sz1NdrPtr = 0;
3334 UINT32 sz2NdrPtr = 0;
3335 UINT32 index = 0;
3336 UINT32 pbContextNdrPtr = 0;
3337
3338 WINPR_ASSERT(call);
3339 wLog* log = scard_log();
3340
3341 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3342 &pbContextNdrPtr);
3343 if (status != SCARD_S_SUCCESS)
3344 return status;
3345
3346 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3347 return ERROR_INVALID_DATA;
3348 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3349 return ERROR_INVALID_DATA;
3350
3351 status =
3352 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3353 if (status != SCARD_S_SUCCESS)
3354 return status;
3355
3356 if (sz1NdrPtr)
3357 {
3358 status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3359 if (status != SCARD_S_SUCCESS)
3360 return status;
3361 }
3362 if (sz2NdrPtr)
3363 {
3364 status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3365 if (status != SCARD_S_SUCCESS)
3366 return status;
3367 }
3368 smartcard_trace_context_and_two_strings_a_call(log, call);
3369 return SCARD_S_SUCCESS;
3370}
3371
3372LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3373{
3374 UINT32 sz1NdrPtr = 0;
3375 UINT32 sz2NdrPtr = 0;
3376 UINT32 index = 0;
3377 UINT32 pbContextNdrPtr = 0;
3378
3379 WINPR_ASSERT(call);
3380 wLog* log = scard_log();
3381
3382 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3383 &pbContextNdrPtr);
3384 if (status != SCARD_S_SUCCESS)
3385 return status;
3386
3387 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3388 return ERROR_INVALID_DATA;
3389 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3390 return ERROR_INVALID_DATA;
3391
3392 status =
3393 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3394 if (status != SCARD_S_SUCCESS)
3395 return status;
3396
3397 if (sz1NdrPtr)
3398 {
3399 status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3400 if (status != SCARD_S_SUCCESS)
3401 return status;
3402 }
3403 if (sz2NdrPtr)
3404 {
3405 status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3406 if (status != SCARD_S_SUCCESS)
3407 return status;
3408 }
3409 smartcard_trace_context_and_two_strings_w_call(log, call);
3410 return SCARD_S_SUCCESS;
3411}
3412
3413LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3414{
3415 UINT32 sz1NdrPtr = 0;
3416 UINT32 sz2NdrPtr = 0;
3417 UINT32 index = 0;
3418 UINT32 pbContextNdrPtr = 0;
3419
3420 WINPR_ASSERT(call);
3421 wLog* log = scard_log();
3422
3423 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3424 &pbContextNdrPtr);
3425 if (status != SCARD_S_SUCCESS)
3426 return status;
3427
3428 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3429 return STATUS_BUFFER_TOO_SMALL;
3430
3431 Stream_Read_UINT32(s, call->cBytes);
3432 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3433 return ERROR_INVALID_DATA;
3434
3435 Stream_Read_UINT32(s, call->cReaders);
3436 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3437 return ERROR_INVALID_DATA;
3438
3439 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3440 &(call->handles.hContext));
3441 if (status != SCARD_S_SUCCESS)
3442 return status;
3443
3444 if (sz1NdrPtr)
3445 {
3446 status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, call->cBytes,
3447 NDR_PTR_SIMPLE);
3448 if (status != SCARD_S_SUCCESS)
3449 return status;
3450 }
3451 if (sz2NdrPtr)
3452 {
3453 status =
3454 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3455 if (status != SCARD_S_SUCCESS)
3456 return status;
3457 }
3458 smartcard_trace_locate_cards_a_call(log, call);
3459 return SCARD_S_SUCCESS;
3460}
3461
3462LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3463{
3464 UINT32 sz1NdrPtr = 0;
3465 UINT32 sz2NdrPtr = 0;
3466 UINT32 index = 0;
3467 UINT32 pbContextNdrPtr = 0;
3468
3469 WINPR_ASSERT(call);
3470 wLog* log = scard_log();
3471
3472 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3473 &pbContextNdrPtr);
3474 if (status != SCARD_S_SUCCESS)
3475 return status;
3476
3477 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3478 return STATUS_BUFFER_TOO_SMALL;
3479
3480 Stream_Read_UINT32(s, call->cBytes);
3481 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3482 return ERROR_INVALID_DATA;
3483
3484 Stream_Read_UINT32(s, call->cReaders);
3485 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3486 return ERROR_INVALID_DATA;
3487
3488 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3489 &(call->handles.hContext));
3490 if (status != SCARD_S_SUCCESS)
3491 return status;
3492
3493 if (sz1NdrPtr)
3494 {
3495 status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, call->cBytes,
3496 NDR_PTR_SIMPLE);
3497 if (status != SCARD_S_SUCCESS)
3498 return status;
3499 }
3500 if (sz2NdrPtr)
3501 {
3502 status =
3503 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3504 if (status != SCARD_S_SUCCESS)
3505 return status;
3506 }
3507 smartcard_trace_locate_cards_w_call(log, call);
3508 return SCARD_S_SUCCESS;
3509}
3510
3511LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3512{
3513 UINT32 index = 0;
3514 UINT32 ndrPtr = 0;
3515 UINT32 pbContextNdrPtr = 0;
3516
3517 WINPR_ASSERT(call);
3518 wLog* log = scard_log();
3519
3520 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3521 &pbContextNdrPtr);
3522 if (status != SCARD_S_SUCCESS)
3523 return status;
3524 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3525 if (status != SCARD_S_SUCCESS)
3526 return status;
3527
3528 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3529 return STATUS_BUFFER_TOO_SMALL;
3530 Stream_Read_UINT32(s, call->dwAttrId);
3531 Stream_Read_UINT32(s, call->cbAttrLen);
3532
3533 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3534 return ERROR_INVALID_DATA;
3535
3536 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3537 &(call->handles.hContext));
3538 if (status != SCARD_S_SUCCESS)
3539 return status;
3540
3541 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3542 if (status != SCARD_S_SUCCESS)
3543 return status;
3544
3545 if (ndrPtr)
3546 {
3547 size_t len = 0;
3548 status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3549 if (status != SCARD_S_SUCCESS)
3550 return status;
3551 if (call->cbAttrLen > len)
3552 call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3553 }
3554 else
3555 call->cbAttrLen = 0;
3556 smartcard_trace_set_attrib_call(log, call);
3557 return SCARD_S_SUCCESS;
3558}
3559
3560LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3561{
3562 UINT32 rgReaderStatesNdrPtr = 0;
3563 UINT32 rgAtrMasksNdrPtr = 0;
3564 UINT32 index = 0;
3565 UINT32 pbContextNdrPtr = 0;
3566
3567 WINPR_ASSERT(call);
3568 wLog* log = scard_log();
3569
3570 call->rgReaderStates = nullptr;
3571
3572 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3573 &pbContextNdrPtr);
3574 if (status != SCARD_S_SUCCESS)
3575 return status;
3576
3577 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3578 return STATUS_BUFFER_TOO_SMALL;
3579
3580 Stream_Read_UINT32(s, call->cAtrs);
3581 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3582 return ERROR_INVALID_DATA;
3583
3584 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3585 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3586 return ERROR_INVALID_DATA;
3587
3588 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3589 &(call->handles.hContext));
3590 if (status != SCARD_S_SUCCESS)
3591 return status;
3592
3593 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3594 {
3595 WLog_Print(log, WLOG_WARN,
3596 "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3597 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3598 rgAtrMasksNdrPtr, call->cAtrs);
3599 return STATUS_INVALID_PARAMETER;
3600 }
3601
3602 if (rgAtrMasksNdrPtr)
3603 {
3604 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3605 if (status != SCARD_S_SUCCESS)
3606 return status;
3607 }
3608
3609 if (rgReaderStatesNdrPtr)
3610 {
3611 status =
3612 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3613 if (status != SCARD_S_SUCCESS)
3614 return status;
3615 }
3616
3617 smartcard_trace_locate_cards_by_atr_w_call(log, call);
3618 return SCARD_S_SUCCESS;
3619}
3620
3621LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3622{
3623 UINT32 mszNdrPtr = 0;
3624 UINT32 contextNdrPtr = 0;
3625 UINT32 index = 0;
3626 UINT32 pbContextNdrPtr = 0;
3627
3628 WINPR_ASSERT(call);
3629 wLog* log = scard_log();
3630
3631 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3632 return ERROR_INVALID_DATA;
3633
3634 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3635 &index, &pbContextNdrPtr);
3636 if (status != SCARD_S_SUCCESS)
3637 return status;
3638
3639 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3640 return ERROR_INVALID_DATA;
3641
3642 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3643 return STATUS_BUFFER_TOO_SMALL;
3644 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3645 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3646 Stream_Read_UINT32(s, call->Common.cbDataLen);
3647
3648 call->szLookupName = nullptr;
3649 if (mszNdrPtr)
3650 {
3651 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3652 if (status != SCARD_S_SUCCESS)
3653 return status;
3654 }
3655
3656 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3657 &call->Common.handles.hContext);
3658 if (status != SCARD_S_SUCCESS)
3659 return status;
3660
3661 if (contextNdrPtr)
3662 {
3663 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3664 if (status != SCARD_S_SUCCESS)
3665 return status;
3666 }
3667 smartcard_trace_read_cache_a_call(log, call);
3668 return SCARD_S_SUCCESS;
3669}
3670
3671LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3672{
3673 UINT32 mszNdrPtr = 0;
3674 UINT32 contextNdrPtr = 0;
3675 UINT32 index = 0;
3676 UINT32 pbContextNdrPtr = 0;
3677
3678 WINPR_ASSERT(call);
3679 wLog* log = scard_log();
3680
3681 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3682 return ERROR_INVALID_DATA;
3683
3684 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3685 &index, &pbContextNdrPtr);
3686 if (status != SCARD_S_SUCCESS)
3687 return status;
3688
3689 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3690 return ERROR_INVALID_DATA;
3691
3692 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3693 return STATUS_BUFFER_TOO_SMALL;
3694 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3695 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3696 Stream_Read_UINT32(s, call->Common.cbDataLen);
3697
3698 call->szLookupName = nullptr;
3699 if (mszNdrPtr)
3700 {
3701 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3702 if (status != SCARD_S_SUCCESS)
3703 return status;
3704 }
3705
3706 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3707 &call->Common.handles.hContext);
3708 if (status != SCARD_S_SUCCESS)
3709 return status;
3710
3711 if (contextNdrPtr)
3712 {
3713 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3714 if (status != SCARD_S_SUCCESS)
3715 return status;
3716 }
3717 smartcard_trace_read_cache_w_call(log, call);
3718 return SCARD_S_SUCCESS;
3719}
3720
3721LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
3722{
3723 UINT32 mszNdrPtr = 0;
3724 UINT32 contextNdrPtr = 0;
3725 UINT32 pbDataNdrPtr = 0;
3726 UINT32 index = 0;
3727 UINT32 pbContextNdrPtr = 0;
3728
3729 WINPR_ASSERT(call);
3730 wLog* log = scard_log();
3731
3732 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3733 return ERROR_INVALID_DATA;
3734
3735 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3736 &index, &pbContextNdrPtr);
3737 if (status != SCARD_S_SUCCESS)
3738 return status;
3739
3740 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3741 return ERROR_INVALID_DATA;
3742
3743 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3744 return STATUS_BUFFER_TOO_SMALL;
3745
3746 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3747 Stream_Read_UINT32(s, call->Common.cbDataLen);
3748
3749 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3750 return ERROR_INVALID_DATA;
3751
3752 call->szLookupName = nullptr;
3753 if (mszNdrPtr)
3754 {
3755 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3756 if (status != SCARD_S_SUCCESS)
3757 return status;
3758 }
3759
3760 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3761 &call->Common.handles.hContext);
3762 if (status != SCARD_S_SUCCESS)
3763 return status;
3764
3765 call->Common.CardIdentifier = nullptr;
3766 if (contextNdrPtr)
3767 {
3768 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3769 if (status != SCARD_S_SUCCESS)
3770 return status;
3771 }
3772
3773 call->Common.pbData = nullptr;
3774 if (pbDataNdrPtr)
3775 {
3776 status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3777 NDR_PTR_SIMPLE);
3778 if (status != SCARD_S_SUCCESS)
3779 return status;
3780 }
3781 smartcard_trace_write_cache_a_call(log, call);
3782 return SCARD_S_SUCCESS;
3783}
3784
3785LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
3786{
3787 UINT32 mszNdrPtr = 0;
3788 UINT32 contextNdrPtr = 0;
3789 UINT32 pbDataNdrPtr = 0;
3790 UINT32 index = 0;
3791 UINT32 pbContextNdrPtr = 0;
3792
3793 WINPR_ASSERT(call);
3794 wLog* log = scard_log();
3795
3796 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3797 return ERROR_INVALID_DATA;
3798
3799 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3800 &index, &pbContextNdrPtr);
3801 if (status != SCARD_S_SUCCESS)
3802 return status;
3803
3804 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3805 return ERROR_INVALID_DATA;
3806
3807 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3808 return STATUS_BUFFER_TOO_SMALL;
3809 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3810 Stream_Read_UINT32(s, call->Common.cbDataLen);
3811
3812 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3813 return ERROR_INVALID_DATA;
3814
3815 call->szLookupName = nullptr;
3816 if (mszNdrPtr)
3817 {
3818 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3819 if (status != SCARD_S_SUCCESS)
3820 return status;
3821 }
3822
3823 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3824 &call->Common.handles.hContext);
3825 if (status != SCARD_S_SUCCESS)
3826 return status;
3827
3828 call->Common.CardIdentifier = nullptr;
3829 if (contextNdrPtr)
3830 {
3831 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3832 if (status != SCARD_S_SUCCESS)
3833 return status;
3834 }
3835
3836 call->Common.pbData = nullptr;
3837 if (pbDataNdrPtr)
3838 {
3839 status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3840 NDR_PTR_SIMPLE);
3841 if (status != SCARD_S_SUCCESS)
3842 return status;
3843 }
3844 smartcard_trace_write_cache_w_call(log, call);
3845 return status;
3846}
3847
3848LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
3849{
3850 WINPR_ASSERT(call);
3851 wLog* log = scard_log();
3852
3853 UINT32 index = 0;
3854 UINT32 pbContextNdrPtr = 0;
3855
3856 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3857 &pbContextNdrPtr);
3858 if (status != SCARD_S_SUCCESS)
3859 return status;
3860
3861 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3862 if (status != SCARD_S_SUCCESS)
3863 return status;
3864
3865 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3866 &(call->handles.hContext));
3867 if (status != SCARD_S_SUCCESS)
3868 {
3869 WLog_Print(log, WLOG_ERROR,
3870 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
3871 status);
3872 return status;
3873 }
3874
3875 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3876 if (status != SCARD_S_SUCCESS)
3877 WLog_Print(log, WLOG_ERROR,
3878 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
3879
3880 smartcard_trace_get_transmit_count_call(log, call);
3881 return status;
3882}
3883
3884LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
3885{
3886 WINPR_ASSERT(call);
3887 wLog* log = scard_log();
3888 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3889 &call->szReaderName);
3890}
3891
3892LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
3893{
3894 WINPR_ASSERT(call);
3895 wLog* log = scard_log();
3896 return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
3897}
3898
3899LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
3900{
3901 WINPR_ASSERT(call);
3902 wLog* log = scard_log();
3903 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
3904}
3905
3906LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
3907{
3908 WINPR_ASSERT(call);
3909 wLog* log = scard_log();
3910 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3911 &call->szReaderName);
3912}
3913
3914LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
3915{
3916 WINPR_ASSERT(ret);
3917 wLog* log = scard_log();
3918 smartcard_trace_device_type_id_return(log, ret);
3919
3920 if (!Stream_EnsureRemainingCapacity(s, 4))
3921 {
3922 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3923 return SCARD_F_INTERNAL_ERROR;
3924 }
3925
3926 Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
3927
3928 return ret->ReturnCode;
3929}
3930
3931LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
3932{
3933 WINPR_ASSERT(ret);
3934 wLog* log = scard_log();
3935
3936 LONG status = 0;
3937 DWORD cbDataLen = ret->cReaders;
3938 UINT32 index = 0;
3939
3940 smartcard_trace_locate_cards_return(log, ret);
3941 if (ret->ReturnCode != SCARD_S_SUCCESS)
3942 cbDataLen = 0;
3943 if (cbDataLen == SCARD_AUTOALLOCATE)
3944 cbDataLen = 0;
3945
3946 if (!Stream_EnsureRemainingCapacity(s, 4))
3947 {
3948 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3949 return SCARD_F_INTERNAL_ERROR;
3950 }
3951
3952 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3953 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3954 return SCARD_E_NO_MEMORY;
3955
3956 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
3957 if (status != SCARD_S_SUCCESS)
3958 return status;
3959 return ret->ReturnCode;
3960}
3961
3962LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
3963{
3964 WINPR_ASSERT(ret);
3965 wLog* log = scard_log();
3966
3967 LONG status = 0;
3968 UINT32 index = 0;
3969 DWORD cbDataLen = ret->cbDataLen;
3970 smartcard_trace_get_reader_icon_return(log, ret);
3971 if (ret->ReturnCode != SCARD_S_SUCCESS)
3972 cbDataLen = 0;
3973 if (cbDataLen == SCARD_AUTOALLOCATE)
3974 cbDataLen = 0;
3975
3976 if (!Stream_EnsureRemainingCapacity(s, 4))
3977 {
3978 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3979 return SCARD_F_INTERNAL_ERROR;
3980 }
3981
3982 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3983 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3984 return SCARD_E_NO_MEMORY;
3985
3986 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3987 if (status != SCARD_S_SUCCESS)
3988 return status;
3989 return ret->ReturnCode;
3990}
3991
3992LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* call)
3993{
3994 WINPR_ASSERT(call);
3995 wLog* log = scard_log();
3996
3997 smartcard_trace_get_transmit_count_return(log, call);
3998
3999 if (!Stream_EnsureRemainingCapacity(s, 4))
4000 {
4001 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4002 return SCARD_F_INTERNAL_ERROR;
4003 }
4004
4005 Stream_Write_UINT32(s, call->cTransmitCount); /* cBytes (4 cbDataLen) */
4006
4007 return call->ReturnCode;
4008}
4009
4010LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
4011{
4012 WINPR_ASSERT(ret);
4013 wLog* log = scard_log();
4014
4015 LONG status = 0;
4016 UINT32 index = 0;
4017 DWORD cbDataLen = ret->cbDataLen;
4018 smartcard_trace_read_cache_return(log, ret);
4019 if (ret->ReturnCode != SCARD_S_SUCCESS)
4020 cbDataLen = 0;
4021
4022 if (cbDataLen == SCARD_AUTOALLOCATE)
4023 cbDataLen = 0;
4024
4025 if (!Stream_EnsureRemainingCapacity(s, 4))
4026 {
4027 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4028 return SCARD_F_INTERNAL_ERROR;
4029 }
4030
4031 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4032 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4033 return SCARD_E_NO_MEMORY;
4034
4035 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4036 if (status != SCARD_S_SUCCESS)
4037 return status;
4038 return ret->ReturnCode;
4039}
Definition wtypes.h:263