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