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