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