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