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