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