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 *ppbContextNdrPtr = pbContextNdrPtr;
1903 return SCARD_S_SUCCESS;
1904}
1905
1906LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1907 const REDIR_SCARDCONTEXT* context, DWORD* index)
1908{
1909 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1910
1911 WINPR_ASSERT(context);
1912 if (context->cbContext != 0)
1913 {
1914 Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1915 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1916 *index = *index + 1;
1917 }
1918 else
1919 Stream_Zero(s, 8);
1920
1921 return SCARD_S_SUCCESS;
1922}
1923
1924LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1925 WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1926 REDIR_SCARDCONTEXT* context)
1927{
1928 UINT32 length = 0;
1929
1930 WINPR_ASSERT(context);
1931
1932 if (context->cbContext == 0)
1933 return SCARD_S_SUCCESS;
1934
1935 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1936 return STATUS_BUFFER_TOO_SMALL;
1937
1938 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1939
1940 if (length != context->cbContext)
1941 {
1942 WLog_Print(log, WLOG_WARN,
1943 "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1944 length, context->cbContext);
1945 return STATUS_INVALID_PARAMETER;
1946 }
1947
1948 const LONG status = smartcard_context_supported(log, context->cbContext);
1949 if (status != SCARD_S_SUCCESS)
1950 return status;
1951
1952 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1953 return STATUS_BUFFER_TOO_SMALL;
1954
1955 if (context->cbContext)
1956 Stream_Read(s, &(context->pbContext), context->cbContext);
1957 else
1958 ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1959
1960 return SCARD_S_SUCCESS;
1961}
1962
1963LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1964 const REDIR_SCARDCONTEXT* context)
1965{
1966 WINPR_ASSERT(context);
1967
1968 if (context->cbContext == 0)
1969 return SCARD_S_SUCCESS;
1970
1971 Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1972 Stream_Write(s, &(context->pbContext), context->cbContext);
1973
1974 return SCARD_S_SUCCESS;
1975}
1976
1977LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
1978 UINT32* index, const char* file, const char* function,
1979 size_t line)
1980{
1981 UINT32 pbHandleNdrPtr = 0;
1982
1983 WINPR_ASSERT(handle);
1984 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1985
1986 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1987 return STATUS_BUFFER_TOO_SMALL;
1988
1989 Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1990
1991 if (!smartcard_ndr_pointer_read_(log, s, index, &pbHandleNdrPtr, file, function, line))
1992 return ERROR_INVALID_DATA;
1993
1994 if (((handle->cbHandle == 0) && pbHandleNdrPtr) ||
1995 ((handle->cbHandle != 0) && !pbHandleNdrPtr))
1996 {
1997 WLog_Print(log, WLOG_WARN,
1998 "REDIR_SCARDHANDLE cbHandle (%" PRIu32 ") pbHandleNdrPtr (%" PRIu32
1999 ") inconsistency",
2000 handle->cbHandle, pbHandleNdrPtr);
2001 return STATUS_INVALID_PARAMETER;
2002 }
2003
2004 return SCARD_S_SUCCESS;
2005}
2006
2007LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2008 const REDIR_SCARDHANDLE* handle, DWORD* index)
2009{
2010 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
2011
2012 WINPR_ASSERT(handle);
2013 if (handle->cbHandle != 0)
2014 {
2015 Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
2016 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
2017 *index = *index + 1;
2018 }
2019 else
2020 Stream_Zero(s, 8);
2021 return SCARD_S_SUCCESS;
2022}
2023
2024LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
2025{
2026 UINT32 length = 0;
2027
2028 WINPR_ASSERT(handle);
2029
2030 if (handle->cbHandle == 0)
2031 return SCARD_S_SUCCESS;
2032
2033 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2034 return STATUS_BUFFER_TOO_SMALL;
2035
2036 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
2037
2038 if (length != handle->cbHandle)
2039 {
2040 WLog_Print(log, WLOG_WARN,
2041 "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
2042 handle->cbHandle);
2043 return STATUS_INVALID_PARAMETER;
2044 }
2045
2046 if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
2047 {
2048 WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
2049 handle->cbHandle);
2050 return STATUS_INVALID_PARAMETER;
2051 }
2052
2053 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
2054 return STATUS_BUFFER_TOO_SMALL;
2055
2056 if (handle->cbHandle)
2057 Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
2058
2059 return SCARD_S_SUCCESS;
2060}
2061
2062LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
2063 const REDIR_SCARDHANDLE* handle)
2064{
2065 WINPR_ASSERT(handle);
2066
2067 if (handle->cbHandle == 0)
2068 return SCARD_S_SUCCESS;
2069
2070 Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
2071 Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
2072
2073 return SCARD_S_SUCCESS;
2074}
2075
2076LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
2077{
2078 WINPR_ASSERT(call);
2079 wLog* log = scard_log();
2080
2081 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2082 return STATUS_BUFFER_TOO_SMALL;
2083
2084 Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2085 smartcard_trace_establish_context_call(log, call);
2086 return SCARD_S_SUCCESS;
2087}
2088
2089LONG smartcard_pack_establish_context_call(wStream* s, const EstablishContext_Call* call)
2090{
2091 WINPR_ASSERT(call);
2092 wLog* log = scard_log();
2093
2094 smartcard_trace_establish_context_call(log, call);
2095
2096 if (!Stream_EnsureRemainingCapacity(s, 4))
2097 return SCARD_E_NO_MEMORY;
2098
2099 Stream_Write_UINT32(s, call->dwScope);
2100
2101 return SCARD_S_SUCCESS;
2102}
2103
2104LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2105{
2106 WINPR_ASSERT(ret);
2107 wLog* log = scard_log();
2108 LONG status = 0;
2109 DWORD index = 0;
2110
2111 smartcard_trace_establish_context_return(log, ret);
2112 if (ret->ReturnCode != SCARD_S_SUCCESS)
2113 return ret->ReturnCode;
2114
2115 status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2116 if (status != SCARD_S_SUCCESS)
2117 return status;
2118
2119 return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2120}
2121
2122LONG smartcard_unpack_establish_context_return(wStream* s, EstablishContext_Return* ret)
2123{
2124 WINPR_ASSERT(ret);
2125 wLog* log = scard_log();
2126 UINT32 index = 0;
2127 UINT32 pbContextNdrPtr = 0;
2128
2129 LONG status =
2130 smartcard_unpack_redir_scard_context(log, s, &(ret->hContext), &index, &pbContextNdrPtr);
2131 if (status != SCARD_S_SUCCESS)
2132 return status;
2133
2134 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &(ret->hContext));
2135 if (status != SCARD_S_SUCCESS)
2136 return status;
2137
2138 smartcard_trace_establish_context_return(log, ret);
2139 return SCARD_S_SUCCESS;
2140}
2141
2142LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2143{
2144 UINT32 index = 0;
2145 UINT32 pbContextNdrPtr = 0;
2146 wLog* log = scard_log();
2147
2148 WINPR_ASSERT(call);
2149 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2150 &pbContextNdrPtr);
2151 if (status != SCARD_S_SUCCESS)
2152 return status;
2153
2154 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2155 &(call->handles.hContext));
2156 if (status != SCARD_S_SUCCESS)
2157 WLog_Print(log, WLOG_ERROR,
2158 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2159 status);
2160
2161 smartcard_trace_context_call(log, call, name);
2162 return status;
2163}
2164
2165LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2166{
2167 UINT32 index = 0;
2168 UINT32 pbContextNdrPtr = 0;
2169 wLog* log = scard_log();
2170
2171 WINPR_ASSERT(call);
2172 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2173 &pbContextNdrPtr);
2174
2175 if (status != SCARD_S_SUCCESS)
2176 return status;
2177
2178 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2179 return STATUS_BUFFER_TOO_SMALL;
2180
2181 Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2182 Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */
2183 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2184 &(call->handles.hContext));
2185
2186 if (status != SCARD_S_SUCCESS)
2187 return status;
2188
2189 smartcard_trace_list_reader_groups_call(log, call, unicode);
2190 return SCARD_S_SUCCESS;
2191}
2192
2193LONG smartcard_pack_list_reader_groups_call(wStream* s, const ListReaderGroups_Call* call,
2194 BOOL unicode)
2195{
2196 WINPR_ASSERT(call);
2197 wLog* log = scard_log();
2198 DWORD index = 0;
2199
2200 smartcard_trace_list_reader_groups_call(log, call, unicode);
2201
2202 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2203 if (status != SCARD_S_SUCCESS)
2204 return status;
2205
2206 if (!Stream_EnsureRemainingCapacity(s, 8))
2207 return SCARD_E_NO_MEMORY;
2208
2209 Stream_Write_INT32(s, call->fmszGroupsIsNULL);
2210 Stream_Write_UINT32(s, call->cchGroups);
2211
2212 return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2213}
2214
2215LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2216 BOOL unicode)
2217{
2218 WINPR_ASSERT(ret);
2219 wLog* log = scard_log();
2220 LONG status = 0;
2221 DWORD cBytes = ret->cBytes;
2222 UINT32 index = 0;
2223
2224 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2225 if (ret->ReturnCode != SCARD_S_SUCCESS)
2226 cBytes = 0;
2227 if (cBytes == SCARD_AUTOALLOCATE)
2228 cBytes = 0;
2229
2230 if (!Stream_EnsureRemainingCapacity(s, 4))
2231 return SCARD_E_NO_MEMORY;
2232
2233 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2234 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2235 return SCARD_E_NO_MEMORY;
2236
2237 status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2238 if (status != SCARD_S_SUCCESS)
2239 return status;
2240 return ret->ReturnCode;
2241}
2242
2243LONG smartcard_unpack_list_reader_groups_return(wStream* s, ListReaderGroups_Return* ret,
2244 BOOL unicode)
2245{
2246 WINPR_ASSERT(ret);
2247 wLog* log = scard_log();
2248 UINT32 index = 0;
2249 UINT32 mszNdrPtr = 0;
2250
2251 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2252 return STATUS_BUFFER_TOO_SMALL;
2253
2254 const UINT32 cBytes = Stream_Get_UINT32(s);
2255
2256 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
2257 return ERROR_INVALID_DATA;
2258
2259 if (mszNdrPtr)
2260 {
2261 LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2262 if (status != SCARD_S_SUCCESS)
2263 return status;
2264 ret->cBytes = cBytes;
2265 }
2266
2267 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2268 return SCARD_S_SUCCESS;
2269}
2270
2271LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2272{
2273 UINT32 index = 0;
2274 UINT32 mszGroupsNdrPtr = 0;
2275 UINT32 pbContextNdrPtr = 0;
2276 wLog* log = scard_log();
2277
2278 WINPR_ASSERT(call);
2279 call->mszGroups = nullptr;
2280
2281 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2282 &pbContextNdrPtr);
2283 if (status != SCARD_S_SUCCESS)
2284 return status;
2285
2286 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2287 return STATUS_BUFFER_TOO_SMALL;
2288
2289 const UINT32 cBytes = Stream_Get_UINT32(s);
2290 if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2291 return ERROR_INVALID_DATA;
2292
2293 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2294 return STATUS_BUFFER_TOO_SMALL;
2295 Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2296 Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */
2297
2298 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2299 &(call->handles.hContext));
2300 if (status != SCARD_S_SUCCESS)
2301 return status;
2302
2303 if (mszGroupsNdrPtr)
2304 {
2305 status = smartcard_ndr_read(log, s, &call->mszGroups, cBytes, 1, NDR_PTR_SIMPLE);
2306 if (status != SCARD_S_SUCCESS)
2307 return status;
2308 call->cBytes = cBytes;
2309 }
2310
2311 smartcard_trace_list_readers_call(log, call, unicode);
2312 return SCARD_S_SUCCESS;
2313}
2314
2315LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2316{
2317 WINPR_ASSERT(ret);
2318 wLog* log = scard_log();
2319 LONG status = 0;
2320 UINT32 index = 0;
2321 UINT32 size = ret->cBytes;
2322
2323 smartcard_trace_list_readers_return(log, ret, unicode);
2324 if (ret->ReturnCode != SCARD_S_SUCCESS)
2325 size = 0;
2326
2327 if (!Stream_EnsureRemainingCapacity(s, 4))
2328 {
2329 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2330 return SCARD_F_INTERNAL_ERROR;
2331 }
2332
2333 Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2334 if (!smartcard_ndr_pointer_write(s, &index, size))
2335 return SCARD_E_NO_MEMORY;
2336
2337 status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2338 if (status != SCARD_S_SUCCESS)
2339 return status;
2340 return ret->ReturnCode;
2341}
2342
2343static LONG smartcard_unpack_connect_common(wLog* log, wStream* s, Connect_Common_Call* common,
2344 UINT32* index, UINT32* ppbContextNdrPtr)
2345{
2346 WINPR_ASSERT(common);
2347 LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2348 ppbContextNdrPtr);
2349 if (status != SCARD_S_SUCCESS)
2350 return status;
2351
2352 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2353 return STATUS_BUFFER_TOO_SMALL;
2354
2355 Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
2356 Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2357 return SCARD_S_SUCCESS;
2358}
2359
2360LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2361{
2362 LONG status = 0;
2363 UINT32 index = 0;
2364 UINT32 pbContextNdrPtr = 0;
2365
2366 WINPR_ASSERT(call);
2367 wLog* log = scard_log();
2368
2369 call->szReader = nullptr;
2370
2371 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2372 return ERROR_INVALID_DATA;
2373
2374 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2375 if (status != SCARD_S_SUCCESS)
2376 {
2377 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2378 status);
2379 return status;
2380 }
2381
2382 status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2383 if (status != SCARD_S_SUCCESS)
2384 return status;
2385
2386 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2387 &(call->Common.handles.hContext));
2388 if (status != SCARD_S_SUCCESS)
2389 WLog_Print(log, WLOG_ERROR,
2390 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2391 status);
2392
2393 smartcard_trace_connect_a_call(log, call);
2394 return status;
2395}
2396
2397LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2398{
2399 LONG status = 0;
2400 UINT32 index = 0;
2401 UINT32 pbContextNdrPtr = 0;
2402
2403 WINPR_ASSERT(call);
2404 wLog* log = scard_log();
2405 call->szReader = nullptr;
2406
2407 if (!smartcard_ndr_pointer_read(log, s, &index, nullptr))
2408 return ERROR_INVALID_DATA;
2409
2410 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2411 if (status != SCARD_S_SUCCESS)
2412 {
2413 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2414 status);
2415 return status;
2416 }
2417
2418 status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2419 if (status != SCARD_S_SUCCESS)
2420 return status;
2421
2422 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2423 &(call->Common.handles.hContext));
2424 if (status != SCARD_S_SUCCESS)
2425 WLog_Print(log, WLOG_ERROR,
2426 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2427 status);
2428
2429 smartcard_trace_connect_w_call(log, call);
2430 return status;
2431}
2432
2433LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2434{
2435 LONG status = 0;
2436 DWORD index = 0;
2437
2438 WINPR_ASSERT(ret);
2439 wLog* log = scard_log();
2440 smartcard_trace_connect_return(log, ret);
2441
2442 status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2443 if (status != SCARD_S_SUCCESS)
2444 return status;
2445
2446 status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2447 if (status != SCARD_S_SUCCESS)
2448 return status;
2449
2450 if (!Stream_EnsureRemainingCapacity(s, 4))
2451 return SCARD_E_NO_MEMORY;
2452
2453 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2454 status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2455 if (status != SCARD_S_SUCCESS)
2456 return status;
2457 return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2458}
2459
2460LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2461{
2462 UINT32 index = 0;
2463 UINT32 pbContextNdrPtr = 0;
2464
2465 WINPR_ASSERT(call);
2466 wLog* log = scard_log();
2467 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2468 &pbContextNdrPtr);
2469 if (status != SCARD_S_SUCCESS)
2470 return status;
2471
2472 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2473 if (status != SCARD_S_SUCCESS)
2474 return status;
2475
2476 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2477 return STATUS_BUFFER_TOO_SMALL;
2478
2479 Stream_Read_UINT32(s, call->dwShareMode); /* dwShareMode (4 bytes) */
2480 Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2481 Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */
2482
2483 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2484 &(call->handles.hContext));
2485 if (status != SCARD_S_SUCCESS)
2486 {
2487 WLog_Print(log, WLOG_ERROR,
2488 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2489 status);
2490 return status;
2491 }
2492
2493 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2494 if (status != SCARD_S_SUCCESS)
2495 WLog_Print(log, WLOG_ERROR,
2496 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2497
2498 smartcard_trace_reconnect_call(log, call);
2499 return status;
2500}
2501
2502LONG smartcard_pack_reconnect_call(wStream* s, const Reconnect_Call* call)
2503{
2504 WINPR_ASSERT(call);
2505 wLog* log = scard_log();
2506 DWORD index = 0;
2507
2508 smartcard_trace_reconnect_call(log, call);
2509
2510 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
2511 if (status != SCARD_S_SUCCESS)
2512 return status;
2513
2514 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
2515 if (status != SCARD_S_SUCCESS)
2516 return status;
2517
2518 if (!Stream_EnsureRemainingCapacity(s, 12))
2519 return SCARD_E_NO_MEMORY;
2520
2521 Stream_Write_UINT32(s, call->dwShareMode);
2522 Stream_Write_UINT32(s, call->dwPreferredProtocols);
2523 Stream_Write_UINT32(s, call->dwInitialization);
2524
2525 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
2526 if (status != SCARD_S_SUCCESS)
2527 return status;
2528
2529 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
2530}
2531
2532LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2533{
2534 WINPR_ASSERT(ret);
2535 wLog* log = scard_log();
2536 smartcard_trace_reconnect_return(log, ret);
2537
2538 if (!Stream_EnsureRemainingCapacity(s, 4))
2539 return SCARD_E_NO_MEMORY;
2540 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2541 return ret->ReturnCode;
2542}
2543
2544LONG smartcard_unpack_reconnect_return(wStream* s, Reconnect_Return* ret)
2545{
2546 WINPR_ASSERT(ret);
2547 wLog* log = scard_log();
2548
2549 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2550 return STATUS_BUFFER_TOO_SMALL;
2551
2552 Stream_Read_UINT32(s, ret->dwActiveProtocol);
2553
2554 smartcard_trace_reconnect_return(log, ret);
2555 return SCARD_S_SUCCESS;
2556}
2557
2558LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2559 const char* name)
2560{
2561 UINT32 index = 0;
2562 UINT32 pbContextNdrPtr = 0;
2563
2564 WINPR_ASSERT(call);
2565 wLog* log = scard_log();
2566
2567 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2568 &pbContextNdrPtr);
2569 if (status != SCARD_S_SUCCESS)
2570 return status;
2571
2572 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2573 if (status != SCARD_S_SUCCESS)
2574 return status;
2575
2576 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2577 return STATUS_BUFFER_TOO_SMALL;
2578
2579 Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2580
2581 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2582 &(call->handles.hContext));
2583 if (status != SCARD_S_SUCCESS)
2584 return status;
2585
2586 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2587 if (status != SCARD_S_SUCCESS)
2588 return status;
2589
2590 smartcard_trace_hcard_and_disposition_call(log, call, name);
2591 return status;
2592}
2593
2594static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2595{
2596 WINPR_ASSERT(call);
2597
2598 if (!WLog_IsLevelActive(log, g_LogLevel))
2599 return;
2600
2601 WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2602 smartcard_log_context(log, &call->handles.hContext);
2603
2604 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2605 call->cReaders);
2606
2607 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2608
2609 WLog_Print(log, g_LogLevel, "}");
2610}
2611
2612static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2613 UINT32 cReaders, UINT32* ptrIndex)
2614{
2615 LONG status = SCARD_E_NO_MEMORY;
2616
2617 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2618 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2619 return status;
2620
2621 const UINT32 len = Stream_Get_UINT32(s);
2622 if (len != cReaders)
2623 {
2624 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2625 return status;
2626 }
2627
2628 LPSCARD_READERSTATEA rgReaderStates =
2629 (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2630 BOOL* states = calloc(cReaders, sizeof(BOOL));
2631 if (!rgReaderStates || !states)
2632 goto fail;
2633 status = ERROR_INVALID_DATA;
2634
2635 for (UINT32 index = 0; index < cReaders; index++)
2636 {
2637 UINT32 ptr = UINT32_MAX;
2638 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2639
2640 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2641 goto fail;
2642
2643 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2644 {
2645 if (ptr != 0)
2646 goto fail;
2647 }
2648 /* Ignore nullptr length strings */
2649 states[index] = ptr != 0;
2650 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2651 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2652 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2653 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2654 {
2655 WLog_Print(log, WLOG_ERROR,
2656 "SCARD_READERSTATEA[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2657 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2658 goto fail;
2659 }
2660 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2661 }
2662
2663 for (UINT32 index = 0; index < cReaders; index++)
2664 {
2665 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2666
2667 /* Ignore empty strings */
2668 if (!states[index])
2669 continue;
2670 status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2671 if (status != SCARD_S_SUCCESS)
2672 goto fail;
2673 }
2674
2675 *ppcReaders = rgReaderStates;
2676 free(states);
2677 return SCARD_S_SUCCESS;
2678fail:
2679 if (rgReaderStates)
2680 {
2681 for (UINT32 index = 0; index < cReaders; index++)
2682 {
2683 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2684 free(readerState->szReader);
2685 }
2686 }
2687 free(rgReaderStates);
2688 free(states);
2689 return status;
2690}
2691
2692static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2693 UINT32 cReaders, UINT32* ptrIndex)
2694{
2695 LONG status = SCARD_E_NO_MEMORY;
2696
2697 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2698 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2699 return status;
2700
2701 const UINT32 len = Stream_Get_UINT32(s);
2702 if (len != cReaders)
2703 {
2704 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2705 return status;
2706 }
2707
2708 LPSCARD_READERSTATEW rgReaderStates =
2709 (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2710 BOOL* states = calloc(cReaders, sizeof(BOOL));
2711
2712 if (!rgReaderStates || !states)
2713 goto fail;
2714
2715 status = ERROR_INVALID_DATA;
2716 for (UINT32 index = 0; index < cReaders; index++)
2717 {
2718 UINT32 ptr = UINT32_MAX;
2719 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2720
2721 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2722 goto fail;
2723
2724 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2725 {
2726 if (ptr != 0)
2727 goto fail;
2728 }
2729 /* Ignore nullptr length strings */
2730 states[index] = ptr != 0;
2731 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2732 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2733 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2734 if (readerState->cbAtr > ARRAYSIZE(readerState->rgbAtr))
2735 {
2736 WLog_Print(log, WLOG_ERROR,
2737 "SCARD_READERSTATEW[%" PRIu32 "]::cbAtr %" PRIu32 " exceeds %" PRIuz, index,
2738 readerState->cbAtr, (size_t)ARRAYSIZE(readerState->rgbAtr));
2739 goto fail;
2740 }
2741 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2742 }
2743
2744 for (UINT32 index = 0; index < cReaders; index++)
2745 {
2746 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2747
2748 /* Skip nullptr pointers */
2749 if (!states[index])
2750 continue;
2751
2752 status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2753 if (status != SCARD_S_SUCCESS)
2754 goto fail;
2755 }
2756
2757 *ppcReaders = rgReaderStates;
2758 free(states);
2759 return SCARD_S_SUCCESS;
2760fail:
2761 if (rgReaderStates)
2762 {
2763 for (UINT32 index = 0; index < cReaders; index++)
2764 {
2765 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2766 free(readerState->szReader);
2767 }
2768 }
2769 free(rgReaderStates);
2770 free(states);
2771 return status;
2772}
2773
2774/******************************************************************************/
2775/************************************* End Trace Functions ********************/
2776/******************************************************************************/
2777
2778LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2779{
2780 UINT32 ndrPtr = 0;
2781 UINT32 index = 0;
2782 UINT32 pbContextNdrPtr = 0;
2783
2784 WINPR_ASSERT(call);
2785 wLog* log = scard_log();
2786
2787 call->rgReaderStates = nullptr;
2788
2789 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2790 &pbContextNdrPtr);
2791 if (status != SCARD_S_SUCCESS)
2792 return status;
2793
2794 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2795 return STATUS_BUFFER_TOO_SMALL;
2796
2797 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2798 const DWORD cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2799 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2800 return ERROR_INVALID_DATA;
2801
2802 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2803 &(call->handles.hContext));
2804 if (status != SCARD_S_SUCCESS)
2805 return status;
2806
2807 if (ndrPtr)
2808 {
2809 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
2810 if (status != SCARD_S_SUCCESS)
2811 return status;
2812 call->cReaders = cReaders;
2813 }
2814 else
2815 {
2816 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2817 return SCARD_E_UNEXPECTED;
2818 }
2819
2820 smartcard_trace_get_status_change_a_call(log, call);
2821 return SCARD_S_SUCCESS;
2822}
2823
2824LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2825{
2826 UINT32 ndrPtr = 0;
2827 UINT32 index = 0;
2828 UINT32 pbContextNdrPtr = 0;
2829
2830 WINPR_ASSERT(call);
2831 wLog* log = scard_log();
2832 call->rgReaderStates = nullptr;
2833
2834 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2835 &pbContextNdrPtr);
2836 if (status != SCARD_S_SUCCESS)
2837 return status;
2838
2839 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2840 return STATUS_BUFFER_TOO_SMALL;
2841
2842 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2843 const DWORD cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
2844 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2845 return ERROR_INVALID_DATA;
2846
2847 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2848 &(call->handles.hContext));
2849 if (status != SCARD_S_SUCCESS)
2850 return status;
2851
2852 if (ndrPtr)
2853 {
2854 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
2855 if (status != SCARD_S_SUCCESS)
2856 return status;
2857 call->cReaders = cReaders;
2858 }
2859 else
2860 {
2861 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2862 return SCARD_E_UNEXPECTED;
2863 }
2864
2865 smartcard_trace_get_status_change_w_call(log, call);
2866 return SCARD_S_SUCCESS;
2867}
2868
2869LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2870 BOOL unicode)
2871{
2872 WINPR_ASSERT(ret);
2873 wLog* log = scard_log();
2874
2875 LONG status = 0;
2876 DWORD cReaders = ret->cReaders;
2877 UINT32 index = 0;
2878
2879 smartcard_trace_get_status_change_return(log, ret, unicode);
2880 if ((ret->ReturnCode != SCARD_S_SUCCESS) && (ret->ReturnCode != SCARD_E_TIMEOUT))
2881 cReaders = 0;
2882 if (cReaders == SCARD_AUTOALLOCATE)
2883 cReaders = 0;
2884
2885 if (!Stream_EnsureRemainingCapacity(s, 4))
2886 return SCARD_E_NO_MEMORY;
2887
2888 Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2889 if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2890 return SCARD_E_NO_MEMORY;
2891 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2892 if (status != SCARD_S_SUCCESS)
2893 return status;
2894 return ret->ReturnCode;
2895}
2896
2897LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2898{
2899 UINT32 index = 0;
2900 UINT32 pbContextNdrPtr = 0;
2901
2902 wLog* log = scard_log();
2903
2904 WINPR_ASSERT(call);
2905 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2906 &pbContextNdrPtr);
2907 if (status != SCARD_S_SUCCESS)
2908 return status;
2909
2910 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2911 if (status != SCARD_S_SUCCESS)
2912 return status;
2913
2914 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2915 return STATUS_BUFFER_TOO_SMALL;
2916
2917 Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2918 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2919
2920 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2921 &(call->handles.hContext));
2922 if (status != SCARD_S_SUCCESS)
2923 return status;
2924
2925 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2926 if (status != SCARD_S_SUCCESS)
2927 return status;
2928
2929 return status;
2930}
2931
2932LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2933{
2934 WINPR_ASSERT(ret);
2935 wLog* log = scard_log();
2936 LONG status = 0;
2937 DWORD cbAtrLen = ret->cbAtrLen;
2938 UINT32 index = 0;
2939
2940 smartcard_trace_state_return(log, ret);
2941 if (ret->ReturnCode != SCARD_S_SUCCESS)
2942 cbAtrLen = 0;
2943 if (cbAtrLen == SCARD_AUTOALLOCATE)
2944 cbAtrLen = 0;
2945
2946 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2947 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2948 Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
2949 if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2950 return SCARD_E_NO_MEMORY;
2951 status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2952 if (status != SCARD_S_SUCCESS)
2953 return status;
2954 return ret->ReturnCode;
2955}
2956
2957LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2958{
2959 UINT32 index = 0;
2960 UINT32 pbContextNdrPtr = 0;
2961
2962 WINPR_ASSERT(call);
2963 wLog* log = scard_log();
2964
2965 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2966 &pbContextNdrPtr);
2967 if (status != SCARD_S_SUCCESS)
2968 return status;
2969
2970 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2971 if (status != SCARD_S_SUCCESS)
2972 return status;
2973
2974 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2975 return STATUS_BUFFER_TOO_SMALL;
2976
2977 Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
2978 Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
2979 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2980
2981 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2982 &(call->handles.hContext));
2983 if (status != SCARD_S_SUCCESS)
2984 return status;
2985
2986 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2987 if (status != SCARD_S_SUCCESS)
2988 return status;
2989
2990 smartcard_trace_status_call(log, call, unicode);
2991 return status;
2992}
2993
2994LONG smartcard_pack_status_call(wStream* s, const Status_Call* call, BOOL unicode)
2995{
2996 WINPR_ASSERT(call);
2997 wLog* log = scard_log();
2998 DWORD index = 0;
2999
3000 smartcard_trace_status_call(log, call, unicode);
3001
3002 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3003 if (status != SCARD_S_SUCCESS)
3004 return status;
3005
3006 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3007 if (status != SCARD_S_SUCCESS)
3008 return status;
3009
3010 if (!Stream_EnsureRemainingCapacity(s, 12))
3011 return SCARD_E_NO_MEMORY;
3012
3013 Stream_Write_INT32(s, call->fmszReaderNamesIsNULL);
3014 Stream_Write_UINT32(s, call->cchReaderLen);
3015 Stream_Write_UINT32(s, call->cbAtrLen);
3016
3017 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3018 if (status != SCARD_S_SUCCESS)
3019 return status;
3020
3021 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3022}
3023
3024LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
3025{
3026 WINPR_ASSERT(ret);
3027 wLog* log = scard_log();
3028
3029 LONG status = 0;
3030 UINT32 index = 0;
3031 DWORD cBytes = ret->cBytes;
3032
3033 smartcard_trace_status_return(log, ret, unicode);
3034 if (ret->ReturnCode != SCARD_S_SUCCESS)
3035 cBytes = 0;
3036 if (cBytes == SCARD_AUTOALLOCATE)
3037 cBytes = 0;
3038
3039 if (!Stream_EnsureRemainingCapacity(s, 4))
3040 return SCARD_F_INTERNAL_ERROR;
3041
3042 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
3043 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
3044 return SCARD_E_NO_MEMORY;
3045
3046 if (!Stream_EnsureRemainingCapacity(s, 44))
3047 return SCARD_F_INTERNAL_ERROR;
3048
3049 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
3050 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
3051 Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
3052 Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
3053 status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3054 if (status != SCARD_S_SUCCESS)
3055 return status;
3056 return ret->ReturnCode;
3057}
3058
3059LONG smartcard_unpack_status_return(wStream* s, Status_Return* ret, BOOL unicode)
3060{
3061 WINPR_ASSERT(ret);
3062 wLog* log = scard_log();
3063 UINT32 index = 0;
3064 UINT32 mszNdrPtr = 0;
3065
3066 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3067 return STATUS_BUFFER_TOO_SMALL;
3068
3069 const UINT32 cBytes = Stream_Get_UINT32(s);
3070
3071 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3072 return ERROR_INVALID_DATA;
3073
3074 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 44))
3075 return STATUS_BUFFER_TOO_SMALL;
3076
3077 Stream_Read_UINT32(s, ret->dwState);
3078 Stream_Read_UINT32(s, ret->dwProtocol);
3079 Stream_Read(s, ret->pbAtr, sizeof(ret->pbAtr));
3080 Stream_Read_UINT32(s, ret->cbAtrLen);
3081
3082 if (mszNdrPtr)
3083 {
3084 LONG status = smartcard_ndr_read(log, s, &ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
3085 if (status != SCARD_S_SUCCESS)
3086 return status;
3087 ret->cBytes = cBytes;
3088 }
3089
3090 smartcard_trace_status_return(log, ret, unicode);
3091 return SCARD_S_SUCCESS;
3092}
3093
3094LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
3095{
3096 WINPR_ASSERT(call);
3097 wLog* log = scard_log();
3098 UINT32 index = 0;
3099 UINT32 pbContextNdrPtr = 0;
3100
3101 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3102 &pbContextNdrPtr);
3103 if (status != SCARD_S_SUCCESS)
3104 return status;
3105
3106 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3107 if (status != SCARD_S_SUCCESS)
3108 return status;
3109
3110 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3111 return STATUS_BUFFER_TOO_SMALL;
3112
3113 Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
3114 Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
3115 Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
3116
3117 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3118 &(call->handles.hContext));
3119 if (status != SCARD_S_SUCCESS)
3120 return status;
3121
3122 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3123 if (status != SCARD_S_SUCCESS)
3124 return status;
3125
3126 smartcard_trace_get_attrib_call(log, call);
3127 return status;
3128}
3129
3130LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
3131 DWORD cbAttrCallLen)
3132{
3133 WINPR_ASSERT(ret);
3134 wLog* log = scard_log();
3135 LONG status = 0;
3136 DWORD cbAttrLen = 0;
3137 UINT32 index = 0;
3138 smartcard_trace_get_attrib_return(log, ret, dwAttrId);
3139
3140 if (!Stream_EnsureRemainingCapacity(s, 4))
3141 return SCARD_F_INTERNAL_ERROR;
3142
3143 cbAttrLen = ret->cbAttrLen;
3144 if (ret->ReturnCode != SCARD_S_SUCCESS)
3145 cbAttrLen = 0;
3146 if (cbAttrLen == SCARD_AUTOALLOCATE)
3147 cbAttrLen = 0;
3148
3149 if (ret->pbAttr)
3150 {
3151 if (cbAttrCallLen < cbAttrLen)
3152 cbAttrLen = cbAttrCallLen;
3153 }
3154 Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
3155 if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
3156 return SCARD_E_NO_MEMORY;
3157
3158 status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
3159 if (status != SCARD_S_SUCCESS)
3160 return status;
3161 return ret->ReturnCode;
3162}
3163
3164LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
3165{
3166 WINPR_ASSERT(call);
3167 wLog* log = scard_log();
3168
3169 UINT32 index = 0;
3170 UINT32 pvInBufferNdrPtr = 0;
3171 UINT32 pbContextNdrPtr = 0;
3172
3173 call->pvInBuffer = nullptr;
3174
3175 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3176 &pbContextNdrPtr);
3177 if (status != SCARD_S_SUCCESS)
3178 return status;
3179
3180 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3181 if (status != SCARD_S_SUCCESS)
3182 return status;
3183
3184 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
3185 return STATUS_BUFFER_TOO_SMALL;
3186
3187 Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
3188 const UINT32 cbInBufferSize = Stream_Get_UINT32(s); /* cbInBufferSize (4 bytes) */
3189 if (!smartcard_ndr_pointer_read(log, s, &index,
3190 &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
3191 return ERROR_INVALID_DATA;
3192 Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
3193 Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
3194
3195 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3196 &(call->handles.hContext));
3197 if (status != SCARD_S_SUCCESS)
3198 return status;
3199
3200 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3201 if (status != SCARD_S_SUCCESS)
3202 return status;
3203
3204 if (pvInBufferNdrPtr)
3205 {
3206 status = smartcard_ndr_read(log, s, &call->pvInBuffer, cbInBufferSize, 1, NDR_PTR_SIMPLE);
3207 if (status != SCARD_S_SUCCESS)
3208 return status;
3209 call->cbInBufferSize = cbInBufferSize;
3210 }
3211
3212 smartcard_trace_control_call(log, call);
3213 return SCARD_S_SUCCESS;
3214}
3215
3216LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
3217{
3218 WINPR_ASSERT(ret);
3219 wLog* log = scard_log();
3220
3221 LONG status = 0;
3222 DWORD cbDataLen = ret->cbOutBufferSize;
3223 UINT32 index = 0;
3224
3225 smartcard_trace_control_return(log, ret);
3226 if (ret->ReturnCode != SCARD_S_SUCCESS)
3227 cbDataLen = 0;
3228 if (cbDataLen == SCARD_AUTOALLOCATE)
3229 cbDataLen = 0;
3230
3231 if (!Stream_EnsureRemainingCapacity(s, 4))
3232 return SCARD_F_INTERNAL_ERROR;
3233
3234 Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
3235 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3236 return SCARD_E_NO_MEMORY;
3237
3238 status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
3239 if (status != SCARD_S_SUCCESS)
3240 return status;
3241 return ret->ReturnCode;
3242}
3243
3244LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
3245{
3246 UINT32 length = 0;
3247 BYTE* pbExtraBytes = nullptr;
3248 UINT32 pbExtraBytesNdrPtr = 0;
3249 UINT32 pbSendBufferNdrPtr = 0;
3250 UINT32 pioRecvPciNdrPtr = 0;
3251 SCardIO_Request ioSendPci;
3252 SCardIO_Request ioRecvPci;
3253 UINT32 index = 0;
3254 UINT32 pbContextNdrPtr = 0;
3255
3256 WINPR_ASSERT(call);
3257 wLog* log = scard_log();
3258
3259 call->pioSendPci = nullptr;
3260 call->pioRecvPci = nullptr;
3261 call->pbSendBuffer = nullptr;
3262
3263 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3264 &pbContextNdrPtr);
3265 if (status != SCARD_S_SUCCESS)
3266 return status;
3267
3268 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3269 if (status != SCARD_S_SUCCESS)
3270 return status;
3271
3272 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
3273 return STATUS_BUFFER_TOO_SMALL;
3274
3275 Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
3276 Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3277 if (!smartcard_ndr_pointer_read(log, s, &index,
3278 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3279 return ERROR_INVALID_DATA;
3280
3281 const UINT32 cbSendLength = Stream_Get_UINT32(s); /* cbSendLength (4 bytes) */
3282 if (!smartcard_ndr_pointer_read(log, s, &index,
3283 &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
3284 return ERROR_INVALID_DATA;
3285
3286 if (!smartcard_ndr_pointer_read(log, s, &index,
3287 &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
3288 return ERROR_INVALID_DATA;
3289
3290 Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
3291 Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
3292
3293 if (ioSendPci.cbExtraBytes > 1024)
3294 {
3295 WLog_Print(log, WLOG_WARN,
3296 "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3297 ioSendPci.cbExtraBytes);
3298 return STATUS_INVALID_PARAMETER;
3299 }
3300
3301 if (cbSendLength > 66560)
3302 {
3303 WLog_Print(log, WLOG_WARN,
3304 "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3305 ioSendPci.cbExtraBytes);
3306 return STATUS_INVALID_PARAMETER;
3307 }
3308
3309 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3310 &(call->handles.hContext));
3311 if (status != SCARD_S_SUCCESS)
3312 return status;
3313
3314 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3315 if (status != SCARD_S_SUCCESS)
3316 return status;
3317
3318 if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3319 {
3320 WLog_Print(
3321 log, WLOG_WARN,
3322 "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3323 return STATUS_INVALID_PARAMETER;
3324 }
3325
3326 if (pbExtraBytesNdrPtr)
3327 {
3328 // TODO: Use unified pointer reading
3329 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3330 return STATUS_BUFFER_TOO_SMALL;
3331
3332 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3333
3334 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3335 return STATUS_BUFFER_TOO_SMALL;
3336
3337 ioSendPci.pbExtraBytes = Stream_Pointer(s);
3338 call->pioSendPci =
3339 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3340
3341 if (!call->pioSendPci)
3342 {
3343 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3344 return STATUS_NO_MEMORY;
3345 }
3346
3347 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3348 call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3349 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3350 Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3351 if (smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4) < 0)
3352 return STATUS_INVALID_PARAMETER;
3353 }
3354 else
3355 {
3356 call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3357
3358 if (!call->pioSendPci)
3359 {
3360 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3361 return STATUS_NO_MEMORY;
3362 }
3363
3364 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3365 call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3366 }
3367
3368 if (pbSendBufferNdrPtr)
3369 {
3370 status = smartcard_ndr_read(log, s, &call->pbSendBuffer, cbSendLength, 1, NDR_PTR_SIMPLE);
3371 if (status != SCARD_S_SUCCESS)
3372 return status;
3373 call->cbSendLength = cbSendLength;
3374 }
3375
3376 if (pioRecvPciNdrPtr)
3377 {
3378 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3379 return STATUS_BUFFER_TOO_SMALL;
3380
3381 Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
3382 Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3383 if (!smartcard_ndr_pointer_read(log, s, &index,
3384 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3385 return ERROR_INVALID_DATA;
3386
3387 if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3388 {
3389 WLog_Print(
3390 log, WLOG_WARN,
3391 "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3392 return STATUS_INVALID_PARAMETER;
3393 }
3394
3395 if (pbExtraBytesNdrPtr)
3396 {
3397 // TODO: Unify ndr pointer reading
3398 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3399 return STATUS_BUFFER_TOO_SMALL;
3400
3401 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3402
3403 if (ioRecvPci.cbExtraBytes > 1024)
3404 {
3405 WLog_Print(log, WLOG_WARN,
3406 "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3407 " (max: 1024)",
3408 ioRecvPci.cbExtraBytes);
3409 return STATUS_INVALID_PARAMETER;
3410 }
3411
3412 if (length != ioRecvPci.cbExtraBytes)
3413 {
3414 WLog_Print(log, WLOG_WARN,
3415 "Transmit_Call unexpected length: Actual: %" PRIu32
3416 ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3417 length, ioRecvPci.cbExtraBytes);
3418 return STATUS_INVALID_PARAMETER;
3419 }
3420
3421 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3422 return STATUS_BUFFER_TOO_SMALL;
3423
3424 ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3425 call->pioRecvPci =
3426 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3427
3428 if (!call->pioRecvPci)
3429 {
3430 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3431 return STATUS_NO_MEMORY;
3432 }
3433
3434 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3435 call->pioRecvPci->cbPciLength =
3436 (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3437 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3438 Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3439 if (smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4) < 0)
3440 return STATUS_INVALID_PARAMETER;
3441 }
3442 else
3443 {
3444 call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3445
3446 if (!call->pioRecvPci)
3447 {
3448 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3449 return STATUS_NO_MEMORY;
3450 }
3451
3452 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3453 call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3454 }
3455 }
3456
3457 smartcard_trace_transmit_call(log, call);
3458 return SCARD_S_SUCCESS;
3459}
3460
3461LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3462{
3463 WINPR_ASSERT(ret);
3464 wLog* log = scard_log();
3465
3466 LONG status = 0;
3467 UINT32 index = 0;
3468 LONG error = 0;
3469 UINT32 cbRecvLength = ret->cbRecvLength;
3470 UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3471
3472 smartcard_trace_transmit_return(log, ret);
3473
3474 if (!ret->pbRecvBuffer)
3475 cbRecvLength = 0;
3476
3477 if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3478 return SCARD_E_NO_MEMORY;
3479 if (!Stream_EnsureRemainingCapacity(s, 4))
3480 return SCARD_E_NO_MEMORY;
3481 Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3482 if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3483 return SCARD_E_NO_MEMORY;
3484
3485 if (ret->pioRecvPci)
3486 {
3487 UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3488 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3489
3490 if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3491 {
3492 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3493 return SCARD_F_INTERNAL_ERROR;
3494 }
3495
3496 Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3497 Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
3498 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3499 return SCARD_E_NO_MEMORY;
3500 error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3501 if (error)
3502 return error;
3503 }
3504
3505 status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3506 if (status != SCARD_S_SUCCESS)
3507 return status;
3508 return ret->ReturnCode;
3509}
3510
3511LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3512{
3513 UINT32 rgReaderStatesNdrPtr = 0;
3514 UINT32 rgAtrMasksNdrPtr = 0;
3515 UINT32 index = 0;
3516 UINT32 pbContextNdrPtr = 0;
3517
3518 WINPR_ASSERT(call);
3519 wLog* log = scard_log();
3520
3521 call->rgReaderStates = nullptr;
3522
3523 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3524 &pbContextNdrPtr);
3525 if (status != SCARD_S_SUCCESS)
3526 return status;
3527
3528 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3529 return STATUS_BUFFER_TOO_SMALL;
3530
3531 Stream_Read_UINT32(s, call->cAtrs);
3532 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3533 return ERROR_INVALID_DATA;
3534 const DWORD cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3535 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3536 return ERROR_INVALID_DATA;
3537
3538 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3539 &(call->handles.hContext));
3540 if (status != SCARD_S_SUCCESS)
3541 return status;
3542
3543 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3544 {
3545 WLog_Print(log, WLOG_WARN,
3546 "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3547 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3548 rgAtrMasksNdrPtr, call->cAtrs);
3549 return STATUS_INVALID_PARAMETER;
3550 }
3551
3552 if (rgAtrMasksNdrPtr)
3553 {
3554 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3555 if (status != SCARD_S_SUCCESS)
3556 return status;
3557 }
3558
3559 if (rgReaderStatesNdrPtr)
3560 {
3561 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3562 if (status != SCARD_S_SUCCESS)
3563 return status;
3564 call->cReaders = cReaders;
3565 }
3566
3567 smartcard_trace_locate_cards_by_atr_a_call(log, call);
3568 return SCARD_S_SUCCESS;
3569}
3570
3571LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3572{
3573 UINT32 sz1NdrPtr = 0;
3574 UINT32 sz2NdrPtr = 0;
3575 UINT32 index = 0;
3576 UINT32 pbContextNdrPtr = 0;
3577
3578 WINPR_ASSERT(call);
3579 wLog* log = scard_log();
3580
3581 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3582 &pbContextNdrPtr);
3583 if (status != SCARD_S_SUCCESS)
3584 return status;
3585
3586 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3587 return ERROR_INVALID_DATA;
3588 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3589 return ERROR_INVALID_DATA;
3590
3591 status =
3592 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3593 if (status != SCARD_S_SUCCESS)
3594 return status;
3595
3596 if (sz1NdrPtr)
3597 {
3598 status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3599 if (status != SCARD_S_SUCCESS)
3600 return status;
3601 }
3602 if (sz2NdrPtr)
3603 {
3604 status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3605 if (status != SCARD_S_SUCCESS)
3606 return status;
3607 }
3608 smartcard_trace_context_and_two_strings_a_call(log, call);
3609 return SCARD_S_SUCCESS;
3610}
3611
3612LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3613{
3614 UINT32 sz1NdrPtr = 0;
3615 UINT32 sz2NdrPtr = 0;
3616 UINT32 index = 0;
3617 UINT32 pbContextNdrPtr = 0;
3618
3619 WINPR_ASSERT(call);
3620 wLog* log = scard_log();
3621
3622 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3623 &pbContextNdrPtr);
3624 if (status != SCARD_S_SUCCESS)
3625 return status;
3626
3627 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3628 return ERROR_INVALID_DATA;
3629 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3630 return ERROR_INVALID_DATA;
3631
3632 status =
3633 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3634 if (status != SCARD_S_SUCCESS)
3635 return status;
3636
3637 if (sz1NdrPtr)
3638 {
3639 status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3640 if (status != SCARD_S_SUCCESS)
3641 return status;
3642 }
3643 if (sz2NdrPtr)
3644 {
3645 status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3646 if (status != SCARD_S_SUCCESS)
3647 return status;
3648 }
3649 smartcard_trace_context_and_two_strings_w_call(log, call);
3650 return SCARD_S_SUCCESS;
3651}
3652
3653LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3654{
3655 UINT32 sz1NdrPtr = 0;
3656 UINT32 sz2NdrPtr = 0;
3657 UINT32 index = 0;
3658 UINT32 pbContextNdrPtr = 0;
3659
3660 WINPR_ASSERT(call);
3661 wLog* log = scard_log();
3662
3663 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3664 &pbContextNdrPtr);
3665 if (status != SCARD_S_SUCCESS)
3666 return status;
3667
3668 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3669 return STATUS_BUFFER_TOO_SMALL;
3670
3671 const UINT32 cBytes = Stream_Get_UINT32(s);
3672 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3673 return ERROR_INVALID_DATA;
3674
3675 const DWORD cReaders = Stream_Get_UINT32(s);
3676 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3677 return ERROR_INVALID_DATA;
3678
3679 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3680 &(call->handles.hContext));
3681 if (status != SCARD_S_SUCCESS)
3682 return status;
3683
3684 if (sz1NdrPtr)
3685 {
3686 status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3687 if (status != SCARD_S_SUCCESS)
3688 return status;
3689 call->cBytes = cBytes;
3690 }
3691 if (sz2NdrPtr)
3692 {
3693 status = smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, cReaders, &index);
3694 if (status != SCARD_S_SUCCESS)
3695 return status;
3696 call->cReaders = cReaders;
3697 }
3698 smartcard_trace_locate_cards_a_call(log, call);
3699 return SCARD_S_SUCCESS;
3700}
3701
3702LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3703{
3704 UINT32 sz1NdrPtr = 0;
3705 UINT32 sz2NdrPtr = 0;
3706 UINT32 index = 0;
3707 UINT32 pbContextNdrPtr = 0;
3708
3709 WINPR_ASSERT(call);
3710 wLog* log = scard_log();
3711
3712 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3713 &pbContextNdrPtr);
3714 if (status != SCARD_S_SUCCESS)
3715 return status;
3716
3717 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3718 return STATUS_BUFFER_TOO_SMALL;
3719
3720 const UINT32 cBytes = Stream_Get_UINT32(s);
3721 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3722 return ERROR_INVALID_DATA;
3723
3724 const DWORD cReaders = Stream_Get_UINT32(s);
3725 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3726 return ERROR_INVALID_DATA;
3727
3728 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3729 &(call->handles.hContext));
3730 if (status != SCARD_S_SUCCESS)
3731 return status;
3732
3733 if (sz1NdrPtr)
3734 {
3735 status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, cBytes, NDR_PTR_SIMPLE);
3736 if (status != SCARD_S_SUCCESS)
3737 return status;
3738 call->cBytes = cBytes;
3739 }
3740 if (sz2NdrPtr)
3741 {
3742 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3743 if (status != SCARD_S_SUCCESS)
3744 return status;
3745 call->cReaders = cReaders;
3746 }
3747 smartcard_trace_locate_cards_w_call(log, call);
3748 return SCARD_S_SUCCESS;
3749}
3750
3751LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3752{
3753 UINT32 index = 0;
3754 UINT32 ndrPtr = 0;
3755 UINT32 pbContextNdrPtr = 0;
3756
3757 WINPR_ASSERT(call);
3758 wLog* log = scard_log();
3759
3760 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3761 &pbContextNdrPtr);
3762 if (status != SCARD_S_SUCCESS)
3763 return status;
3764 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3765 if (status != SCARD_S_SUCCESS)
3766 return status;
3767
3768 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3769 return STATUS_BUFFER_TOO_SMALL;
3770 Stream_Read_UINT32(s, call->dwAttrId);
3771 Stream_Read_UINT32(s, call->cbAttrLen);
3772
3773 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3774 return ERROR_INVALID_DATA;
3775
3776 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3777 &(call->handles.hContext));
3778 if (status != SCARD_S_SUCCESS)
3779 return status;
3780
3781 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3782 if (status != SCARD_S_SUCCESS)
3783 return status;
3784
3785 if (ndrPtr)
3786 {
3787 size_t len = 0;
3788 status = smartcard_ndr_read_ex(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE, &len);
3789 if (status != SCARD_S_SUCCESS)
3790 return status;
3791 if (call->cbAttrLen > len)
3792 call->cbAttrLen = WINPR_ASSERTING_INT_CAST(DWORD, len);
3793 }
3794 else
3795 call->cbAttrLen = 0;
3796 smartcard_trace_set_attrib_call(log, call);
3797 return SCARD_S_SUCCESS;
3798}
3799
3800LONG smartcard_pack_set_attrib_call(wStream* s, const SetAttrib_Call* call)
3801{
3802 WINPR_ASSERT(call);
3803 wLog* log = scard_log();
3804 DWORD index = 0;
3805
3806 smartcard_trace_set_attrib_call(log, call);
3807
3808 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
3809 if (status != SCARD_S_SUCCESS)
3810 return status;
3811
3812 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
3813 if (status != SCARD_S_SUCCESS)
3814 return status;
3815
3816 if (!Stream_EnsureRemainingCapacity(s, 8))
3817 return SCARD_E_NO_MEMORY;
3818
3819 Stream_Write_UINT32(s, call->dwAttrId);
3820 Stream_Write_UINT32(s, call->cbAttrLen);
3821
3822 if (!smartcard_ndr_pointer_write(s, &index, call->cbAttrLen))
3823 return SCARD_E_NO_MEMORY;
3824
3825 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
3826 if (status != SCARD_S_SUCCESS)
3827 return status;
3828
3829 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
3830 if (status != SCARD_S_SUCCESS)
3831 return status;
3832
3833 status = smartcard_ndr_write(s, call->pbAttr, call->cbAttrLen, 1, NDR_PTR_SIMPLE);
3834 if (status != SCARD_S_SUCCESS)
3835 return status;
3836
3837 return SCARD_S_SUCCESS;
3838}
3839
3840LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3841{
3842 UINT32 rgReaderStatesNdrPtr = 0;
3843 UINT32 rgAtrMasksNdrPtr = 0;
3844 UINT32 index = 0;
3845 UINT32 pbContextNdrPtr = 0;
3846
3847 WINPR_ASSERT(call);
3848 wLog* log = scard_log();
3849
3850 call->rgReaderStates = nullptr;
3851
3852 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3853 &pbContextNdrPtr);
3854 if (status != SCARD_S_SUCCESS)
3855 return status;
3856
3857 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3858 return STATUS_BUFFER_TOO_SMALL;
3859
3860 Stream_Read_UINT32(s, call->cAtrs);
3861 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3862 return ERROR_INVALID_DATA;
3863
3864 const DWORD cReaders = Stream_Get_UINT32(s); /* cReaders (4 bytes) */
3865 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3866 return ERROR_INVALID_DATA;
3867
3868 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3869 &(call->handles.hContext));
3870 if (status != SCARD_S_SUCCESS)
3871 return status;
3872
3873 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3874 {
3875 WLog_Print(log, WLOG_WARN,
3876 "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3877 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3878 rgAtrMasksNdrPtr, call->cAtrs);
3879 return STATUS_INVALID_PARAMETER;
3880 }
3881
3882 if (rgAtrMasksNdrPtr)
3883 {
3884 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3885 if (status != SCARD_S_SUCCESS)
3886 return status;
3887 }
3888
3889 if (rgReaderStatesNdrPtr)
3890 {
3891 status = smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, cReaders, &index);
3892 if (status != SCARD_S_SUCCESS)
3893 return status;
3894 call->cReaders = cReaders;
3895 }
3896
3897 smartcard_trace_locate_cards_by_atr_w_call(log, call);
3898 return SCARD_S_SUCCESS;
3899}
3900
3901LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3902{
3903 UINT32 mszNdrPtr = 0;
3904 UINT32 contextNdrPtr = 0;
3905 UINT32 index = 0;
3906 UINT32 pbContextNdrPtr = 0;
3907
3908 WINPR_ASSERT(call);
3909 wLog* log = scard_log();
3910
3911 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3912 return ERROR_INVALID_DATA;
3913
3914 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3915 &index, &pbContextNdrPtr);
3916 if (status != SCARD_S_SUCCESS)
3917 return status;
3918
3919 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3920 return ERROR_INVALID_DATA;
3921
3922 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3923 return STATUS_BUFFER_TOO_SMALL;
3924 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3925 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3926 Stream_Read_UINT32(s, call->Common.cbDataLen);
3927
3928 call->szLookupName = nullptr;
3929 if (mszNdrPtr)
3930 {
3931 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3932 if (status != SCARD_S_SUCCESS)
3933 return status;
3934 }
3935
3936 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3937 &call->Common.handles.hContext);
3938 if (status != SCARD_S_SUCCESS)
3939 return status;
3940
3941 if (contextNdrPtr)
3942 {
3943 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3944 if (status != SCARD_S_SUCCESS)
3945 return status;
3946 }
3947 smartcard_trace_read_cache_a_call(log, call);
3948 return SCARD_S_SUCCESS;
3949}
3950
3951LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3952{
3953 UINT32 mszNdrPtr = 0;
3954 UINT32 contextNdrPtr = 0;
3955 UINT32 index = 0;
3956 UINT32 pbContextNdrPtr = 0;
3957
3958 WINPR_ASSERT(call);
3959 wLog* log = scard_log();
3960
3961 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3962 return ERROR_INVALID_DATA;
3963
3964 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3965 &index, &pbContextNdrPtr);
3966 if (status != SCARD_S_SUCCESS)
3967 return status;
3968
3969 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3970 return ERROR_INVALID_DATA;
3971
3972 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3973 return STATUS_BUFFER_TOO_SMALL;
3974 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3975 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3976 Stream_Read_UINT32(s, call->Common.cbDataLen);
3977
3978 call->szLookupName = nullptr;
3979 if (mszNdrPtr)
3980 {
3981 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3982 if (status != SCARD_S_SUCCESS)
3983 return status;
3984 }
3985
3986 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3987 &call->Common.handles.hContext);
3988 if (status != SCARD_S_SUCCESS)
3989 return status;
3990
3991 if (contextNdrPtr)
3992 {
3993 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3994 if (status != SCARD_S_SUCCESS)
3995 return status;
3996 }
3997 smartcard_trace_read_cache_w_call(log, call);
3998 return SCARD_S_SUCCESS;
3999}
4000
4001LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
4002{
4003 UINT32 mszNdrPtr = 0;
4004 UINT32 contextNdrPtr = 0;
4005 UINT32 pbDataNdrPtr = 0;
4006 UINT32 index = 0;
4007 UINT32 pbContextNdrPtr = 0;
4008
4009 WINPR_ASSERT(call);
4010 wLog* log = scard_log();
4011
4012 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4013 return ERROR_INVALID_DATA;
4014
4015 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4016 &index, &pbContextNdrPtr);
4017 if (status != SCARD_S_SUCCESS)
4018 return status;
4019
4020 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4021 return ERROR_INVALID_DATA;
4022
4023 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4024 return STATUS_BUFFER_TOO_SMALL;
4025
4026 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4027 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4028
4029 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4030 return ERROR_INVALID_DATA;
4031
4032 call->szLookupName = nullptr;
4033 if (mszNdrPtr)
4034 {
4035 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
4036 if (status != SCARD_S_SUCCESS)
4037 return status;
4038 }
4039
4040 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4041 &call->Common.handles.hContext);
4042 if (status != SCARD_S_SUCCESS)
4043 return status;
4044
4045 call->Common.CardIdentifier = nullptr;
4046 if (contextNdrPtr)
4047 {
4048 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4049 if (status != SCARD_S_SUCCESS)
4050 return status;
4051 }
4052
4053 call->Common.pbData = nullptr;
4054 if (pbDataNdrPtr)
4055 {
4056 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4057 if (status != SCARD_S_SUCCESS)
4058 return status;
4059 call->Common.cbDataLen = cbDataLen;
4060 }
4061 smartcard_trace_write_cache_a_call(log, call);
4062 return SCARD_S_SUCCESS;
4063}
4064
4065LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
4066{
4067 UINT32 mszNdrPtr = 0;
4068 UINT32 contextNdrPtr = 0;
4069 UINT32 pbDataNdrPtr = 0;
4070 UINT32 index = 0;
4071 UINT32 pbContextNdrPtr = 0;
4072
4073 WINPR_ASSERT(call);
4074 wLog* log = scard_log();
4075
4076 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4077 return ERROR_INVALID_DATA;
4078
4079 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
4080 &index, &pbContextNdrPtr);
4081 if (status != SCARD_S_SUCCESS)
4082 return status;
4083
4084 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
4085 return ERROR_INVALID_DATA;
4086
4087 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4088 return STATUS_BUFFER_TOO_SMALL;
4089 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
4090 const UINT32 cbDataLen = Stream_Get_UINT32(s);
4091
4092 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
4093 return ERROR_INVALID_DATA;
4094
4095 call->szLookupName = nullptr;
4096 if (mszNdrPtr)
4097 {
4098 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
4099 if (status != SCARD_S_SUCCESS)
4100 return status;
4101 }
4102
4103 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4104 &call->Common.handles.hContext);
4105 if (status != SCARD_S_SUCCESS)
4106 return status;
4107
4108 call->Common.CardIdentifier = nullptr;
4109 if (contextNdrPtr)
4110 {
4111 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
4112 if (status != SCARD_S_SUCCESS)
4113 return status;
4114 }
4115
4116 call->Common.pbData = nullptr;
4117 if (pbDataNdrPtr)
4118 {
4119 status = smartcard_ndr_read(log, s, &call->Common.pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4120 if (status != SCARD_S_SUCCESS)
4121 return status;
4122 call->Common.cbDataLen = cbDataLen;
4123 }
4124 smartcard_trace_write_cache_w_call(log, call);
4125 return status;
4126}
4127
4128LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
4129{
4130 WINPR_ASSERT(call);
4131 wLog* log = scard_log();
4132
4133 UINT32 index = 0;
4134 UINT32 pbContextNdrPtr = 0;
4135
4136 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
4137 &pbContextNdrPtr);
4138 if (status != SCARD_S_SUCCESS)
4139 return status;
4140
4141 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
4142 if (status != SCARD_S_SUCCESS)
4143 return status;
4144
4145 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
4146 &(call->handles.hContext));
4147 if (status != SCARD_S_SUCCESS)
4148 {
4149 WLog_Print(log, WLOG_ERROR,
4150 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
4151 status);
4152 return status;
4153 }
4154
4155 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
4156 if (status != SCARD_S_SUCCESS)
4157 WLog_Print(log, WLOG_ERROR,
4158 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
4159
4160 smartcard_trace_get_transmit_count_call(log, call);
4161 return status;
4162}
4163
4164LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
4165{
4166 WINPR_ASSERT(call);
4167 wLog* log = scard_log();
4168 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4169 &call->szReaderName);
4170}
4171
4172LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
4173{
4174 WINPR_ASSERT(call);
4175 wLog* log = scard_log();
4176 return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
4177}
4178
4179LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
4180{
4181 WINPR_ASSERT(call);
4182 wLog* log = scard_log();
4183 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
4184}
4185
4186LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
4187{
4188 WINPR_ASSERT(call);
4189 wLog* log = scard_log();
4190 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
4191 &call->szReaderName);
4192}
4193
4194LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
4195{
4196 WINPR_ASSERT(ret);
4197 wLog* log = scard_log();
4198 smartcard_trace_device_type_id_return(log, ret);
4199
4200 if (!Stream_EnsureRemainingCapacity(s, 4))
4201 {
4202 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4203 return SCARD_F_INTERNAL_ERROR;
4204 }
4205
4206 Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
4207
4208 return ret->ReturnCode;
4209}
4210
4211LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
4212{
4213 WINPR_ASSERT(ret);
4214 wLog* log = scard_log();
4215
4216 LONG status = 0;
4217 DWORD cbDataLen = ret->cReaders;
4218 UINT32 index = 0;
4219
4220 smartcard_trace_locate_cards_return(log, ret);
4221 if (ret->ReturnCode != SCARD_S_SUCCESS)
4222 cbDataLen = 0;
4223 if (cbDataLen == SCARD_AUTOALLOCATE)
4224 cbDataLen = 0;
4225
4226 if (!Stream_EnsureRemainingCapacity(s, 4))
4227 {
4228 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4229 return SCARD_F_INTERNAL_ERROR;
4230 }
4231
4232 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4233 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4234 return SCARD_E_NO_MEMORY;
4235
4236 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
4237 if (status != SCARD_S_SUCCESS)
4238 return status;
4239 return ret->ReturnCode;
4240}
4241
4242LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
4243{
4244 WINPR_ASSERT(ret);
4245 wLog* log = scard_log();
4246
4247 LONG status = 0;
4248 UINT32 index = 0;
4249 DWORD cbDataLen = ret->cbDataLen;
4250 smartcard_trace_get_reader_icon_return(log, ret);
4251 if (ret->ReturnCode != SCARD_S_SUCCESS)
4252 cbDataLen = 0;
4253 if (cbDataLen == SCARD_AUTOALLOCATE)
4254 cbDataLen = 0;
4255
4256 if (!Stream_EnsureRemainingCapacity(s, 4))
4257 {
4258 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4259 return SCARD_F_INTERNAL_ERROR;
4260 }
4261
4262 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4263 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4264 return SCARD_E_NO_MEMORY;
4265
4266 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4267 if (status != SCARD_S_SUCCESS)
4268 return status;
4269 return ret->ReturnCode;
4270}
4271
4272LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
4273{
4274 WINPR_ASSERT(ret);
4275 wLog* log = scard_log();
4276
4277 smartcard_trace_get_transmit_count_return(log, ret);
4278
4279 if (!Stream_EnsureRemainingCapacity(s, 4))
4280 {
4281 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4282 return SCARD_F_INTERNAL_ERROR;
4283 }
4284
4285 Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
4286
4287 return ret->ReturnCode;
4288}
4289
4290LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
4291{
4292 WINPR_ASSERT(ret);
4293 wLog* log = scard_log();
4294
4295 LONG status = 0;
4296 UINT32 index = 0;
4297 DWORD cbDataLen = ret->cbDataLen;
4298 smartcard_trace_read_cache_return(log, ret);
4299 if (ret->ReturnCode != SCARD_S_SUCCESS)
4300 cbDataLen = 0;
4301
4302 if (cbDataLen == SCARD_AUTOALLOCATE)
4303 cbDataLen = 0;
4304
4305 if (!Stream_EnsureRemainingCapacity(s, 4))
4306 {
4307 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
4308 return SCARD_F_INTERNAL_ERROR;
4309 }
4310
4311 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
4312 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
4313 return SCARD_E_NO_MEMORY;
4314
4315 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
4316 if (status != SCARD_S_SUCCESS)
4317 return status;
4318 return ret->ReturnCode;
4319}
4320
4321LONG smartcard_pack_context_call(wStream* s, const Context_Call* call, const char* name)
4322{
4323 WINPR_ASSERT(call);
4324 wLog* log = scard_log();
4325 DWORD index = 0;
4326
4327 smartcard_trace_context_call(log, call, name);
4328
4329 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4330 if (status != SCARD_S_SUCCESS)
4331 return status;
4332
4333 return smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4334}
4335
4336LONG smartcard_pack_list_readers_call(wStream* s, const ListReaders_Call* call, BOOL unicode)
4337{
4338 WINPR_ASSERT(call);
4339 wLog* log = scard_log();
4340 DWORD index = 0;
4341
4342 smartcard_trace_list_readers_call(log, call, unicode);
4343
4344 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4345 if (status != SCARD_S_SUCCESS)
4346 return status;
4347
4348 if (!Stream_EnsureRemainingCapacity(s, 4))
4349 return SCARD_E_NO_MEMORY;
4350
4351 Stream_Write_UINT32(s, call->cBytes);
4352 if (!smartcard_ndr_pointer_write(s, &index, call->cBytes))
4353 return SCARD_E_NO_MEMORY;
4354
4355 if (!Stream_EnsureRemainingCapacity(s, 8))
4356 return SCARD_E_NO_MEMORY;
4357
4358 Stream_Write_INT32(s, call->fmszReadersIsNULL);
4359 Stream_Write_UINT32(s, call->cchReaders);
4360
4361 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4362 if (status != SCARD_S_SUCCESS)
4363 return status;
4364
4365 if (call->cBytes > 0)
4366 {
4367 status = smartcard_ndr_write(s, call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
4368 if (status != SCARD_S_SUCCESS)
4369 return status;
4370 }
4371
4372 return SCARD_S_SUCCESS;
4373}
4374
4375static LONG smartcard_pack_reader_state_a(wStream* s, const LPSCARD_READERSTATEA rgReaderStates,
4376 UINT32 cReaders, UINT32* ptrIndex)
4377{
4378 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4379
4380 if (!Stream_EnsureRemainingCapacity(s, 4))
4381 return SCARD_E_NO_MEMORY;
4382
4383 Stream_Write_UINT32(s, cReaders);
4384
4385 for (UINT32 i = 0; i < cReaders; i++)
4386 {
4387 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4388
4389 if (!Stream_EnsureRemainingCapacity(s, 52))
4390 return SCARD_E_NO_MEMORY;
4391
4392 const DWORD nameLen = state->szReader ? (DWORD)(strlen(state->szReader) + 1) : 0;
4393 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4394 return SCARD_E_NO_MEMORY;
4395
4396 Stream_Write_UINT32(s, state->dwCurrentState);
4397 Stream_Write_UINT32(s, state->dwEventState);
4398 Stream_Write_UINT32(s, state->cbAtr);
4399 Stream_Write(s, state->rgbAtr, 36);
4400 }
4401
4402 for (UINT32 i = 0; i < cReaders; i++)
4403 {
4404 const SCARD_READERSTATEA* state = &rgReaderStates[i];
4405
4406 if (state->szReader)
4407 {
4408 const UINT32 nameLen = (UINT32)(strlen(state->szReader) + 1);
4409 LONG status = smartcard_ndr_write_a(s, state->szReader, nameLen, NDR_PTR_FULL);
4410 if (status != SCARD_S_SUCCESS)
4411 return status;
4412 }
4413 }
4414
4415 return SCARD_S_SUCCESS;
4416}
4417
4418static LONG smartcard_pack_reader_state_w(wStream* s, const LPSCARD_READERSTATEW rgReaderStates,
4419 UINT32 cReaders, UINT32* ptrIndex)
4420{
4421 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
4422
4423 if (!Stream_EnsureRemainingCapacity(s, 4))
4424 return SCARD_E_NO_MEMORY;
4425
4426 Stream_Write_UINT32(s, cReaders);
4427
4428 for (UINT32 i = 0; i < cReaders; i++)
4429 {
4430 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4431
4432 if (!Stream_EnsureRemainingCapacity(s, 52))
4433 return SCARD_E_NO_MEMORY;
4434
4435 const DWORD nameLen = state->szReader ? (DWORD)(_wcslen(state->szReader) + 1) : 0;
4436 if (!smartcard_ndr_pointer_write(s, ptrIndex, nameLen))
4437 return SCARD_E_NO_MEMORY;
4438
4439 Stream_Write_UINT32(s, state->dwCurrentState);
4440 Stream_Write_UINT32(s, state->dwEventState);
4441 Stream_Write_UINT32(s, state->cbAtr);
4442 Stream_Write(s, state->rgbAtr, 36);
4443 }
4444
4445 for (UINT32 i = 0; i < cReaders; i++)
4446 {
4447 const SCARD_READERSTATEW* state = &rgReaderStates[i];
4448
4449 if (state->szReader)
4450 {
4451 const UINT32 nameLen = (UINT32)(_wcslen(state->szReader) + 1);
4452 LONG status = smartcard_ndr_write_w(s, state->szReader, nameLen, NDR_PTR_FULL);
4453 if (status != SCARD_S_SUCCESS)
4454 return status;
4455 }
4456 }
4457
4458 return SCARD_S_SUCCESS;
4459}
4460
4461LONG smartcard_pack_get_status_change_a_call(wStream* s, const GetStatusChangeA_Call* call)
4462{
4463 WINPR_ASSERT(call);
4464 wLog* log = scard_log();
4465 DWORD index = 0;
4466
4467 smartcard_trace_get_status_change_a_call(log, call);
4468
4469 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4470 if (status != SCARD_S_SUCCESS)
4471 return status;
4472
4473 if (!Stream_EnsureRemainingCapacity(s, 8))
4474 return SCARD_E_NO_MEMORY;
4475
4476 Stream_Write_UINT32(s, call->dwTimeOut);
4477 Stream_Write_UINT32(s, call->cReaders);
4478
4479 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4480 return SCARD_E_NO_MEMORY;
4481
4482 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4483 if (status != SCARD_S_SUCCESS)
4484 return status;
4485
4486 if (call->cReaders > 0)
4487 {
4488 status = smartcard_pack_reader_state_a(s, call->rgReaderStates, call->cReaders, &index);
4489 if (status != SCARD_S_SUCCESS)
4490 return status;
4491 }
4492
4493 return SCARD_S_SUCCESS;
4494}
4495
4496LONG smartcard_pack_get_status_change_w_call(wStream* s, const GetStatusChangeW_Call* call)
4497{
4498 WINPR_ASSERT(call);
4499 wLog* log = scard_log();
4500 DWORD index = 0;
4501
4502 smartcard_trace_get_status_change_w_call(log, call);
4503
4504 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4505 if (status != SCARD_S_SUCCESS)
4506 return status;
4507
4508 if (!Stream_EnsureRemainingCapacity(s, 8))
4509 return SCARD_E_NO_MEMORY;
4510
4511 Stream_Write_UINT32(s, call->dwTimeOut);
4512 Stream_Write_UINT32(s, call->cReaders);
4513
4514 if (!smartcard_ndr_pointer_write(s, &index, call->cReaders))
4515 return SCARD_E_NO_MEMORY;
4516
4517 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4518 if (status != SCARD_S_SUCCESS)
4519 return status;
4520
4521 if (call->cReaders > 0)
4522 {
4523 status = smartcard_pack_reader_state_w(s, call->rgReaderStates, call->cReaders, &index);
4524 if (status != SCARD_S_SUCCESS)
4525 return status;
4526 }
4527
4528 return SCARD_S_SUCCESS;
4529}
4530
4531LONG smartcard_pack_connect_a_call(wStream* s, const ConnectA_Call* call)
4532{
4533 WINPR_ASSERT(call);
4534 wLog* log = scard_log();
4535 DWORD index = 0;
4536
4537 smartcard_trace_connect_a_call(log, call);
4538
4539 const DWORD readerLen = call->szReader ? (DWORD)(strlen(call->szReader) + 1) : 0;
4540 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4541 return SCARD_E_NO_MEMORY;
4542
4543 LONG status =
4544 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4545 if (status != SCARD_S_SUCCESS)
4546 return status;
4547
4548 if (!Stream_EnsureRemainingCapacity(s, 8))
4549 return SCARD_E_NO_MEMORY;
4550
4551 Stream_Write_UINT32(s, call->Common.dwShareMode);
4552 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4553
4554 if (call->szReader)
4555 {
4556 status = smartcard_ndr_write_a(s, call->szReader, readerLen, NDR_PTR_FULL);
4557 if (status != SCARD_S_SUCCESS)
4558 return status;
4559 }
4560
4561 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4562}
4563
4564LONG smartcard_pack_connect_w_call(wStream* s, const ConnectW_Call* call)
4565{
4566 WINPR_ASSERT(call);
4567 wLog* log = scard_log();
4568 DWORD index = 0;
4569
4570 smartcard_trace_connect_w_call(log, call);
4571
4572 const DWORD readerLen = call->szReader ? (DWORD)(_wcslen(call->szReader) + 1) : 0;
4573 if (!smartcard_ndr_pointer_write(s, &index, readerLen))
4574 return SCARD_E_NO_MEMORY;
4575
4576 LONG status =
4577 smartcard_pack_redir_scard_context(log, s, &call->Common.handles.hContext, &index);
4578 if (status != SCARD_S_SUCCESS)
4579 return status;
4580
4581 if (!Stream_EnsureRemainingCapacity(s, 8))
4582 return SCARD_E_NO_MEMORY;
4583
4584 Stream_Write_UINT32(s, call->Common.dwShareMode);
4585 Stream_Write_UINT32(s, call->Common.dwPreferredProtocols);
4586
4587 if (call->szReader)
4588 {
4589 status = smartcard_ndr_write_w(s, call->szReader, readerLen, NDR_PTR_FULL);
4590 if (status != SCARD_S_SUCCESS)
4591 return status;
4592 }
4593
4594 return smartcard_pack_redir_scard_context_ref(log, s, &call->Common.handles.hContext);
4595}
4596
4597LONG smartcard_pack_control_call(wStream* s, const Control_Call* call)
4598{
4599 WINPR_ASSERT(call);
4600 wLog* log = scard_log();
4601 DWORD index = 0;
4602
4603 smartcard_trace_control_call(log, call);
4604
4605 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4606 if (status != SCARD_S_SUCCESS)
4607 return status;
4608
4609 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4610 if (status != SCARD_S_SUCCESS)
4611 return status;
4612
4613 if (!Stream_EnsureRemainingCapacity(s, 8))
4614 return SCARD_E_NO_MEMORY;
4615
4616 Stream_Write_UINT32(s, call->dwControlCode);
4617 Stream_Write_UINT32(s, call->cbInBufferSize);
4618 if (!smartcard_ndr_pointer_write(s, &index, call->cbInBufferSize))
4619 return SCARD_E_NO_MEMORY;
4620
4621 Stream_Write_INT32(s, call->fpvOutBufferIsNULL);
4622 Stream_Write_UINT32(s, call->cbOutBufferSize);
4623
4624 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4625 if (status != SCARD_S_SUCCESS)
4626 return status;
4627
4628 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4629 if (status != SCARD_S_SUCCESS)
4630 return status;
4631
4632 if (call->cbInBufferSize)
4633 {
4634 status = smartcard_ndr_write(s, call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
4635 if (status != SCARD_S_SUCCESS)
4636 return status;
4637 }
4638
4639 return status;
4640}
4641
4642LONG smartcard_pack_hcard_and_disposition_call(wStream* s, const HCardAndDisposition_Call* call,
4643 const char* name)
4644{
4645 WINPR_ASSERT(call);
4646 wLog* log = scard_log();
4647 DWORD index = 0;
4648
4649 smartcard_trace_hcard_and_disposition_call(log, call, name);
4650
4651 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4652 if (status != SCARD_S_SUCCESS)
4653 return status;
4654
4655 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4656 if (status != SCARD_S_SUCCESS)
4657 return status;
4658
4659 if (!Stream_EnsureRemainingCapacity(s, 4))
4660 return SCARD_E_NO_MEMORY;
4661
4662 Stream_Write_UINT32(s, call->dwDisposition);
4663
4664 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4665 if (status != SCARD_S_SUCCESS)
4666 return status;
4667
4668 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4669}
4670
4671LONG smartcard_pack_transmit_call(wStream* s, const Transmit_Call* call)
4672{
4673 WINPR_ASSERT(call);
4674 wLog* log = scard_log();
4675 DWORD index = 0;
4676
4677 smartcard_trace_transmit_call(log, call);
4678
4679 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4680 if (status != SCARD_S_SUCCESS)
4681 return status;
4682
4683 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4684 if (status != SCARD_S_SUCCESS)
4685 return status;
4686
4687 UINT32 cbExtraBytes = 0;
4688 const BYTE* pbExtraBytes = nullptr;
4689 if (call->pioSendPci)
4690 {
4691 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4692 if (cbExtraBytes > 0)
4693 pbExtraBytes = &((const BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
4694 }
4695
4696 if (!Stream_EnsureRemainingCapacity(s, 32))
4697 return SCARD_E_NO_MEMORY;
4698
4699 Stream_Write_UINT32(s, call->pioSendPci ? call->pioSendPci->dwProtocol : 0);
4700 Stream_Write_UINT32(s, cbExtraBytes);
4701 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
4702 return SCARD_E_NO_MEMORY;
4703
4704 Stream_Write_UINT32(s, call->cbSendLength);
4705 if (!smartcard_ndr_pointer_write(s, &index, call->cbSendLength))
4706 return SCARD_E_NO_MEMORY;
4707
4708 const UINT32 recvPciLen = call->pioRecvPci ? (UINT32)call->pioRecvPci->cbPciLength : 0;
4709 if (!smartcard_ndr_pointer_write(s, &index, recvPciLen))
4710 return SCARD_E_NO_MEMORY;
4711
4712 Stream_Write_INT32(s, call->fpbRecvBufferIsNULL);
4713 Stream_Write_UINT32(s, call->cbRecvLength);
4714
4715 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4716 if (status != SCARD_S_SUCCESS)
4717 return status;
4718
4719 status = smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4720 if (status != SCARD_S_SUCCESS)
4721 return status;
4722
4723 if (cbExtraBytes > 0)
4724 {
4725 status = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
4726 if (status != SCARD_S_SUCCESS)
4727 return status;
4728 }
4729
4730 if (call->cbSendLength > 0)
4731 {
4732 status = smartcard_ndr_write(s, call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
4733 if (status != SCARD_S_SUCCESS)
4734 return status;
4735 }
4736
4737 if (call->pioRecvPci && recvPciLen > 0)
4738 {
4739 UINT32 cbRecvExtra = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
4740 const BYTE* pbRecvExtra = &((const BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
4741
4742 if (!Stream_EnsureRemainingCapacity(s, 12))
4743 return SCARD_E_NO_MEMORY;
4744
4745 Stream_Write_UINT32(s, call->pioRecvPci->dwProtocol);
4746 Stream_Write_UINT32(s, cbRecvExtra);
4747 if (!smartcard_ndr_pointer_write(s, &index, cbRecvExtra))
4748 return SCARD_E_NO_MEMORY;
4749
4750 if (cbRecvExtra > 0)
4751 {
4752 status = smartcard_ndr_write(s, pbRecvExtra, cbRecvExtra, 1, NDR_PTR_SIMPLE);
4753 if (status != SCARD_S_SUCCESS)
4754 return status;
4755 }
4756 }
4757
4758 return SCARD_S_SUCCESS;
4759}
4760
4761LONG smartcard_pack_get_attrib_call(wStream* s, const GetAttrib_Call* call)
4762{
4763 WINPR_ASSERT(call);
4764 wLog* log = scard_log();
4765 DWORD index = 0;
4766
4767 smartcard_trace_get_attrib_call(log, call);
4768
4769 LONG status = smartcard_pack_redir_scard_context(log, s, &call->handles.hContext, &index);
4770 if (status != SCARD_S_SUCCESS)
4771 return status;
4772
4773 status = smartcard_pack_redir_scard_handle(log, s, &call->handles.hCard, &index);
4774 if (status != SCARD_S_SUCCESS)
4775 return status;
4776
4777 if (!Stream_EnsureRemainingCapacity(s, 12))
4778 return STATUS_NO_MEMORY;
4779
4780 Stream_Write_UINT32(s, call->dwAttrId);
4781 Stream_Write_INT32(s, call->fpbAttrIsNULL);
4782 Stream_Write_UINT32(s, call->cbAttrLen);
4783
4784 status = smartcard_pack_redir_scard_context_ref(log, s, &call->handles.hContext);
4785 if (status != SCARD_S_SUCCESS)
4786 return status;
4787
4788 return smartcard_pack_redir_scard_handle_ref(log, s, &call->handles.hCard);
4789}
4790
4791LONG smartcard_unpack_list_readers_return(wStream* s, ListReaders_Return* ret, BOOL unicode)
4792{
4793 WINPR_ASSERT(ret);
4794 wLog* log = scard_log();
4795 UINT32 index = 0;
4796 UINT32 mszNdrPtr = 0;
4797
4798 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4799 return STATUS_BUFFER_TOO_SMALL;
4800
4801 const UINT32 cBytes = Stream_Get_UINT32(s);
4802
4803 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
4804 return ERROR_INVALID_DATA;
4805
4806 if (mszNdrPtr)
4807 {
4808 LONG status = smartcard_ndr_read(log, s, &ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
4809 if (status != SCARD_S_SUCCESS)
4810 return status;
4811 ret->cBytes = cBytes;
4812 }
4813
4814 smartcard_trace_list_readers_return(log, ret, unicode);
4815 return SCARD_S_SUCCESS;
4816}
4817
4818LONG smartcard_unpack_get_status_change_return(wStream* s, GetStatusChange_Return* ret,
4819 BOOL unicode)
4820{
4821 WINPR_ASSERT(ret);
4822 wLog* log = scard_log();
4823 UINT32 index = 0;
4824 UINT32 ndrPtr = 0;
4825
4826 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4827 return STATUS_BUFFER_TOO_SMALL;
4828
4829 Stream_Read_UINT32(s, ret->cReaders);
4830
4831 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
4832 return ERROR_INVALID_DATA;
4833
4834 if (ndrPtr && ret->cReaders > 0)
4835 {
4836 LONG status =
4837 smartcard_ndr_read_state(log, s, &ret->rgReaderStates, ret->cReaders, NDR_PTR_SIMPLE);
4838 if (status != SCARD_S_SUCCESS)
4839 return status;
4840 }
4841 else
4842 ret->rgReaderStates = nullptr;
4843
4844 smartcard_trace_get_status_change_return(log, ret, unicode);
4845 return SCARD_S_SUCCESS;
4846}
4847
4848LONG smartcard_unpack_connect_return(wStream* s, Connect_Return* ret)
4849{
4850 WINPR_ASSERT(ret);
4851 wLog* log = scard_log();
4852 UINT32 index = 0;
4853 UINT32 pbContextNdrPtr = 0;
4854
4855 LONG status =
4856 smartcard_unpack_redir_scard_context(log, s, &ret->hContext, &index, &pbContextNdrPtr);
4857 if (status != SCARD_S_SUCCESS)
4858 return status;
4859
4860 status = smartcard_unpack_redir_scard_handle(log, s, &ret->hCard, &index);
4861 if (status != SCARD_S_SUCCESS)
4862 return status;
4863
4864 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4865 return STATUS_BUFFER_TOO_SMALL;
4866
4867 Stream_Read_UINT32(s, ret->dwActiveProtocol);
4868
4869 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &ret->hContext);
4870 if (status != SCARD_S_SUCCESS)
4871 return status;
4872
4873 status = smartcard_unpack_redir_scard_handle_ref(log, s, &ret->hCard);
4874 if (status != SCARD_S_SUCCESS)
4875 return status;
4876
4877 smartcard_trace_connect_return(log, ret);
4878 return SCARD_S_SUCCESS;
4879}
4880
4881LONG smartcard_unpack_control_return(wStream* s, Control_Return* ret)
4882{
4883 WINPR_ASSERT(ret);
4884 wLog* log = scard_log();
4885 UINT32 index = 0;
4886 UINT32 pvOutBufferNdrPtr = 0;
4887
4888 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4889 return STATUS_BUFFER_TOO_SMALL;
4890
4891 const UINT32 cbOutBufferSize = Stream_Get_UINT32(s);
4892
4893 if (!smartcard_ndr_pointer_read(log, s, &index, &pvOutBufferNdrPtr))
4894 return ERROR_INVALID_DATA;
4895
4896 if (pvOutBufferNdrPtr && (cbOutBufferSize > 0))
4897 {
4898 LONG status =
4899 smartcard_ndr_read(log, s, &ret->pvOutBuffer, cbOutBufferSize, 1, NDR_PTR_SIMPLE);
4900 if (status != SCARD_S_SUCCESS)
4901 return status;
4902 ret->cbOutBufferSize = cbOutBufferSize;
4903 }
4904 smartcard_trace_control_return(log, ret);
4905 return SCARD_S_SUCCESS;
4906}
4907
4908LONG smartcard_unpack_transmit_return(wStream* s, Transmit_Return* ret)
4909{
4910 WINPR_ASSERT(ret);
4911 wLog* log = scard_log();
4912 UINT32 index = 0;
4913 UINT32 recvPciNdrPtr = 0;
4914 UINT32 recvBufferNdrPtr = 0;
4915
4916 if (!smartcard_ndr_pointer_read(log, s, &index, &recvPciNdrPtr))
4917 return ERROR_INVALID_DATA;
4918
4919 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4920 return STATUS_BUFFER_TOO_SMALL;
4921
4922 const UINT32 cbRecvLength = Stream_Get_UINT32(s);
4923
4924 if (!smartcard_ndr_pointer_read(log, s, &index, &recvBufferNdrPtr))
4925 return ERROR_INVALID_DATA;
4926
4927 if (recvPciNdrPtr)
4928 {
4929 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
4930 return STATUS_BUFFER_TOO_SMALL;
4931
4932 UINT32 dwProtocol = 0;
4933 UINT32 cbExtraBytes = 0;
4934 Stream_Read_UINT32(s, dwProtocol);
4935 Stream_Read_UINT32(s, cbExtraBytes);
4936
4937 UINT32 pbExtraBytesNdrPtr = 0;
4938 if (!smartcard_ndr_pointer_read(log, s, &index, &pbExtraBytesNdrPtr))
4939 return ERROR_INVALID_DATA;
4940
4941 if (pbExtraBytesNdrPtr)
4942 {
4943 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
4944 return STATUS_BUFFER_TOO_SMALL;
4945
4946 UINT32 length = 0;
4947 Stream_Read_UINT32(s, length);
4948 if (length != cbExtraBytes)
4949 {
4950 WLog_Print(log, WLOG_WARN,
4951 "Transmit_Return unexpected length: Actual: %" PRIu32
4952 ", Expected: %" PRIu32 " (pioRecvPci.cbExtraBytes)",
4953 length, cbExtraBytes);
4954 return STATUS_INVALID_PARAMETER;
4955 }
4956
4957 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, cbExtraBytes))
4958 return STATUS_BUFFER_TOO_SMALL;
4959
4960 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
4961 if (!ret->pioRecvPci)
4962 return SCARD_E_NO_MEMORY;
4963
4964 ret->pioRecvPci->dwProtocol = dwProtocol;
4965 ret->pioRecvPci->cbPciLength = (DWORD)(sizeof(SCARD_IO_REQUEST) + cbExtraBytes);
4966
4967 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
4968 Stream_Read(s, pbExtraBytes, length);
4969 if (smartcard_unpack_read_size_align(s, cbExtraBytes, 4) < 0)
4970 return STATUS_INVALID_PARAMETER;
4971 }
4972 else
4973 {
4974 ret->pioRecvPci = (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST));
4975 if (!ret->pioRecvPci)
4976 return SCARD_E_NO_MEMORY;
4977
4978 ret->pioRecvPci->dwProtocol = dwProtocol;
4979 ret->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
4980 }
4981 }
4982
4983 if (recvBufferNdrPtr && (cbRecvLength > 0))
4984 {
4985 LONG status =
4986 smartcard_ndr_read(log, s, &ret->pbRecvBuffer, cbRecvLength, 1, NDR_PTR_SIMPLE);
4987 if (status != SCARD_S_SUCCESS)
4988 return status;
4989 ret->cbRecvLength = cbRecvLength;
4990 }
4991
4992 smartcard_trace_transmit_return(log, ret);
4993 return SCARD_S_SUCCESS;
4994}
4995
4996LONG smartcard_unpack_get_attrib_return(wStream* s, GetAttrib_Return* ret)
4997{
4998 WINPR_ASSERT(ret);
4999 wLog* log = scard_log();
5000 UINT32 index = 0;
5001 UINT32 pbAttrPtr = 0;
5002
5003 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
5004 return STATUS_BUFFER_TOO_SMALL;
5005
5006 const UINT32 cbAttrLen = Stream_Get_UINT32(s);
5007
5008 if (!smartcard_ndr_pointer_read(log, s, &index, &pbAttrPtr))
5009 return ERROR_INVALID_DATA;
5010
5011 LONG status = smartcard_ndr_read(log, s, &ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
5012 if (status != SCARD_S_SUCCESS)
5013 return status;
5014 ret->cbAttrLen = cbAttrLen;
5015
5016 smartcard_trace_get_attrib_return(log, ret, 0);
5017 return SCARD_S_SUCCESS;
5018}
Definition wtypes.h:263