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