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